function SWEP:NPC_PrimaryAttack() if !IsValid(self:GetOwner()) then return end local enemy = self:GetOwner():GetEnemy() local aps = self:GetValue("AmmoPerShot") if self:Clip1() < aps then if !IsValid(enemy) or !IsValid(enemy:GetActiveWeapon()) or table.HasValue({"weapon_crowbar", "weapon_stunstick"}, enemy:GetActiveWeapon():GetClass()) then // do not attempt to find cover if enemy does not have a ranged weapon self:GetOwner():SetSchedule(SCHED_RELOAD) else self:GetOwner():SetSchedule(SCHED_HIDE_AND_RELOAD) end return end self:SetBaseSettings() self:SetShouldHoldType() self.Primary.Automatic = true local pvar = self:GetValue("ShootPitchVariance") local sshoot = self:GetValue("Sound_Shoot") if self:GetValue("Silencer") then sshoot = self:GetValue("Sound_Shoot_Silenced") end if istable(sshoot) then sshoot = table.Random(sshoot) end self:EmitSound(sshoot, self:GetValue("Vol_Shoot"), self:GetValue("Pitch_Shoot") + math.Rand(-pvar, pvar), 1, CHAN_WEAPON) self:SetClip1(self:Clip1() - aps) local delay = 60 / self:GetValue("RPM") self:SetNextPrimaryFire(CurTime() + delay) if delay < 0.1 then self:GetOwner():NextThink(CurTime() + delay) // they will only attempt to fire once per think end local spread = self:GetNPCSpread() local dir = self:GetOwner():GetAimVector() if self:GetValue("ShootEnt") then if IsValid(enemy) then dir = (enemy:WorldSpaceCenter() - self:GetOwner():GetShootPos()):GetNormalized():Angle() dir = dir + ((spread + (0.1 / self:GetOwner():GetCurrentWeaponProficiency())) * AngleRand() / 3.6) end self:ShootRocket(dir) else self:GetOwner():FireBullets({ Damage = self:GetValue("Damage_Max"), Force = 8, TracerName = "tacrp_tracer", Tracer = self:GetValue("TracerNum"), Num = self:GetValue("Num"), Dir = dir, Src = self:GetOwner():GetShootPos(), Spread = Vector(spread, spread, spread), Callback = function(att, btr, dmg) local range = (btr.HitPos - btr.StartPos):Length() self:AfterShotFunction(btr, dmg, range, 0, {}) // self:GetValue("Penetration") if TacRP.Developer() then if SERVER then debugoverlay.Cross(btr.HitPos, 4, 5, Color(255, 0, 0), false) else debugoverlay.Cross(btr.HitPos, 4, 5, Color(255, 255, 255), false) end end end }) end self:DoEffects() self:DoEject() end function SWEP:GetNPCBulletSpread(prof) local mode = self:GetCurrentFiremode() if mode < 0 then return 10 / (prof + 1) elseif mode == 1 then if math.Rand(0, 100) < (prof + 5) * 5 then return 2 / (prof + 1) else return 20 / (prof + 1) end elseif mode > 1 then if math.Rand(0, 100) < (prof + 5) * 2 then return 5 / (prof + 1) else return 30 / (prof + 1) end end return 15 end function SWEP:GetNPCSpread() return self:GetValue("Spread") end function SWEP:GetNPCBurstSettings() local mode = self:GetCurrentFiremode() local delay = 60 / self:GetValue("RPM") if !mode then return 1, 1, delay 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.max(1, math.floor(c * math.Rand(0.15, 0.3))), delay + math.Rand(0.1, 0.2) elseif mode >= 2 then return math.min(self:Clip1(), 1 + math.floor(0.5 / delay)), math.min(self:Clip1(), 1 + math.floor(2 / delay)), delay end end function SWEP:GetNPCRestTimes() local mode = self:GetCurrentFiremode() local postburst = self:GetValue("PostBurstDelay") or 0 local m = self:GetValue("RecoilKick") local delay = 60 / self:GetValue("RPM") if !mode then return delay + 0.3, delay + 0.6 end local o = m > 1 and math.sqrt(m) or m if delay <= 60 / 90 then return delay + 0.1 * o, delay + 0.2 * o elseif mode < 0 then o = delay + o * 0.5 + postburst end return delay + 0.4 * o, delay + 0.6 * o end function SWEP:CanBePickedUpByNPCs() return self.NPCUsable end function SWEP:NPC_Reload() self:DropMagazine() end function SWEP:NPC_Initialize() if CLIENT then return end // auto attachment if TacRP.ConVars["npc_atts"]:GetBool() then for i, slot in pairs(self.Attachments) do local atts = TacRP.GetAttsForCats(slot.Category or "", self) local ind = math.random(0, #atts) if ind > 0 and math.random() <= 0.75 then slot.Installed = atts[ind] end end self:InvalidateCache() end timer.Simple(0.25, function() if !IsValid(self) then return end self:NetworkWeapon() end) self:SetBaseSettings() self:SetClip1(self:GetCapacity()) if math.random() <= 0.5 then self:SetFiremode(math.random(1, self:GetFiremodeAmount())) end end