Files
wnsrc/lua/arccw/server/sv_npc.lua
lifestorm 9c918c46e5 Upload
2024-08-04 23:12:27 +03:00

223 lines
7.4 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/
--]]
if CLIENT then return end
ArcCW.RandomWeaponCache = {}
hook.Add("PlayerSpawnedNPC", "ArcCW_PlayerSpawnedNPC", function( ply, ent )
net.Start("arccw_npcgiverequest")
net.Send(ply)
ply.ArcCW_LastSpawnedNPC = ent
end)
net.Receive("arccw_npcgivereturn", function(len, ply)
local class = net.ReadString()
local ent = ply.ArcCW_LastSpawnedNPC
if !ent then return end
if !IsValid(ent) then return end
if !ent:IsNPC() then return end
if !class then return end
local wpn = weapons.Get(class)
if wpn and wpn.AdminOnly and !ply:IsPlayer() then return end
if !ArcCW:WithinYearLimit(wpn) then
return
end
local cap = ent:CapabilitiesGet()
if bit.band(cap, CAP_USE_WEAPONS) != CAP_USE_WEAPONS then return end
if weapons.IsBasedOn(class, "arccw_base") and wpn.Spawnable and !wpn.NotForNPCs and (!wpn.AdminOnly or ply:IsAdmin()) then
ent:Give(class)
end
end)
function ArcCW:GetRandomWeapon(wpn)
local tbl = ArcCW.RandomWeaponCache[wpn] and ArcCW.RandomWeaponCache[wpn][2]
local wgt = ArcCW.RandomWeaponCache[wpn] and ArcCW.RandomWeaponCache[wpn][1] or 0
if !tbl then
tbl = {}
for i, k in pairs(weapons.GetList()) do
if !weapons.IsBasedOn(k.ClassName, "arccw_base") then continue end
if k.PrimaryBash then continue end
if !k.Spawnable then continue end
--if !nades and k.NotForNPCs then continue end -- what does nades do???
if k.AutoSpawnable == false then continue end
if !ArcCW:WithinYearLimit(k) then
continue
end
local weight = k.NPCWeight or 0
if engine.ActiveGamemode() == "terrortown" and k.TTTWeight then
weight = k.TTTWeight
end
if wpn and engine.ActiveGamemode() == "terrortown" and k.TTTWeaponType then -- TTT weapon type(s) take priority over NPC weapon types
if isstring(k.TTTWeaponType) then
if k.TTTWeaponType != wpn then continue end
elseif istable(k.TTTWeaponType) then
if !table.HasValue(k.TTTWeaponType, wpn) then continue end
end
elseif wpn and k.NPCWeaponType then
local class = wpn
if engine.ActiveGamemode() == "terrortown" and ArcCW.TTTReplaceTable[wpn] then
class = ArcCW.TTTReplaceTable[wpn]
end
if isstring(k.NPCWeaponType) then
if k.NPCWeaponType != class then continue end
elseif istable(k.NPCWeaponType) then
if !table.HasValue(k.NPCWeaponType, class) then continue end
end
else
local og = weapons.Get(wpn)
if og and og.ArcCW then continue end
weight = 0 -- Don't spawn if there is none of either
end
if weight > 0 then
-- Don't insert 0 weight, otherwise they still spawn
wgt = wgt + weight
table.insert(tbl, {k.ClassName, wgt})
end
end
ArcCW.RandomWeaponCache[wpn] = {wgt, tbl}
end
local r = math.random(0, wgt)
for _, i in pairs(tbl) do
if i[2] >= r then
return i[1]
end
end
end
hook.Add( "OnEntityCreated", "ArcCW_NPCWeaponReplacement", function(ent)
if CLIENT then return end
if ent:IsNPC() and ArcCW.ConVars["npc_replace"]:GetBool() then
timer.Simple(0, function()
if !ent:IsValid() then return end
local cap = ent:CapabilitiesGet()
if bit.band(cap, CAP_USE_WEAPONS) != CAP_USE_WEAPONS then return end
local class
if IsValid(ent:GetActiveWeapon()) then
class = ent:GetActiveWeapon():GetClass()
end
if !class then return end
local wpn
wpn = ArcCW:GetRandomWeapon(class)
if wpn then
ent:Give(wpn)
end
end)
elseif ent:IsWeapon() and ((engine.ActiveGamemode() == "terrortown" and ArcCW.ConVars["ttt_replace"]:GetBool()) or (engine.ActiveGamemode() != "terrortown" and ArcCW.ConVars["npc_replace"]:GetBool())) then
timer.Simple(0, function()
if !ent:IsValid() then return end
if IsValid(ent:GetOwner()) then return end
if ent.ArcCW then return end
local class = ent:GetClass()
local wpn = ArcCW:GetRandomWeapon(class)
if wpn then
local wpnent = ents.Create(wpn)
wpnent:SetPos(ent:GetPos())
wpnent:SetAngles(ent:GetAngles())
wpnent:NPC_Initialize()
wpnent:Spawn()
timer.Simple(0, function()
if !ent:IsValid() then return end
wpnent:OnDrop(true)
ent:Remove()
end)
end
end)
end
end)
-- This hook steals attachments from dropped weapons when a player walks over.
-- Disabled cause this is called CONSTANTLY when player is over a weapon, causing massive network lag.
-- Also it's just weird and hard to understand.
-- hook.Add("PlayerCanPickupWeapon", "ArcCW_PlayerCanPickupWeapon", function(ply, wep)
-- if !wep.ArcCW then return end
-- if !ply:HasWeapon(wep:GetClass()) then return end
-- if wep.Singleton then return false end
-- if !ArcCW.EnableCustomization or ArcCW.ConVars["enable_customization"]:GetInt() < 0 or ArcCW.ConVars["attinv_free"]:GetBool() then return end
-- for _, i in pairs(wep.Attachments) do
-- if i.Installed then
-- ArcCW:PlayerGiveAtt(ply, i.Installed)
-- end
-- i.Installed = nil
-- end
-- ArcCW:PlayerSendAttInv(ply)
-- wep:NetworkWeapon()
-- end)
hook.Add("onDarkRPWeaponDropped", "ArcCW_DarkRP", function(ply, spawned_weapon, wep)
if wep.ArcCW and wep.Attachments then
for i, k in pairs(wep.Attachments) do
if k.Installed then
ArcCW:PlayerGiveAtt(ply, k.Installed, 1)
end
end
-- Has to be sent to client or desync will happen
ArcCW:PlayerSendAttInv(ply)
end
end)
hook.Add("PlayerGiveSWEP", "ArcCW_SpawnRandomAttachments", function(ply, class, tbl)
if weapons.IsBasedOn(class, "arccw_base") and ArcCW.ConVars["atts_spawnrand"]:GetBool() then
-- We can't get the weapon entity here - it's spawned after the hook call.
-- Mark the player to disable autosave tempoarily if we're spawning random attachments.
ply.ArcCW_Sandbox_RandomAtts = true
timer.Simple(0.0001, function()
local wpn = ply:GetWeapon(class)
if IsValid(ply) and IsValid(wpn) then
wpn:NPC_SetupAttachments()
if ply.ArcCW_Sandbox_FirstSpawn then
wpn:RestoreAmmo()
ply.ArcCW_Sandbox_FirstSpawn = nil
end
end
end)
end
end)
hook.Add("PlayerSpawnedSWEP", "ArcCW_SpawnRandomAttachments", function(ply, wep)
if wep.ArcCW and ArcCW.ConVars["atts_spawnrand"]:GetBool() then
wep:NPC_SetupAttachments()
end
end)