Files
wnsrc/lua/weapons/arccw_base/sv_npc.lua
lifestorm 6a58f406b1 Upload
2024-08-04 23:54:45 +03:00

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