This commit is contained in:
lifestorm
2024-08-05 18:40:29 +03:00
parent 9f505a0646
commit c6d9b6f580
8044 changed files with 1853472 additions and 21 deletions

View File

@@ -0,0 +1,40 @@
--[[
| 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
net.Receive("arccw_sendconvar", function(len, ply)
local command = net.ReadString()
if !ply:IsAdmin() then return end
if game.SinglePlayer() then return end
if string.sub(command, 1, 5) != "arccw" then return end
local cmds = string.Split(command, " ")
local timername = "change" .. cmds[1]
if timer.Exists(timername) then
timer.Remove(timername)
end
local args = {}
for i, k in pairs(cmds) do
if k == " " then continue end
k = string.Trim(k, " ")
table.insert(args, k)
end
timer.Create(timername, 0.25, 1, function()
RunConsoleCommand(args[1], args[2])
print("Changed " .. args[1] .. " to " .. args[2] .. ".")
end)
end)

View File

@@ -0,0 +1,27 @@
--[[
| 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
hook.Add("OnEntityCreated", "ArcCW_DefaultClip", function(ent)
if !ent.ArcCW then return end
if ArcCW.ConVars["mult_startunloaded"]:GetBool() then
ent.Primary.DefaultClip = 0
elseif ent.ForceDefaultClip then
ent.Primary.DefaultClip = ent.ForceDefaultClip
elseif ent.Primary.DefaultClip <= 0 then
ent.Primary.DefaultClip = ent.Primary.ClipSize
end
end)
hook.Add("PlayerCanPickupWeapon", "ArcCW_EquipmentSingleton", function(ply, wep)
if wep.ArcCW and wep.Throwing and wep.Singleton and ply:HasWeapon(wep:GetClass()) then return false end
end)

View File

@@ -0,0 +1,110 @@
--[[
| 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
function ArcCW.DoorBust(ent, vel)
local cvar = ArcCW.ConVars["doorbust"]:GetInt()
local t = ArcCW.ConVars["doorbust_time"]:GetFloat()
if cvar == 0 or ent.ArcCW_DoorBusted then return end
ent.ArcCW_DoorBusted = true
local oldSpeed = ent:GetInternalVariable("m_flSpeed")
ent:Fire("SetSpeed", tostring(oldSpeed * 5), 0)
ent:Fire("Open", "", 0)
ent:Fire("SetSpeed", oldSpeed, 0.3)
if ent:GetPhysicsObject():IsValid() and cvar == 1 then
-- Don't remove the door, that's a silly thing to do
ent.ArcCW_DoorOldPos = ent:GetPos()
ent:SetNoDraw(true)
ent:SetNotSolid(true)
-- Make a busted door prop and fling it
local prop = ents.Create("prop_physics")
prop:SetModel(ent:GetModel())
prop:SetPos(ent:GetPos())
prop:SetAngles(ent:GetAngles())
prop:SetSkin(ent:GetSkin())
prop:Spawn()
prop:GetPhysicsObject():SetVelocity(vel)
ent:SetPos(ent:GetPos() - Vector(0, 0, 10000))
-- Make it not collide with players after a bit cause that's annoying
timer.Create("ArcCW_DoorBust_" .. prop:EntIndex(), 2, 1, function()
if IsValid(prop) then
prop:SetCollisionGroup(COLLISION_GROUP_WEAPON)
end
end)
-- Reset it after a while
SafeRemoveEntityDelayed(prop, t)
timer.Create("ArcCW_DoorBust_" .. ent:EntIndex(), t, 1, function()
if IsValid(ent) then
ent:SetNoDraw(false)
ent:SetNotSolid(false)
ent.ArcCW_DoorBusted = false
ent:SetPos(ent.ArcCW_DoorOldPos)
ent.ArcCW_DoorOldPos = nil
end
end)
else
timer.Create("ArcCW_DoorBust_" .. ent:EntIndex(), 0.5, 1, function()
if IsValid(ent) then
ent.ArcCW_DoorBusted = false
end
end)
end
end
function ArcCW.TryBustDoor(ent, dmginfo)
if ArcCW.ConVars["doorbust"]:GetInt() == 0 or !IsValid(ent) or !string.find(ent:GetClass(), "door") then return end
local wep = IsValid(dmginfo:GetAttacker()) and ((dmginfo:GetInflictor():IsWeapon() and dmginfo:GetInflictor()) or dmginfo:GetAttacker():GetActiveWeapon())
if !wep or !wep:IsWeapon() or !wep.ArcCW or !dmginfo:IsDamageType(DMG_BUCKSHOT) then return end
if ent:GetNoDraw() or ent.ArcCW_NoBust or ent.ArcCW_DoorBusted then return end
--- TTT may choose for some doors to not be openable by a crowbar, let's respect that
if GAMEMODE.crowbar_unlocks and GAMEMODE.crowbar_unlocks[ent] != true then return end
-- Magic number: 119.506 is the size of door01_left
-- The bigger the door is, the harder it is to bust
local threshold = ArcCW.ConVars["doorbust_threshold"]:GetInt() * math.pow((ent:OBBMaxs() - ent:OBBMins()):Length() / 119.506, 2)
-- Because shotgun damage is done per pellet, we must count them together
if ent.ArcCW_BustCurTime and (ent.ArcCW_BustCurTime + 0.1 < CurTime()) then
ent.ArcCW_BustCurTime = nil
ent.ArcCW_BustDamage = 0
end
if dmginfo:GetDamage() < (threshold - (ent.ArcCW_BustDamage or 0)) then
ent.ArcCW_BustCurTime = ent.ArcCW_BustCurTime or CurTime()
ent.ArcCW_BustDamage = (ent.ArcCW_BustDamage or 0) + dmginfo:GetDamage()
return
else
ent.ArcCW_BustCurTime = nil
ent.ArcCW_BustDamage = nil
end
ArcCW.DoorBust(ent, dmginfo:GetDamageForce() * 0.5)
-- Double doors are usually linked to the same areaportal. We must destroy the second half of the double door no matter what
for _, otherDoor in pairs(ents.FindInSphere(ent:GetPos(), 64)) do
if ent != otherDoor and otherDoor:GetClass() == ent:GetClass() and !otherDoor:GetNoDraw() then
ArcCW.DoorBust(otherDoor, dmginfo:GetDamageForce() * 0.5)
break
end
end
end
hook.Add("PlayerUse", "ArcCW_DoorBust", function(ply, ent)
if ent.ArcCW_DoorBusted then return false end
end)
-- This hook is not called on brush doors. Let's call this, uhh, intended behavior.
-- hook.Add("EntityTakeDamage", "ArcCW_DoorBust", ArcCW.TryBustDoor)

View File

@@ -0,0 +1,39 @@
--[[
| 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.ShieldPropPile = {} -- { {Model = NULL, Weapon = NULL} }
local function SV_ArcCW_CollectGarbage()
local removed = 0
local newpile = {}
for _, k in pairs(ArcCW.ShieldPropPile) do
if IsValid(k.Weapon) then
table.insert(newpile, k)
continue
end
SafeRemoveEntity(k.Model)
removed = removed + 1
end
ArcCW.ShieldPropPile = newpile
if GetConVar("developer"):GetBool() and removed > 0 then
print("Removed " .. tostring(removed) .. " Shield Models")
end
end
timer.Create("ArcCW Shield Model Garbage Collector", 5, 0, SV_ArcCW_CollectGarbage)

View File

@@ -0,0 +1,50 @@
--[[
| 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
if game.SinglePlayer() then
util.AddNetworkString("arccw_sp_lhikanim")
util.AddNetworkString("arccw_sp_anim")
util.AddNetworkString("arccw_sp_health")
util.AddNetworkString("arccw_sp_checkpoints")
end
util.AddNetworkString("arccw_sendattinv")
util.AddNetworkString("arccw_slidepos")
util.AddNetworkString("arccw_colorindex")
util.AddNetworkString("arccw_asktoattach")
util.AddNetworkString("arccw_asktodetach")
util.AddNetworkString("arccw_asktodrop")
util.AddNetworkString("arccw_networkatts")
util.AddNetworkString("arccw_firemode")
util.AddNetworkString("arccw_quicknade")
util.AddNetworkString("arccw_togglecustomize")
util.AddNetworkString("arccw_ubgl")
util.AddNetworkString("arccw_npcgiverequest")
util.AddNetworkString("arccw_npcgivereturn")
util.AddNetworkString("arccw_rqwpnnet")
util.AddNetworkString("arccw_blacklist")
util.AddNetworkString("arccw_sendatthp")
util.AddNetworkString("arccw_reloadatts")
util.AddNetworkString("arccw_sendbullet")
util.AddNetworkString("arccw_sendconvar")
util.AddNetworkString("arccw_applypreset")
util.AddNetworkString("arccw_ttt_bodyattinfo")
util.AddNetworkString("arccw_networksound")
util.AddNetworkString("arccw_togglenum")
util.AddNetworkString("arccw_networktpanim")

223
lua/arccw/server/sv_npc.lua Normal file
View File

@@ -0,0 +1,223 @@
--[[
| 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)

View File

@@ -0,0 +1,20 @@
--[[
| 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
-- We have to do a timer because there is no "PlayerGivenSWEP" or similar
hook.Add("PlayerGiveSWEP", "ArcCW_Autoload", function(ply, class, tbl)
local weptbl = weapons.Get(class)
if not weptbl or not weptbl.ArcCW then return end
-- Mark the player's next weapon to get ammo restore
ply.ArcCW_Sandbox_FirstSpawn = true
end)

View File

@@ -0,0 +1,22 @@
--[[
| 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 or !game.SinglePlayer() then return end
hook.Add("EntityTakeDamage", "ArcCW_ETD", function(npc, dmg)
timer.Simple(0, function()
if !IsValid(npc) then return end
if npc:Health() <= 0 then
net.Start("arccw_sp_health")
net.WriteEntity(npc)
net.Broadcast()
end
end)
end)

View File

@@ -0,0 +1,98 @@
--[[
| 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.NPCsCache = ArcCW.NPCsCache or {}
local npcs = ArcCW.NPCsCache
ArcCW.SmokeCache = ArcCW.SmokeCache or {}
local smokes = ArcCW.SmokeCache
hook.Add("OnEntityCreated", "ArcCW_NPCSmokeCache", function(ent)
if !ent:IsValid() then return end
if ent:IsNPC() then
npcs[#npcs + 1] = ent
elseif ent.ArcCWSmoke then
smokes[#smokes + 1] = ent
end
end)
hook.Add("EntityRemoved", "ArcCW_NPCSmokeCache", function(ent)
if ent:IsNPC() then
table.RemoveByValue(npcs, ent)
elseif ent.ArcCWSmoke then
table.RemoveByValue(smokes, ent)
end
end)
function ArcCW:ProcessNPCSmoke()
if #npcs == 0 or #smokes == 0 then return end
for _, npc in ipairs(npcs) do
local target = npc:GetEnemy()
if !target or !target:IsValid() then continue end
npc.ArcCW_Smoked_Time = npc.ArcCW_Smoked_Time or 0
if npc.ArcCW_Smoked_Time > CurTime() then
if npc.ArcCW_Smoked then
if npc.ArcCW_Smoked_Target == target then
npc:SetSchedule(SCHED_STANDOFF)
debugoverlay.Cross(npc:EyePos(), 5, 0.1, Color(50, 0, 0), true)
continue
end
elseif npc.ArcCW_Smoked_Target != target then
if npc.ArcCW_Smoked then
npc:SetSchedule(SCHED_IDLE_STAND)
end
npc.ArcCW_Smoked = false
else
continue
end
else
npc.ArcCW_Smoked = false
end
local sr = 256
local maxs = Vector(sr, sr, sr)
local mins = -maxs
local rayEnts = ents.FindAlongRay(npc:EyePos(), target:WorldSpaceCenter(), mins, maxs)
local anysmoke = false
for _, i in ipairs(rayEnts) do
if i.ArcCWSmoke then
anysmoke = true
break
end
end
if anysmoke then
-- print("Smoke!")
npc.ArcCW_Smoked = true
npc.ArcCW_Smoked_Target = target
npc:SetSchedule(SCHED_STANDOFF)
debugoverlay.Line(npc:EyePos(), target:WorldSpaceCenter(), 1, Color(50, 0, 0), true)
else
if npc.ArcCW_Smoked then
npc:SetSchedule(SCHED_IDLE_STAND)
end
npc.ArcCW_Smoked = false
end
npc.ArcCW_Smoked_Time = CurTime() + 1
end
end
hook.Add("Think", "ArcCW_NPCSmoke", ArcCW.ProcessNPCSmoke)

View File

@@ -0,0 +1,39 @@
--[[
| 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
hook.Add("EntityTakeDamage", "ArcCW_DoAttDMG", function(ent, dmg)
if !ent:IsPlayer() then return end
local wpn = ent:GetActiveWeapon()
if !wpn.ArcCW then return end
for i, k in pairs(wpn.Attachments) do
if !k.Installed then continue end
local atttbl = ArcCW.AttachmentTable[k.Installed]
if atttbl.Hook_PlayerTakeDamage then
atttbl.Hook_PlayerTakeDamage(wpn, {slot = i, atthp = k.HP, dmg = dmg})
end
end
wpn:SendAttHP()
end)
hook.Add("DoPlayerDeath","ArcCW_GrenadeDrop",function(ply)
local wep = ply:GetActiveWeapon()
if !(wep.ArcCW and wep.Throwing) then return end
if wep:GetGrenadePrimed() then
wep:GrenadeDrop()
end
end)

View File

@@ -0,0 +1,36 @@
--[[
| 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
hook.Add( "PlayerGiveSWEP", "ArcCW_YearLimiter", function( ply, class, swep )
local wep = weapons.Get(class)
if !ArcCW:WithinYearLimit(wep) then
ply:ChatPrint( wep.PrintName .. " is outside the year limit!")
return false
end
end )
function ArcCW:WithinYearLimit(wep)
if !wep then return true end
if !wep.ArcCW then return true end
if !ArcCW.ConVars["limityear_enable"]:GetBool() then return true end
local year = ArcCW.ConVars["limityear"]:GetInt()
if !wep.Trivia_Year then return true end
if !isnumber(wep.Trivia_Year) then return true end
if wep.Trivia_Year > year then return false end
return true
end