Clear crippled and near-death enemies, various optimizations

This commit is contained in:
toasterpanic 2026-05-26 23:21:18 -04:00
parent 8da450edb3
commit 85eb62a495
3 changed files with 115 additions and 72 deletions

View file

@ -44,6 +44,12 @@ local function PopulatePerformanceSBXToolMenu(pnl)
pnl:CheckBox("Never remove corpses near the player", "zcnpci_disable_corpse_removal_near_player") pnl:CheckBox("Never remove corpses near the player", "zcnpci_disable_corpse_removal_near_player")
pnl:ControlHelp("If on, corpses under the variable above in distance will never be cleared.") pnl:ControlHelp("If on, corpses under the variable above in distance will never be cleared.")
pnl:CheckBox("Treat crippled NPCs as dead", "zcnpci_treat_crippled_as_dead")
pnl:ControlHelp("If on, corpses with amputations or both legs broken will be clearable.")
pnl:CheckBox("Treat near-death NPCs as dead", "zcnpci_treat_near_death_as_dead")
pnl:ControlHelp("If on, corpses near death (severe blood loss, comas, etc.) will be clearable.")
end end
if engine.ActiveGamemode() == "sandbox" then if engine.ActiveGamemode() == "sandbox" then

View file

@ -9,6 +9,10 @@ local max_corpses = CreateConVar("zcnpci_max_corpses", 8, bit.bor(FCVAR_ARC
local max_corpse_time = CreateConVar("zcnpci_max_corpse_time", 120, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) local max_corpse_time = CreateConVar("zcnpci_max_corpse_time", 120, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local max_corpse_distance = CreateConVar("zcnpci_max_corpse_distance", 2500, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) local max_corpse_distance = CreateConVar("zcnpci_max_corpse_distance", 2500, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local no_corpse_removal_near_player = CreateConVar("zcnpci_disable_corpse_removal_near_player", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) local no_corpse_removal_near_player = CreateConVar("zcnpci_disable_corpse_removal_near_player", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local treat_crippled_as_dead = CreateConVar("zcnpci_treat_crippled_as_dead", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local treat_near_death_as_dead = CreateConVar("zcnpci_treat_near_death_as_dead", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local debug_ragdoll_all = CreateConVar("zcnpci_debug_ragdoll_all", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED, FCVAR_PROTECTED))
local last_dmgpos = {} local last_dmgpos = {}
local last_hitgroup = {} local last_hitgroup = {}
@ -16,6 +20,9 @@ local last_attacker = {}
local corpses = {} local corpses = {}
local last_corpse_tick = CurTime()
local last_tick = CurTime()
hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll) hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll)
if !ent.organism then return end if !ent.organism then return end
@ -83,6 +90,13 @@ hook.Add("ScaleNPCDamage", "zcnpci", function(npc, hitgroup, dmginfo)
end) end)
hook.Add("Think", "zcnpci", function() hook.Add("Think", "zcnpci", function()
local do_corpse_loop = (CurTime() - last_corpse_tick) > 2.0
local do_general_loop = (CurTime() - last_tick) > 0.1
if do_general_loop then
if do_corpse_loop then
last_corpse_tick = CurTime()
for i, ent in pairs(corpses) do for i, ent in pairs(corpses) do
if !IsValid(ent) then if !IsValid(ent) then
table.RemoveByValue(corpses, ent) table.RemoveByValue(corpses, ent)
@ -96,6 +110,7 @@ hook.Add("Think", "zcnpci", function()
table.remove(corpses, 1) table.remove(corpses, 1)
end end
end
for i, ent in pairs(ents.GetAll()) do for i, ent in pairs(ents.GetAll()) do
if !IsValid(ent) then continue end if !IsValid(ent) then continue end
@ -109,7 +124,8 @@ hook.Add("Think", "zcnpci", function()
ent.organism.rlegamputated or ent.organism.rlegamputated or
(ent.organism.consciousness <= 0.3) or (ent.organism.consciousness <= 0.3) or
(ent.organism.pain > 90) or (ent.organism.pain > 90) or
ent:IsOnFire() ent:IsOnFire() or
debug_ragdoll_all:GetBool()
) then ) then
local damage_info = DamageInfo() local damage_info = DamageInfo()
damage_info:SetDamage(ent:Health()) damage_info:SetDamage(ent:Health())
@ -119,7 +135,24 @@ hook.Add("Think", "zcnpci", function()
ent:TakeDamageInfo(damage_info) ent:TakeDamageInfo(damage_info)
end end
elseif !ent.organism.alive and remove_corpses and ent.is_npc_corpse then elseif do_corpse_loop and remove_corpses and ent.is_npc_corpse then
local clearable = false
if !ent.organism.alive then clearable = true end
if treat_crippled_as_dead:GetBool() and (
ent.organism.llegamputated or ent.organism.rlegamputated or ent.organism.larmamputated or ent.organism.rarmamputated or
((ent.organism.lleg >= 1) and (ent.organism.rleg >= 1))
) then clearable = true end
if treat_near_death_as_dead:GetBool() and (
ent.organism.heartstop or
(ent.organism.brain > 0.6) or
!ent.organism.lungsfunction or
(ent.organism.blood < 3000) or
(ent.organism.pulse < 10)
) then clearable = true end
if !clearable then return end
-- Add to corpse list if not there already -- Add to corpse list if not there already
if !table.HasValue(corpses, ent) then if !table.HasValue(corpses, ent) then
table.insert(corpses, ent) table.insert(corpses, ent)
@ -156,6 +189,8 @@ hook.Add("Think", "zcnpci", function()
end end
end end
end end
end
end) end)
--[[hook.Add("OnNPCKilled", "Fedhoria", function(ent, attacker, inflictor) --[[hook.Add("OnNPCKilled", "Fedhoria", function(ent, attacker, inflictor)

View file

@ -161,6 +161,8 @@ function MODULE:Init()
self.StartDie = nil self.StartDie = nil
self.AnimationRollEndTime = 0 self.AnimationRollEndTime = 0
self.StopProcessing = false self.StopProcessing = false
self.LastThink = CurTime()
self.LastPhysProcess = CurTime()
-- Add damping to all bones. -- Add damping to all bones.
local phys = self:GetPhysicsObject() local phys = self:GetPhysicsObject()
@ -184,14 +186,14 @@ end
---------------------------------------------------------------------------]] ---------------------------------------------------------------------------]]
function MODULE:Think() function MODULE:Think()
if (CurTime() - self.LastThink) < 1 then return end
if !IsValid(target) then return end if !IsValid(target) then return end
print("target is valid") self.LastThink = CurTime()
local phys = target:GetPhysicsObject() local phys = target:GetPhysicsObject()
if !IsValid(phys) or !phys:IsAsleep() then return end
print("phys is valid") if !IsValid(phys) or !phys:IsAsleep() then return end
phys:Wake() phys:Wake()
end end
@ -237,9 +239,11 @@ end
Physics Simulation Hook (FIXED) Physics Simulation Hook (FIXED)
---------------------------------------------------------------------------]] ---------------------------------------------------------------------------]]
function MODULE:PhysicsSimulate(phys, dt) function MODULE:PhysicsSimulate(phys, dt)
phys:Wake()
if self.StopProcessing then return false end if self.StopProcessing then return false end
--print((CurTime() - self.LastPhysProcess) < 0.05)
--if (CurTime() - self.LastPhysProcess) < (1 /) then return false end
self.LastPhysProcess = CurTime()
local cur_time = CurTime() local cur_time = CurTime()
local target = self:GetTarget() local target = self:GetTarget()
@ -357,10 +361,8 @@ function MODULE:PhysicsSimulate(phys, dt)
local offset_sqr = (pos - self.last_pos):LengthSqr() local offset_sqr = (pos - self.last_pos):LengthSqr()
self.last_pos = pos self.last_pos = pos
if (offset_sqr < (10*10 * dt*dt) and not (ragmod and ragmod:IsRagmodRagdoll(target))) then if offset_sqr < (10*10 * dt*dt) then
self.StartDie = self.StartDie or cur_time self.StartDie = self.StartDie or cur_time
else
--self.StartDie = nil
end end
-- Physics correction after collision -- Physics correction after collision