From a17730107aee267d7e81fed5f3279b61fcabcb8f Mon Sep 17 00:00:00 2001 From: toasterpanic Date: Tue, 26 May 2026 18:38:42 -0400 Subject: [PATCH] Rename stuff, add automatic corpse clearing with various settings --- .../client/{fedh_menu.lua => zcnpci_menu.lua} | 34 ++++++- lua/autorun/server/fedh_init.lua | 1 - lua/autorun/server/zcnpci_init.lua | 1 + lua/{fedhoria.lua => zcnpci.lua} | 90 +++++++++++++++---- lua/zcnpci/modules/falling_legs.lua | 23 ++++- 5 files changed, 126 insertions(+), 23 deletions(-) rename lua/autorun/client/{fedh_menu.lua => zcnpci_menu.lua} (50%) delete mode 100644 lua/autorun/server/fedh_init.lua create mode 100644 lua/autorun/server/zcnpci_init.lua rename lua/{fedhoria.lua => zcnpci.lua} (65%) diff --git a/lua/autorun/client/fedh_menu.lua b/lua/autorun/client/zcnpci_menu.lua similarity index 50% rename from lua/autorun/client/fedh_menu.lua rename to lua/autorun/client/zcnpci_menu.lua index 0a394a1..abca5a2 100644 --- a/lua/autorun/client/fedh_menu.lua +++ b/lua/autorun/client/zcnpci_menu.lua @@ -4,6 +4,8 @@ local function PopulateRagdollSBXToolMenu(pnl) pnl:Help(" ") + pnl:Help(" ") + pnl:NumSlider("Stumble time", "zcnpci_stumble_time", 0, 10, 3) pnl:ControlHelp("How long the ragdoll should try to stumble for.") @@ -15,14 +17,33 @@ local function PopulateRagdollSBXToolMenu(pnl) pnl:NumSlider("Minimum down time", "zcnpci_down_time", 0, 20, 3) pnl:ControlHelp("The minimum amount of time the ragdoll should be down before trying to get back up.") +end + +local function PopulatePerformanceSBXToolMenu(pnl) + pnl:NumSlider("Activation range", "zcnpci_active_range", 0, 5000, 0) + pnl:ControlHelp("How close the ragdoll has to be to a player to be living when downed by damage. Enemies downed by other causes are unaffected.") + + pnl:CheckBox("Always activate on player kill", "zcnpci_always_active_on_player_kill") + pnl:ControlHelp("If on, all player-damaged ragdolls will be activated regardless of other factors.") pnl:Help(" ") - pnl:NumSlider("Activation range", "zcnpci_active_range", 0, 5000, 0) - pnl:ControlHelp("How close the ragdoll has to be to a player to have euphoria physics") + pnl:Help(" ") - pnl:CheckBox("Always activate on player kill", "zcnpci_always_active_on_player_kill") - pnl:ControlHelp("If on, all player-killed ragdolls will be activated regardless of other factors.") + pnl:CheckBox("Enable automatic corpse removal", "zcnpci_enable_corpse_removal") + pnl:ControlHelp("Enable or disable the removal of dead corpses.") + + pnl:NumSlider("Max corpses", "zcnpci_max_corpses", -1, 64, 0) + pnl:ControlHelp("The maximum amount of dead corpses that are allowed before one is removed. Set to -1 to disable") + + pnl:NumSlider("Max time", "zcnpci_max_corpse_time", -1, 600, 2) + pnl:ControlHelp("The maximum amount of time before a corpse is removed. Set to -1 to disable") + + pnl:NumSlider("Max distance between player", "zcnpci_max_corpse_distance", -1, 32768, 2) + pnl:ControlHelp("If the corpse is further than this distance, it will be removed. Set to -1 to disable") + + 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.") end if engine.ActiveGamemode() == "sandbox" then @@ -35,5 +56,10 @@ if engine.ActiveGamemode() == "sandbox" then pnl:ClearControls() PopulateRagdollSBXToolMenu(pnl) end) + + spawnmenu.AddToolMenuOption("Utilities", "zcnpci", "PerformanceSettings", "Performance", "", "", function(pnl) + pnl:ClearControls() + PopulatePerformanceSBXToolMenu(pnl) + end) end) end \ No newline at end of file diff --git a/lua/autorun/server/fedh_init.lua b/lua/autorun/server/fedh_init.lua deleted file mode 100644 index a493209..0000000 --- a/lua/autorun/server/fedh_init.lua +++ /dev/null @@ -1 +0,0 @@ -include("fedhoria.lua") \ No newline at end of file diff --git a/lua/autorun/server/zcnpci_init.lua b/lua/autorun/server/zcnpci_init.lua new file mode 100644 index 0000000..420dddb --- /dev/null +++ b/lua/autorun/server/zcnpci_init.lua @@ -0,0 +1 @@ +include("zcnpci.lua") \ No newline at end of file diff --git a/lua/fedhoria.lua b/lua/zcnpci.lua similarity index 65% rename from lua/fedhoria.lua rename to lua/zcnpci.lua index b1e42bc..121b3bc 100644 --- a/lua/fedhoria.lua +++ b/lua/zcnpci.lua @@ -1,13 +1,21 @@ include("zcnpci/modules.lua") local enabled = CreateConVar("zcnpci_enabled", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) -local active_range = CreateConVar("zcnpci_active_range", 300, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) +local active_range = CreateConVar("zcnpci_active_range", 3000, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) local always_active_on_player_kill = CreateConVar("zcnpci_always_active_on_player_kill", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) +local remove_corpses = CreateConVar("zcnpci_enable_corpse_removal", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) +local max_corpses = CreateConVar("zcnpci_max_corpses", 8, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) +local max_corpse_time = CreateConVar("zcnpci_max_corpse_time", 30, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED)) +local max_corpse_distance = CreateConVar("zcnpci_max_corpse_distance", 3000, 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 last_dmgpos = {} local last_hitgroup = {} local last_attacker = {} +local corpses = {} + hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll) if !ent.organism then return end @@ -75,26 +83,76 @@ hook.Add("ScaleNPCDamage", "zcnpci", function(npc, hitgroup, dmginfo) end) hook.Add("Think", "zcnpci", function() + for i, ent in pairs(corpses) do + if !IsValid(ent) then + table.RemoveByValue(corpses, ent) + end + end + + if (max_corpses:GetFloat() != -1) and (#corpses > max_corpses:GetFloat()) then + if IsValid(corpses[1]) then + corpses[1]:Remove() + end + + table.remove(corpses, 1) + end + for i, ent in pairs(ents.GetAll()) do if !IsValid(ent) then continue end - if !ent:IsNPC() 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) + ) 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)) - -- 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.5) or - (ent.organism.pain > 90) - ) 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 then + -- Add to corpse list if not there already + if !table.HasValue(corpses, ent) then + table.insert(corpses, ent) + end - ent:TakeDamageInfo(damage_info) + -- 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() + continue + end + + 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) diff --git a/lua/zcnpci/modules/falling_legs.lua b/lua/zcnpci/modules/falling_legs.lua index 2a21bb3..c172a08 100644 --- a/lua/zcnpci/modules/falling_legs.lua +++ b/lua/zcnpci/modules/falling_legs.lua @@ -69,7 +69,7 @@ local cv_anim_roll_impact_threshold = CreateConVar("zcnpci_falling_anim_roll_imp local cv_anim_roll_playback_rate = CreateConVar("zcnpci_falling_anim_roll_playback_rate", "3.0", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Скорость воспроизведения анимации") -- Down time -local minimum_down_time = CreateConVar("zcnpci_down_time", "8", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Down time!!!!!!!!!") +local minimum_down_time = CreateConVar("zcnpci_down_time", "3", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Down time!!!!!!!!!") --[[------------------------------------------------------------------------- Tug function @@ -182,8 +182,18 @@ end --[[------------------------------------------------------------------------- Think-hook ---------------------------------------------------------------------------]] + function MODULE:Think() - -- Space for additional logic + if !IsValid(target) then return end + + print("target is valid") + + local phys = target:GetPhysicsObject() + if !IsValid(phys) or !phys:IsAsleep() then return end + + print("phys is valid") + + phys:Wake() end --[[------------------------------------------------------------------------- @@ -218,11 +228,17 @@ function MODULE:PhysicsCollide(data, phys) end end +function MODULE:EntityTakeDamage(ent, dmginfo) + print("I TOOK DAMAGE") +end + --[[------------------------------------------------------------------------- Physics Simulation Hook (FIXED) ---------------------------------------------------------------------------]] function MODULE:PhysicsSimulate(phys, dt) + phys:Wake() + if self.StopProcessing then return false end local cur_time = CurTime() @@ -285,6 +301,9 @@ function MODULE:PhysicsSimulate(phys, dt) timer.Simple(0, function() hg.organism.Add(ent) table.Merge(ent.organism, target.organism) + + ent.tourniquets = table.Copy(target.tourniquets) + ent.bandaged_limbs = table.Copy(target.bandaged_limbs) ent.organism.alive = true ent.organism.owner = ent