Clear crippled and near-death enemies, various optimizations
This commit is contained in:
parent
8da450edb3
commit
85eb62a495
3 changed files with 115 additions and 72 deletions
|
|
@ -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
|
||||||
|
|
|
||||||
159
lua/zcnpci.lua
159
lua/zcnpci.lua
|
|
@ -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,79 +90,107 @@ hook.Add("ScaleNPCDamage", "zcnpci", function(npc, hitgroup, dmginfo)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
hook.Add("Think", "zcnpci", function()
|
hook.Add("Think", "zcnpci", function()
|
||||||
for i, ent in pairs(corpses) do
|
local do_corpse_loop = (CurTime() - last_corpse_tick) > 2.0
|
||||||
if !IsValid(ent) then
|
local do_general_loop = (CurTime() - last_tick) > 0.1
|
||||||
table.RemoveByValue(corpses, ent)
|
|
||||||
end
|
if do_general_loop then
|
||||||
end
|
if do_corpse_loop then
|
||||||
|
last_corpse_tick = CurTime()
|
||||||
|
|
||||||
if (max_corpses:GetFloat() != -1) and (#corpses > max_corpses:GetFloat()) then
|
for i, ent in pairs(corpses) do
|
||||||
if IsValid(corpses[1]) then
|
if !IsValid(ent) then
|
||||||
corpses[1]:Remove()
|
table.RemoveByValue(corpses, ent)
|
||||||
end
|
|
||||||
|
|
||||||
table.remove(corpses, 1)
|
|
||||||
end
|
|
||||||
|
|
||||||
for i, ent in pairs(ents.GetAll()) do
|
|
||||||
if !IsValid(ent) then continue end
|
|
||||||
if !ent.organism then continue end
|
|
||||||
|
|
||||||
if ent:IsNPC() then
|
|
||||||
-- Knock them down if something is off
|
|
||||||
if (
|
|
||||||
((ent.organism.lleg >= 1) and (ent.organism.rleg >= 1)) or
|
|
||||||
ent.organism.llegamputated or
|
|
||||||
ent.organism.rlegamputated or
|
|
||||||
(ent.organism.consciousness <= 0.3) or
|
|
||||||
(ent.organism.pain > 90) or
|
|
||||||
ent:IsOnFire()
|
|
||||||
) then
|
|
||||||
local damage_info = DamageInfo()
|
|
||||||
damage_info:SetDamage(ent:Health())
|
|
||||||
damage_info:SetAttacker(ent)
|
|
||||||
damage_info:SetDamageType( DMG_DIRECT )
|
|
||||||
damage_info:SetDamageForce(Vector(0, 0, 0))
|
|
||||||
|
|
||||||
ent:TakeDamageInfo(damage_info)
|
|
||||||
end
|
|
||||||
elseif !ent.organism.alive and remove_corpses and ent.is_npc_corpse then
|
|
||||||
-- Add to corpse list if not there already
|
|
||||||
if !table.HasValue(corpses, ent) then
|
|
||||||
table.insert(corpses, ent)
|
|
||||||
end
|
|
||||||
|
|
||||||
-- Get nearest player for future checks
|
|
||||||
local nearby_player
|
|
||||||
local players = player.GetAll()
|
|
||||||
|
|
||||||
for i, loop_player in pairs(players) do
|
|
||||||
local player_position = loop_player:GetPos()
|
|
||||||
|
|
||||||
local distance = ent:GetPos():Distance(player_position)
|
|
||||||
|
|
||||||
if (distance <= max_corpse_distance:GetFloat()) or (max_corpse_distance:GetFloat() == -1) then
|
|
||||||
nearby_player = loop_player
|
|
||||||
break
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
if nearby_player and IsValid(nearby_player) and no_corpse_removal_near_player:GetBool() then continue
|
if (max_corpses:GetFloat() != -1) and (#corpses > max_corpses:GetFloat()) then
|
||||||
elseif (max_corpse_distance:GetFloat() != -1) and !nearby_player then
|
if IsValid(corpses[1]) then
|
||||||
ent:Remove()
|
corpses[1]:Remove()
|
||||||
continue
|
end
|
||||||
end
|
|
||||||
|
|
||||||
if max_corpse_time:GetFloat() != -1 then
|
table.remove(corpses, 1)
|
||||||
if !ent.corpse_timestamp then ent.corpse_timestamp = CurTime()
|
end
|
||||||
elseif (CurTime() - ent.corpse_timestamp) > max_corpse_time:GetFloat() then
|
end
|
||||||
|
|
||||||
|
for i, ent in pairs(ents.GetAll()) do
|
||||||
|
if !IsValid(ent) then continue end
|
||||||
|
if !ent.organism then continue end
|
||||||
|
|
||||||
|
if ent:IsNPC() then
|
||||||
|
-- Knock them down if something is off
|
||||||
|
if (
|
||||||
|
((ent.organism.lleg >= 1) and (ent.organism.rleg >= 1)) or
|
||||||
|
ent.organism.llegamputated or
|
||||||
|
ent.organism.rlegamputated or
|
||||||
|
(ent.organism.consciousness <= 0.3) or
|
||||||
|
(ent.organism.pain > 90) or
|
||||||
|
ent:IsOnFire() or
|
||||||
|
debug_ragdoll_all:GetBool()
|
||||||
|
) then
|
||||||
|
local damage_info = DamageInfo()
|
||||||
|
damage_info:SetDamage(ent:Health())
|
||||||
|
damage_info:SetAttacker(ent)
|
||||||
|
damage_info:SetDamageType( DMG_DIRECT )
|
||||||
|
damage_info:SetDamageForce(Vector(0, 0, 0))
|
||||||
|
|
||||||
|
ent:TakeDamageInfo(damage_info)
|
||||||
|
end
|
||||||
|
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
|
||||||
|
if !table.HasValue(corpses, ent) then
|
||||||
|
table.insert(corpses, ent)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Get nearest player for future checks
|
||||||
|
local nearby_player
|
||||||
|
local players = player.GetAll()
|
||||||
|
|
||||||
|
for i, loop_player in pairs(players) do
|
||||||
|
local player_position = loop_player:GetPos()
|
||||||
|
|
||||||
|
local distance = ent:GetPos():Distance(player_position)
|
||||||
|
|
||||||
|
if (distance <= max_corpse_distance:GetFloat()) or (max_corpse_distance:GetFloat() == -1) then
|
||||||
|
nearby_player = loop_player
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if nearby_player and IsValid(nearby_player) and no_corpse_removal_near_player:GetBool() then continue
|
||||||
|
elseif (max_corpse_distance:GetFloat() != -1) and !nearby_player then
|
||||||
ent:Remove()
|
ent:Remove()
|
||||||
continue
|
continue
|
||||||
end
|
end
|
||||||
print((CurTime() - ent.corpse_timestamp) > max_corpse_time:GetFloat())
|
|
||||||
|
if max_corpse_time:GetFloat() != -1 then
|
||||||
|
if !ent.corpse_timestamp then ent.corpse_timestamp = CurTime()
|
||||||
|
elseif (CurTime() - ent.corpse_timestamp) > max_corpse_time:GetFloat() then
|
||||||
|
ent:Remove()
|
||||||
|
continue
|
||||||
|
end
|
||||||
|
print((CurTime() - ent.corpse_timestamp) > max_corpse_time:GetFloat())
|
||||||
|
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)
|
||||||
|
|
|
||||||
|
|
@ -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,15 +186,15 @@ 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
|
if !IsValid(phys) or !phys:IsAsleep() then return end
|
||||||
|
|
||||||
print("phys is valid")
|
|
||||||
|
|
||||||
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
|
||||||
|
|
@ -373,7 +375,7 @@ function MODULE:PhysicsSimulate(phys, dt)
|
||||||
|
|
||||||
return true, f
|
return true, f
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Logic for other bones
|
-- Logic for other bones
|
||||||
local delta_collide = cur_time - self.LastCollideTime
|
local delta_collide = cur_time - self.LastCollideTime
|
||||||
if (delta_collide < 0.2) then
|
if (delta_collide < 0.2) then
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue