--[[ | 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