Compare commits
2 commits
a17730107a
...
85eb62a495
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
85eb62a495 | ||
|
|
8da450edb3 |
4 changed files with 129 additions and 76 deletions
10
README.md
10
README.md
|
|
@ -5,8 +5,14 @@ Adds better NPC integration for the Garry's Mod addon Z-City. While Z-City has a
|
|||
- NPCs can now be alive while ragdolled, and can move around in that state.
|
||||
- NPCs can collapse due to unconsciousness or pain.
|
||||
- NPCs can get back up after being ragdolled.
|
||||
- Various performance settings are included, with the biggest one being automatic corpse removal.
|
||||
|
||||
This plugin is based off of Kazarei's Euphoria, which in turn is a fork of Fedhoria by Rama.
|
||||
This plugin is based off of Kazarei's Euphoria, which in turn is a fork of Fedhoria by Rama. Credits to them for making the cool thing.
|
||||
|
||||
## Known issues
|
||||
|
||||
- Kicking NPCs does not knock them down. This is not something I can easily fix -- I would have to override code in Z-City, which I would rather not do.
|
||||
- NPCs currently instantly get up, with no animation. I plan on remedying this in the future.
|
||||
|
||||
## Incompatibilities
|
||||
|
||||
|
|
@ -18,4 +24,4 @@ No guarantees any of this will become real.
|
|||
|
||||
- NPCs will back out of combat when injured.
|
||||
- Friendly NPCs can heal each other.
|
||||
- NPCs can heal themselves to a limited degree.
|
||||
- NPCs can heal themselves.
|
||||
|
|
@ -44,6 +44,12 @@ local function PopulatePerformanceSBXToolMenu(pnl)
|
|||
|
||||
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: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
|
||||
|
||||
if engine.ActiveGamemode() == "sandbox" then
|
||||
|
|
|
|||
|
|
@ -6,9 +6,13 @@ local always_active_on_player_kill = CreateConVar("zcnpci_always_active_on_play
|
|||
|
||||
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 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 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_hitgroup = {}
|
||||
|
|
@ -16,6 +20,9 @@ local last_attacker = {}
|
|||
|
||||
local corpses = {}
|
||||
|
||||
local last_corpse_tick = CurTime()
|
||||
local last_tick = CurTime()
|
||||
|
||||
hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll)
|
||||
if !ent.organism then return end
|
||||
|
||||
|
|
@ -83,6 +90,13 @@ hook.Add("ScaleNPCDamage", "zcnpci", function(npc, hitgroup, dmginfo)
|
|||
end)
|
||||
|
||||
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
|
||||
if !IsValid(ent) then
|
||||
table.RemoveByValue(corpses, ent)
|
||||
|
|
@ -96,6 +110,7 @@ hook.Add("Think", "zcnpci", function()
|
|||
|
||||
table.remove(corpses, 1)
|
||||
end
|
||||
end
|
||||
|
||||
for i, ent in pairs(ents.GetAll()) do
|
||||
if !IsValid(ent) then continue end
|
||||
|
|
@ -108,7 +123,9 @@ hook.Add("Think", "zcnpci", function()
|
|||
ent.organism.llegamputated or
|
||||
ent.organism.rlegamputated or
|
||||
(ent.organism.consciousness <= 0.3) or
|
||||
(ent.organism.pain > 90)
|
||||
(ent.organism.pain > 90) or
|
||||
ent:IsOnFire() or
|
||||
debug_ragdoll_all:GetBool()
|
||||
) then
|
||||
local damage_info = DamageInfo()
|
||||
damage_info:SetDamage(ent:Health())
|
||||
|
|
@ -118,7 +135,24 @@ hook.Add("Think", "zcnpci", function()
|
|||
|
||||
ent:TakeDamageInfo(damage_info)
|
||||
end
|
||||
elseif !ent.organism.alive and remove_corpses 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
|
||||
if !table.HasValue(corpses, ent) then
|
||||
table.insert(corpses, ent)
|
||||
|
|
@ -155,6 +189,8 @@ hook.Add("Think", "zcnpci", function()
|
|||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
--[[hook.Add("OnNPCKilled", "Fedhoria", function(ent, attacker, inflictor)
|
||||
|
|
|
|||
|
|
@ -161,6 +161,8 @@ function MODULE:Init()
|
|||
self.StartDie = nil
|
||||
self.AnimationRollEndTime = 0
|
||||
self.StopProcessing = false
|
||||
self.LastThink = CurTime()
|
||||
self.LastPhysProcess = CurTime()
|
||||
|
||||
-- Add damping to all bones.
|
||||
local phys = self:GetPhysicsObject()
|
||||
|
|
@ -184,14 +186,14 @@ end
|
|||
---------------------------------------------------------------------------]]
|
||||
|
||||
function MODULE:Think()
|
||||
if (CurTime() - self.LastThink) < 1 then return end
|
||||
if !IsValid(target) then return end
|
||||
|
||||
print("target is valid")
|
||||
self.LastThink = CurTime()
|
||||
|
||||
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()
|
||||
end
|
||||
|
|
@ -237,14 +239,18 @@ end
|
|||
Physics Simulation Hook (FIXED)
|
||||
---------------------------------------------------------------------------]]
|
||||
function MODULE:PhysicsSimulate(phys, dt)
|
||||
phys:Wake()
|
||||
|
||||
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 target = self:GetTarget()
|
||||
if not IsValid(target) then self:Remove(); return false end
|
||||
|
||||
target.is_npc_corpse = true
|
||||
|
||||
if !self.StartDie then self.StartDie = cur_time end
|
||||
|
||||
-- Check for active animation
|
||||
|
|
@ -281,7 +287,8 @@ function MODULE:PhysicsSimulate(phys, dt)
|
|||
(minimum_down_timer >= 1.0) and
|
||||
(target.class_in_previous_life != nil) and
|
||||
!(target.organism.llegamputated or target.organism.rlegamputated or target.organism.larmamputated or target.organism.rarmamputated) and
|
||||
(target.organism.pain <= 80)
|
||||
(target.organism.pain <= 80) and
|
||||
!target:IsOnFire()
|
||||
) then
|
||||
local ent = ents.Create(target.class_in_previous_life)
|
||||
ent:SetPos(target:GetPos())
|
||||
|
|
@ -354,10 +361,8 @@ function MODULE:PhysicsSimulate(phys, dt)
|
|||
local offset_sqr = (pos - self.last_pos):LengthSqr()
|
||||
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
|
||||
else
|
||||
--self.StartDie = nil
|
||||
end
|
||||
|
||||
-- Physics correction after collision
|
||||
|
|
|
|||
Loading…
Reference in a new issue