mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 21:53:46 +03:00
415 lines
12 KiB
Lua
415 lines
12 KiB
Lua
--[[
|
|
| This file was obtained through the combined efforts
|
|
| of Madbluntz & Plymouth Antiquarian Society.
|
|
|
|
|
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
|
| Maloy, DrPepper10 @ RIP, Atle!
|
|
|
|
|
| Visit for more: https://plymouth.thetwilightzone.ru/
|
|
--]]
|
|
|
|
-- NPC integration
|
|
|
|
function SWEP:NPC_Initialize()
|
|
if CLIENT then return end
|
|
|
|
if !IsValid(self:GetOwner()) then return end
|
|
if !self:GetOwner():IsNPC() then return end
|
|
|
|
self:NPC_SetupAttachments()
|
|
|
|
self:SetHoldType(self.HoldtypeNPC or self:GetBuff_Override("Override_HoldtypeActive") or self.HoldtypeActive)
|
|
|
|
self:SetNextPrimaryFire(CurTime())
|
|
|
|
self:SetClip1(self:GetCapacity() or self.Primary.ClipSize)
|
|
|
|
-- print(self:Clip1())
|
|
|
|
local range = self:GetBuff("Range") / ArcCW.HUToM
|
|
|
|
if self:GetBuff("DamageMin") >= self:GetBuff("Damage") or (self:GetBuff_Override("Override_ManualAction") or self.ManualAction) and self:GetBuff("Num") == 1 then
|
|
range = math.max(range, 10000) * 2
|
|
end
|
|
|
|
range = math.Clamp(range, 2048, 36000)
|
|
|
|
self:GetOwner():Input("SetMaxLookDistance", nil, nil, range)
|
|
|
|
self:SetNextPrimaryFire(CurTime())
|
|
self:SetNextSecondaryFire(CurTime() + 30)
|
|
self:GetOwner():NextThink(CurTime())
|
|
end
|
|
|
|
function SWEP:AssignRandomAttToSlot(slot)
|
|
if slot.DoNotRandomize then return end
|
|
if slot.Installed then return end
|
|
|
|
local att = ArcCW:RollRandomAttachment(true, self, slot)
|
|
if !att then return end
|
|
slot.Installed = att
|
|
|
|
local atttbl = ArcCW.AttachmentTable[slot.Installed]
|
|
|
|
--if !ArcCW:SlotAcceptsAtt(slot.Slot, self, slot.Installed) then return end
|
|
--if !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then return end
|
|
|
|
if atttbl.MountPositionOverride then
|
|
slot.SlidePos = atttbl.MountPositionOverride
|
|
end
|
|
end
|
|
|
|
function SWEP:NPC_SetupAttachments()
|
|
if self:GetOwner():IsNPC() and !ArcCW.ConVars["npc_atts"]:GetBool() then return end
|
|
|
|
local pick = self:GetPickX()
|
|
|
|
local chance = 25 * ArcCW.ConVars["mult_attchance"]:GetFloat()
|
|
local chancestep = 0
|
|
|
|
if pick > 0 then
|
|
chancestep = chance / pick
|
|
--chance = chancestep
|
|
else
|
|
pick = 1000
|
|
end
|
|
|
|
local n = 0
|
|
|
|
for i, slot in pairs(self.Attachments) do
|
|
if n > pick then continue end
|
|
if !self:CheckFlags(slot.ExcludeFlags, slot.RequireFlags) then continue end
|
|
if math.Rand(0, 100) > (chance * (slot.RandomChance or 1)) then continue end
|
|
|
|
if slot.Hidden then continue end
|
|
|
|
local s = i
|
|
|
|
if slot.MergeSlots then
|
|
local ss = {i}
|
|
table.Add(ss, slot.MergeSlots)
|
|
|
|
s = table.Random(ss) or i
|
|
end
|
|
if !self.Attachments[s] then s = i end
|
|
|
|
chance = chance - chancestep
|
|
|
|
self:AssignRandomAttToSlot(self.Attachments[s])
|
|
|
|
n = n + 1
|
|
end
|
|
|
|
self.ActiveElementCache = nil -- Reset cache so we have the proper attachments to check with
|
|
for i, slot in pairs(self.Attachments) do
|
|
if !slot.Installed then continue end
|
|
local atttbl = ArcCW.AttachmentTable[slot.Installed]
|
|
if !ArcCW:SlotAcceptsAtt(slot.Slot, self, slot.Installed) then slot.Installed = nil continue end
|
|
if !self:CheckFlags(slot.ExcludeFlags, slot.RequireFlags) then slot.Installed = nil continue end
|
|
if !self:CheckFlags(atttbl.ExcludeFlags, atttbl.RequireFlags) then slot.Installed = nil continue end
|
|
end
|
|
|
|
if self:GetBuff_Override("UBGL") and self:GetBuff_Override("UBGL_Capacity") then
|
|
self:SetClip2(self:GetBuff_Override("UBGL_Capacity"))
|
|
end
|
|
|
|
self:AdjustAtts()
|
|
self:RefreshBGs()
|
|
|
|
if self:GetOwner():IsNPC() then
|
|
timer.Simple(0.1, function()
|
|
if !IsValid(self) then return end
|
|
self:NetworkWeapon()
|
|
end)
|
|
else
|
|
self:NetworkWeapon()
|
|
self:SetupModel(false)
|
|
self:SetupModel(true)
|
|
end
|
|
end
|
|
|
|
function SWEP:NPC_Shoot()
|
|
-- if self:GetNextPrimaryFire() > CurTime() then return end
|
|
|
|
if !IsValid(self:GetOwner()) then return end
|
|
if self:Clip1() <= 0 then self:GetOwner():SetSchedule(SCHED_HIDE_AND_RELOAD) return end
|
|
|
|
if self:GetOwner().ArcCW_Smoked then return end
|
|
|
|
|
|
self.Primary.Automatic = true
|
|
|
|
|
|
local delay = self:GetFiringDelay()
|
|
|
|
if (self:GetBuff_Override("Override_ManualAction") or self.ManualAction) then
|
|
delay = self:GetAnimKeyTime("cycle", true) * self:GetBuff("CycleTime")
|
|
end
|
|
|
|
local num = self:GetBuff("Num")
|
|
|
|
if num > 0 then
|
|
local spread = ArcCW.MOAToAcc * self:GetBuff("AccuracyMOA")
|
|
|
|
local btabl = {
|
|
Attacker = self:GetOwner(),
|
|
Damage = 0,
|
|
Force = 1,
|
|
Distance = 33000,
|
|
Num = num,
|
|
Tracer = self.TracerNum,
|
|
AmmoType = self.Primary.Ammo,
|
|
Dir = self:GetOwner():GetAimVector(),
|
|
Src = self:GetShootSrc(),
|
|
Spread = Vector(spread, spread, spread),
|
|
Callback = function(att, tr, dmg)
|
|
ArcCW:BulletCallback(att, tr, dmg, self)
|
|
end,
|
|
--[[]
|
|
Callback = function(att, tr, dmg)
|
|
local dist = (tr.HitPos - tr.StartPos):Length() * ArcCW.HUToM
|
|
|
|
local pen = self:GetBuff("Penetration")
|
|
|
|
-- local frags = math.random(1, self.Frangibility)
|
|
|
|
-- for i = 1, frags do
|
|
-- self:DoPenetration(tr, (self.Penetration / frags) - 0.5, tr.Entity)
|
|
-- end
|
|
|
|
if self.DamageMin > self.Damage then
|
|
dist = -dist + self.Range + self.Range
|
|
end
|
|
|
|
local m = 1 * self:GetBuff_Mult("Mult_DamageNPC")
|
|
|
|
local ret = self:GetBuff_Hook("Hook_BulletHit", {
|
|
range = dist,
|
|
damage = self:GetDamage(dist, true) * m,
|
|
dmgtype = self:GetBuff_Override("Override_DamageType") or self.DamageType,
|
|
penleft = pen,
|
|
att = att,
|
|
tr = tr,
|
|
dmg = dmg
|
|
})
|
|
|
|
if !ret then return end
|
|
|
|
dmg:SetDamageType(ret.dmgtype)
|
|
dmg:SetDamage(ret.damage)
|
|
|
|
if dmg:IsDamageType(DMG_BURN) and hit.range <= self.Range then
|
|
dmg:SetDamageType(dmg:GetDamageType() - DMG_BURN)
|
|
|
|
local fx = EffectData()
|
|
fx:SetOrigin(tr.HitPos)
|
|
util.Effect("arccw_incendiaryround", fx)
|
|
|
|
util.Decal("FadingScorch", tr.StartPos, tr.HitPos - (tr.HitNormal * 16), self:GetOwner())
|
|
|
|
tr.Entity:Ignite(1, 32)
|
|
end
|
|
end
|
|
]]
|
|
}
|
|
|
|
local sp = self:GetBuff_Override("Override_ShotgunSpreadPattern") or self.ShotgunSpreadPattern
|
|
local spo = self:GetBuff_Override("Override_ShotgunSpreadPatternOverrun") or self.ShotgunSpreadPatternOverrun
|
|
local se = self:GetBuff_Override("Override_ShootEntity") or self.ShootEntity
|
|
|
|
if sp or spo then
|
|
btabl = self:GetBuff_Hook("Hook_FireBullets", btabl)
|
|
|
|
if !btabl then return end
|
|
if btabl.Num == 0 then return end
|
|
|
|
for n = 1, btabl.Num do
|
|
btabl.Num = 1
|
|
local ang = self:GetOwner():GetAimVector():Angle() + self:GetShotgunSpreadOffset(n)
|
|
|
|
btabl.Dir = ang:Forward()
|
|
|
|
self:DoPrimaryFire(false, btabl)
|
|
end
|
|
elseif se then
|
|
self:FireRocket(se, self:GetBuff("MuzzleVelocity"))
|
|
else
|
|
self:GetBuff_Hook("Hook_FireBullets", btabl)
|
|
|
|
for n = 1, btabl.Num do
|
|
btabl.Num = 1
|
|
|
|
local dispers = self:GetBuff_Override("Override_ShotgunSpreadDispersion", self.ShotgunSpreadDispersion)
|
|
local offset = self:GetShotgunSpreadOffset(n)
|
|
local calcoff = dispers and (offset * self:GetDispersion() * ArcCW.MOAToAcc / 10) or offset
|
|
|
|
local ang = self:GetOwner():GetAimVector():Angle()
|
|
-- ang:RotateAroundAxis(ang:Right(), -1 * calcoff.p)
|
|
-- ang:RotateAroundAxis(ang:Up(), calcoff.y)
|
|
-- ang:RotateAroundAxis(ang:Forward(), calcoff.r)
|
|
|
|
btabl.Dir = ang:Forward()
|
|
|
|
self:DoPrimaryFire(false, btabl)
|
|
end
|
|
end
|
|
end
|
|
|
|
self:DoEffects()
|
|
|
|
if !self.RevolverReload then
|
|
self:DoShellEject()
|
|
end
|
|
|
|
--[[]
|
|
local ss = self.ShootSound
|
|
|
|
if self:GetBuff_Override("Silencer") then
|
|
ss = self.ShootSoundSilenced
|
|
end
|
|
|
|
ss = self:GetBuff_Hook("Hook_GetShootSound", ss)
|
|
|
|
local dss = self.DistantShootSound
|
|
|
|
if self:GetBuff_Override("Silencer") then
|
|
dss = nil
|
|
end
|
|
|
|
dss = self:GetBuff_Hook("Hook_GetDistantShootSound", dss)
|
|
|
|
local svol = self:GetBuff("ShootVol")
|
|
local spitch = self.ShootPitch * math.Rand(0.95, 1.05) * self:GetBuff_Mult("Mult_ShootPitch")
|
|
|
|
svol = svol * 0.75
|
|
|
|
svol = math.Clamp(svol, 51, 149)
|
|
spitch = math.Clamp(spitch, 51, 149)
|
|
|
|
if dss then
|
|
-- sound.Play(self.DistantShootSound, self:GetPos(), 149, self.ShootPitch * math.Rand(0.95, 1.05), 1)
|
|
self:MyEmitSound(dss, 130, spitch, 0.5, CHAN_BODY)
|
|
end
|
|
|
|
if ss then
|
|
self:MyEmitSound(ss, svol, spitch, 1, CHAN_WEAPON)
|
|
end
|
|
]]
|
|
|
|
self:DoShootSound()
|
|
|
|
self:SetClip1(self:Clip1() - 1)
|
|
|
|
self:SetNextPrimaryFire(CurTime() + delay)
|
|
if delay < 0.1 then
|
|
self:GetOwner():NextThink(CurTime() + delay)
|
|
end
|
|
|
|
if self:GetBuff_Override("UBGL_NPCFire") and self:GetNextSecondaryFire() < CurTime() then
|
|
if math.random(0, 100) < (self:GetOwner():GetCurrentWeaponProficiency() + 1) then
|
|
self:SetNextSecondaryFire(CurTime() + math.random(3, 5))
|
|
else
|
|
local func = self:GetBuff_Override("UBGL_NPCFire")
|
|
if func then
|
|
func(self)
|
|
end
|
|
if self:Clip2() == 0 then
|
|
self:SetClip2(self.Secondary.ClipSize)
|
|
self:SetNextSecondaryFire(CurTime() + math.random(300, 600) / (self:GetOwner():GetCurrentWeaponProficiency() + 1))
|
|
else
|
|
self:SetNextSecondaryFire(CurTime() + 1 / ((self:GetBuff_Override("UBGL_RPM") or 300) / 60))
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
function SWEP:GetNPCBulletSpread(prof)
|
|
local mode = self:GetCurrentFiremode()
|
|
mode = mode.Mode
|
|
|
|
if mode < 0 then
|
|
return 15 / (prof + 1)
|
|
elseif mode == 1 then
|
|
if math.Rand(0, 100) < (prof + 5) * 5 then
|
|
return 5 / (prof + 1)
|
|
else
|
|
return 30 / (prof + 1)
|
|
end
|
|
elseif mode > 1 then
|
|
if math.Rand(0, 100) < (prof + 5) * 2 then
|
|
return 15 / (prof + 1)
|
|
else
|
|
return (20 + self:GetBuff("Recoil") * 10) / (prof + 1)
|
|
end
|
|
|
|
end
|
|
|
|
return 15
|
|
end
|
|
|
|
function SWEP:GetNPCBurstSettings()
|
|
local mode = self:GetCurrentFiremode()
|
|
mode = mode.Mode
|
|
|
|
local delay = self:GetFiringDelay()
|
|
|
|
if !mode then return 1, 1, delay end
|
|
|
|
if self.ManualAction or self:GetBuff_Override("Override_ManualAction") then
|
|
return 1, 1, self:GetAnimKeyTime("cycle") * self:GetBuff("CycleTime")
|
|
end
|
|
|
|
if mode < 0 then
|
|
return -mode, -mode, delay
|
|
elseif mode == 0 then
|
|
return 0, 0, delay
|
|
elseif mode == 1 then
|
|
local c = self:GetCapacity()
|
|
return math.ceil(c * 0.075), math.floor(c * math.Rand(0.15, 0.3)), delay + math.Rand(0.2, 0.4)
|
|
elseif mode >= 2 then
|
|
if self:GetCurrentFiremode().RunawayBurst then
|
|
return self:Clip1(), self:Clip1(), delay
|
|
else
|
|
return 2, math.floor(2.5 / delay), delay
|
|
end
|
|
end
|
|
end
|
|
|
|
function SWEP:GetNPCRestTimes()
|
|
local mode = self:GetCurrentFiremode()
|
|
mode = mode.Mode
|
|
local postburst = self:GetCurrentFiremode().PostBurstDelay or 0
|
|
local m = self:GetBuff("Recoil")
|
|
local rs = self:GetBuff("RecoilSide")
|
|
|
|
if !mode then return 0.3, 0.6 end
|
|
|
|
local o = m * 0.3 + rs * 0.15
|
|
if self.ManualAction or self:GetBuff_Override("Override_ManualAction") then
|
|
local cycle = self:GetAnimKeyTime("cycle") * self:GetBuff("CycleTime")
|
|
return cycle + 0.1 * o, cycle + 0.2 * o
|
|
elseif mode < 0 then
|
|
o = o * 0.5 + postburst * self:GetBuff("PostBurstDelay")
|
|
end
|
|
|
|
return 0.4 * o, 0.6 * o
|
|
end
|
|
|
|
function SWEP:CanBePickedUpByNPCs()
|
|
return !self.NotForNPCs
|
|
end
|
|
|
|
function SWEP:OnDrop()
|
|
self.Primary.DefaultClip = 0
|
|
|
|
if self.Singleton or self.Primary.ClipSize == -1 then
|
|
self.Primary.DefaultClip = 1
|
|
end
|
|
|
|
self.UnReady = false
|
|
-- if engine.ActiveGamemode() == "terrortown" then
|
|
-- self.UnReady = true
|
|
-- else
|
|
-- self.UnReady = false
|
|
-- end
|
|
end |