Files
VnUtest/garrysmod/addons/tacrp/lua/weapons/tacrp_base/sh_npc.lua
2026-03-31 10:27:04 +03:00

188 lines
5.3 KiB
Lua

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