Compare commits

..

No commits in common. "02557dacd1b94f351211b7428fa4f0c6463c5ea5" and "4c4d59838a79a27b59787cc70a7fdf31d2a749c9" have entirely different histories.

8 changed files with 101 additions and 340 deletions

View file

@ -1,16 +1,14 @@
# Z-City NPC Integration # Z-City NPC Integration
Adds better NPC integration for the Garry's Mod addon Z-City. Adds better NPC integration for the Garry's Mod addon Z-City. While Z-City has a convar that enables the custom health system on NPCs, it really isn't the best or most advanced thing in the world. This has irritated me since I first started using Z-City. Therefore, I've decided to take care of the problem myself with my own plugin.
While Z-City has a convar that enables the custom health system on NPCs, it really isn't the best or most bug-free thing in the world. This has irritated me since I first started using Z-City. Therefore, I've decided to take care of the problem myself with my own plugin.
- NPCs can be ragdolled like players can, and will wiggle around on the ground. They can get back up, too! - NPCs can be ragdolled like players can, and will wiggle around on the ground. They can get back up, too!
- It takes all elements of Z-City's health system into account, such as unconsciousness and pain. - It takes all elements of Z-City's health system into account, such as unconsciousness and pain.
- NPCs are responsive to damage from many sources -- bullets, fire, melee (especially kicks!) and more. - NPCs are responsive to damage from many sources -- bullets, fire, melee (especially kicks!) and more.
- NPCs can also see and target downed NPCs, and will prioritize standing NPCs over them when needed. - NPCs can also see and target downed NPCs, and will prioritize standing NPCs over them when needed.
- Everything is configurable, so you can modify and disable features as you like to create your preferred experience. - Various configurable settings are included, allowing you to tweak the mod to your liking.
This mod is built to perform reasonably well, thus it includes optimizations, configurable performance settings, and an automatic corpse cleanup tool. This mod is built to perform reasonably well, thus it includes optimizations, configurable performance settings, and an automatic corpse remover.
This addon 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. This addon 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.
@ -36,16 +34,16 @@ It is, however, not compatbile with:
MUST BE DONE BEFORE RELEASE: MUST BE DONE BEFORE RELEASE:
- Spinal injuries
- NPCs should not unfake when moved around
- Fire / falling / pain reaction (more rapid flailing) - Fire / falling / pain reaction (more rapid flailing)
- NPCs should not unfake if being grabbed - NPCs should not unfake if being grabbed
- Fix combine targeting players when ai_ignoreplayers = 1. This is caused by an npc_bullseye that is always on the player. I don't know why it's always there but I don't like it. Will probably override it with my own npc_ragdoll_target entity.
Stuff to do: Stuff to do:
- Posturing (like when you get hit) more similar to Z-City
- Facial expressions - Facial expressions
- Generally improve stumbling (foot stepping) - Generally improve stumbling (foot stepping)
- Stop NPCs from dropping their guns maybe? - Stop NPCs from dropping their guns (that's not a good thing to do)
Post release ideas: Post release ideas:

View file

@ -53,12 +53,6 @@ local function PopulateRagdollSBXToolMenu(pnl)
pnl:NumSlider("Wound grab time", "zcnpci_woundgrab_time", 0, 10, 3) pnl:NumSlider("Wound grab time", "zcnpci_woundgrab_time", 0, 10, 3)
pnl:ControlHelp("How long the ragdoll should hold its wound.") pnl:ControlHelp("How long the ragdoll should hold its wound.")
pnl:NumSlider("Writhing strength", "zcnpci_writhing_strength", 0, 5, 3)
pnl:ControlHelp("How hard should the ragdoll wriggle/writhe. 1 is default.")
pnl:NumSlider("Death timer", "zcnpci_death_timer", -1, 600, 3)
pnl:ControlHelp("After an NPC is ragdolled for longer than this timer, they will die instantly. Set to -1 to disable.")
pnl:CheckBox("Allow getting up", "zcnpci_unfake_enabled") pnl:CheckBox("Allow getting up", "zcnpci_unfake_enabled")
pnl:ControlHelp("If enabled, NPCs will get back up if able.") pnl:ControlHelp("If enabled, NPCs will get back up if able.")
@ -67,9 +61,6 @@ local function PopulateRagdollSBXToolMenu(pnl)
pnl:NumSlider("Minimum down time", "zcnpci_down_time", 0, 20, 3) 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.") pnl:ControlHelp("The minimum amount of time the ragdoll should be down before trying to get back up.")
pnl:NumSlider("Movement sensitivity", "zcnpci_movement_sensitivity", -1, 256, 3)
pnl:ControlHelp("How far does the NPC have to move to reset the getting up timer. Set to -1 to disable.")
end end
local function PopulatePerformanceSBXToolMenu(pnl) local function PopulatePerformanceSBXToolMenu(pnl)

View file

@ -15,7 +15,7 @@ local function UpdateRelationship(ent, me)
if !IsValid(ent) or !ent:IsNPC() or (ent:GetClass() == "npc_ragdoll_target") then return end if !IsValid(ent) or !ent:IsNPC() or (ent:GetClass() == "npc_ragdoll_target") then return end
if ent:Disposition(me.dummy_entity) == D_HT then if ent:Disposition(me.dummy_entity) == D_HT then
--print("Ragdoll target of class "..me.ragdoll_to_follow.class_in_previous_life.." is hated by a "..ent:GetClass()) print("Ragdoll target of class "..me.ragdoll_to_follow.class_in_previous_life.." is hated by a "..ent:GetClass())
ent:AddEntityRelationship(me, D_HT, -1) ent:AddEntityRelationship(me, D_HT, -1)
else else
ent:AddEntityRelationship(me, D_NU, -1) ent:AddEntityRelationship(me, D_NU, -1)
@ -84,7 +84,7 @@ function ENT:Think()
(ragdoll.organism.critical) (ragdoll.organism.critical)
) )
if (should_stop_targeting != self.last_stop_targeting) then if true or (should_stop_targeting != self.last_stop_targeting) then
self.last_stop_targeting = should_stop_targeting self.last_stop_targeting = should_stop_targeting
if should_stop_targeting then if should_stop_targeting then

View file

@ -4,6 +4,8 @@ ENT.Type = "anim"
ENT.Base = "base_anim" ENT.Base = "base_anim"
ENT.AutomaticFrameAdvance = true ENT.AutomaticFrameAdvance = true
local bones_to_animate = { local bones_to_animate = {
"ValveBiped.Bip01_Pelvis", "ValveBiped.Bip01_Pelvis",
"ValveBiped.Bip01_Spine2", "ValveBiped.Bip01_Spine2",
@ -22,15 +24,6 @@ local bones_to_animate = {
"ValveBiped.Bip01_L_Hand", "ValveBiped.Bip01_L_Hand",
} }
-- Copy pasted directly from the GMOD wiki with small edits
local function SetRagdollPos(ragdoll, pos)
for i = 0, ragdoll:GetPhysicsObjectCount() - 1 do
local phys = ragdoll:GetPhysicsObjectNum(i)
local localPos = ragdoll:WorldToLocal( phys:GetPos() )
phys:SetPos(pos + localPos)
end
end
function ENT:Initialize() function ENT:Initialize()
if SERVER then if SERVER then
print("I AM SERVERSIDE") print("I AM SERVERSIDE")
@ -39,93 +32,116 @@ function ENT:Initialize()
if CLIENT then if CLIENT then
print("I AM CLIENTSIDE") print("I AM CLIENTSIDE")
self:SetNoDraw(true) timer.Simple(0.2, function()
end)
end end
end end
function ENT:Think() function ENT:Draw()
if CLIENT then if CLIENT then
hook.Add("physics")
local old_ragdoll = self:GetNWEntity("parent") local old_ragdoll = self:GetNWEntity("parent")
local old_npc = self:GetNWEntity("parent_npc") local old_npc = self:GetNWEntity("parent_npc")
if IsValid(old_ragdoll) and IsValid(old_npc) then if IsValid(old_ragdoll) and IsValid(old_npc) then
local ragdoll = self.ragdoll if !self.ready_to_unfake then
self:SetModel(old_ragdoll:GetModel())
if !self.ready_to_animate then self.bone_list = {}
self.ragdoll = ClientsideRagdoll(old_ragdoll:GetModel()) self.bone_list_end = {}
ragdoll = self.ragdoll self:SetupBones()
self.ragdoll:SetNoDraw(false) local i = 0
self.ragdoll:DrawShadow(true) while i < self:GetBoneCount() do
local name = self:GetBoneName(i)
if name == "__INVALIDBONE__" then
i = i + 1
continue
end
SetRagdollPos(self.ragdoll, old_ragdoll:GetPos()) table.insert(bones_to_animate, name)
print(self.ragdoll)
print("SHOW UP YOU PIECE OF SHIT")
for i, name in pairs(bones_to_animate) do local matrix = Matrix()
local object = ragdoll:GetPhysicsObjectNum(ragdoll:TranslateBoneToPhysBone(ragdoll:LookupBone(name)))
local parent_object = old_ragdoll:GetBoneMatrix(old_ragdoll:LookupBone(name))
print(parent_object)
if parent_object == nil then continue end local position, angle = old_ragdoll:GetBonePosition(i)
if position == old_ragdoll:GetPos() then
get_matrix = old_ragdoll:GetBoneMatrix(i)
if get_matrix then
position = get_matrix:GetTranslation()
end
end
matrix:Translate(position)
matrix:Rotate(angle)
object:SetPos(parent_object:GetTranslation()) self.bone_list[name] = matrix
object:SetAngles(parent_object:GetAngles())
local matrix = Matrix()
local position, angle = old_npc:GetBonePosition(i)
if position == old_npc:GetPos() then
get_matrix = old_npc:GetBoneMatrix(i)
if get_matrix then
position = get_matrix:GetTranslation()
end
end
matrix:Translate(position)
matrix:Rotate(angle)
self.bone_list_end[name] = matrix
i = i + 1
end end
self.ready_to_animate = true PrintTable(bones_to_animate)
--[[for i,name in pairs(bones_to_animate) do
local bone_index = old_ragdoll:LookupBone(name)
if bone_index == nil then continue end
self.bone_list[name] = Matrix(old_ragdoll:GetBoneMatrix(bone_index))
end]]
print("BONES:"..self:GetBoneCount())
self.ready_to_unfake = true
end end
local fake_start = self:GetNWFloat("fake_start") self:SetPos(old_ragdoll:GetPos())
local fake_end = self:GetNWFloat("fake_end")
local progress = (CurTime() - fake_start) / (fake_end - fake_start) self:SetupBones()
for i, name in pairs(bones_to_animate) do for name,matrix in pairs(self.bone_list) do
local object = ragdoll:GetPhysicsObjectNum(ragdoll:TranslateBoneToPhysBone(ragdoll:LookupBone(name))) local bone_index = self:LookupBone(name)
local parent_bone = old_npc:LookupBone(name) if bone_index == -1 then
print(name.." does not exist, skipping...")
continue
end
if parent_bone == -1 then continue end
local parent_bone_matrix = old_npc:GetBoneMatrix(parent_bone) --print(name)
if !parent_bone_matrix then continue end --local bone_matrix = old_ragdoll:GetBoneMatrix(bone_index)
local parent_bone_pos, parent_bone_angle = parent_bone_matrix:GetTranslation(), parent_bone_matrix:GetAngles() if matrix:GetTranslation():DistToSqr(self:GetPos()) == 1 then continue end
local old_bone_pos, old_bone_angle = object:GetPos(), object:GetAngles()
--parent_bone_angle.y = parent_bone_angle.y + 90
local shadow_data = { self:SetBoneMatrix(bone_index, matrix)
secondstoarrive = 0.01,
pos = LerpVector(progress, old_bone_pos, parent_bone_pos),
angle = LerpAngle(progress, old_bone_angle, parent_bone_angle),
maxspeed = 400 * 4,
maxangular = 2000 * 4,
maxspeeddamp = 120 * 4,
maxangularspeeddamp = 600 * 4,
}
-- Can't set position inside physics tick, crashes the game instantly.
-- Instead, send a shadow for it to follow (I think? I don't know GMod is kinda funky)
object:ComputeShadowControl(shadow_data)
object:Wake()
--i = i + 1
end end
end end
end end
self:NextThink(CurTime() + 0.1) self:DrawModel()
end
function ENT:Think()
return true return true
end end
function ENT:OnRemove() function ENT:OnRemove()
if CLIENT then if CLIENT then
if self.ragdoll then --[[if self.anim_ragdoll then
self.ragdoll:Remove() self.anim_ragdoll:Remove()
end end]]
end end
end end

View file

@ -1,191 +0,0 @@
AddCSLuaFile()
ENT.Type = "anim"
ENT.Base = "base_anim"
ENT.AutomaticFrameAdvance = true
local bones_to_animate = {
"ValveBiped.Bip01_Pelvis",
"ValveBiped.Bip01_Spine2",
"ValveBiped.Bip01_Head1",
"ValveBiped.Bip01_R_Thigh",
"ValveBiped.Bip01_L_Thigh",
"ValveBiped.Bip01_L_Calf",
"ValveBiped.Bip01_R_Calf",
"ValveBiped.Bip01_R_Foot",
"ValveBiped.Bip01_L_Foot",
"ValveBiped.Bip01_R_Upperarm",
"ValveBiped.Bip01_L_Upperarm",
"ValveBiped.Bip01_R_Forearm",
"ValveBiped.Bip01_L_Forearm",
"ValveBiped.Bip01_R_Hand",
"ValveBiped.Bip01_L_Hand",
}
local function GetBoneLocalOffsetMatrix(ent, bone_index)
local parent = ent:GetBoneParent(bone_index)
local parent_matrix = Matrix(ent:GetBoneMatrix(parent))
parent_matrix:Invert()
parent_matrix:Mul(ent:GetBoneMatrix(bone_index))
return parent_matrix
end
local function GetGlobalMatrixFromLocal(ent, bone_index, local_matrix)
local parent = ent:GetBoneParent(bone_index)
local parent_matrix = Matrix(ent:GetBoneMatrix(parent))
parent_matrix:Mul(local_matrix)
return parent_matrix
end
function ENT:Initialize()
if SERVER then
print("I AM SERVERSIDE")
self:SetModel("models/dav0r/hoverball.mdl")
end
if CLIENT then
print("I AM CLIENTSIDE")
timer.Simple(0.2, function()
end)
end
end
function ENT:Draw()
if CLIENT then
local old_ragdoll = self:GetNWEntity("parent")
local old_npc = self:GetNWEntity("parent_npc")
if IsValid(old_ragdoll) and IsValid(old_npc) then
if !self.ready_to_unfake then
self:SetModel(old_ragdoll:GetModel())
self.bone_list = {}
self.bone_list_end = {}
self.bone_list_end_offset = {}
self:SetupBones()
local i = 0
while i < self:GetBoneCount() do
local name = self:GetBoneName(i)
if name == "__INVALIDBONE__" then
i = i + 1
continue
end
table.insert(bones_to_animate, name)
local matrix = Matrix()
local position, angle = old_ragdoll:GetBonePosition(i)
if position == old_ragdoll:GetPos() then
get_matrix = old_ragdoll:GetBoneMatrix(i)
if get_matrix then
position = get_matrix:GetTranslation()
end
end
matrix:Translate(position)
matrix:Rotate(angle)
self.bone_list[name] = matrix
local matrix = Matrix()
local npc_bone_index = old_npc:LookupBone(name)
local position, angle = old_npc:GetBonePosition(npc_bone_index)
if position == old_npc:GetPos() then
print("DINGUS!!!! "..name)
self.bone_list_end_offset[name] = GetBoneLocalOffsetMatrix(self, npc_bone_index)
get_matrix = old_npc:GetBoneMatrix(npc_bone_index)
if get_matrix then
position = get_matrix:GetTranslation()
end
else
matrix:Translate(position)
matrix:Rotate(angle)
self.bone_list_end[name] = matrix
end
i = i + 1
end
PrintTable(bones_to_animate)
--[[for i,name in pairs(bones_to_animate) do
local bone_index = old_ragdoll:LookupBone(name)
if bone_index == nil then continue end
self.bone_list[name] = Matrix(old_ragdoll:GetBoneMatrix(bone_index))
end]]
print("BONES:"..self:GetBoneCount())
self.ready_to_unfake = true
end
self:SetPos(old_ragdoll:GetPos())
self:SetupBones()
local fake_start = self:GetNWFloat("fake_start")
local fake_end = self:GetNWFloat("fake_end")
local progress = (CurTime() - fake_start) / (fake_end - fake_start)
for name,matrix in pairs(self.bone_list) do
local bone_index = self:LookupBone(name)
if bone_index == -1 then
print(name.." does not exist, skipping...")
continue
end
local matrix_end = self.bone_list_end[name]
if matrix_end == nil then
if (self.bone_list_end_offset[name] == nil) then
print("OH FUCKKKKKKKK! No matrix end for "..name)
continue
end
matrix_end = GetGlobalMatrixFromLocal(self, bone_index, self.bone_list_end_offset[name])
end
local final_matrix = Matrix()
final_matrix:Translate(LerpVector(progress, matrix:GetTranslation(), matrix_end:GetTranslation()))
final_matrix:Rotate(LerpAngle(progress, matrix:GetAngles(), matrix_end:GetAngles()))
--print(name)
--local bone_matrix = old_ragdoll:GetBoneMatrix(bone_index)
if matrix:GetTranslation():DistToSqr(self:GetPos()) == 1 then continue end
self:SetBoneMatrix(bone_index, final_matrix)
end
end
end
self:DrawModel()
end
function ENT:Think()
return true
end
function ENT:OnRemove()
if CLIENT then
--[[if self.anim_ragdoll then
self.anim_ragdoll:Remove()
end]]
end
end

View file

@ -57,45 +57,16 @@ local corpses = {}
local last_corpse_tick = CurTime() local last_corpse_tick = CurTime()
local last_tick = CurTime() local last_tick = CurTime()
local hook_table = hook.GetTable()
local homigrad_damage_hook = hook_table.EntityTakeDamage["homigrad-damage"]
local homigrad_player_spawn_hook = hook_table.player_spawn["homigrad-spawn3"]
-- We need to override the default homigrad damage hook so it doesn't cause damage to ragdolls we are tryign to fake -- We need to override the default homigrad damage hook so it doesn't cause damage to ragdolls we are tryign to fake
-- Don't particularly like doing this but you gotta do what you gotta do
local homigrad_damage_hook = hook.GetTable().EntityTakeDamage["homigrad-damage"]
hook.Add("EntityTakeDamage", "homigrad-damage", function(ent, dmginfo) hook.Add("EntityTakeDamage", "homigrad-damage", function(ent, dmginfo)
if ent:IsNPC() and ent.organism_no_damage then return false end if ent:IsNPC() and ent.organism_no_damage then return false end
homigrad_damage_hook(ent, dmginfo) homigrad_damage_hook(ent, dmginfo)
end) end)
-- This disables player bullseye spawning, which fixes issues with combine targeting with ai_ignoreplayers
hook.Add("player_spawn", "homigrad-spawn3", function(data)
local ply = Player(data.userid)
if not IsValid(ply) then return end
ply.bull = {
IsValid = function() return true end,
Remove = function() return end
}
homigrad_player_spawn_hook(data)
end)
-- This is called right after the NPC bullseye is created for player ragdolls, which allows us to replace it with a dummy.
-- Fixes similar issues mentioned in previous comment
hook.Add("Ragdoll_Create", "zcnpci-override", function(ply, ragdoll)
if IsValid(ragdoll.bull) then
ragdoll.bull:Remove()
end
ragdoll.bull = {
IsValid = function() return true end,
SetPos = function() return true end,
Remove = function() return end
}
end)
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
@ -173,13 +144,6 @@ hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll)
-- Why is it like this? Fuck if I know, I just know I don't wanna deal with it again. -- Why is it like this? Fuck if I know, I just know I don't wanna deal with it again.
ragdoll.citizentype = ent:GetInternalVariable("citizentype") ragdoll.citizentype = ent:GetInternalVariable("citizentype")
ragdoll.respawn_data = {
flags = ent:GetFlags(),
spawn_flags = ent:GetSpawnFlags()
}
ragdoll:AddCallback("PhysicsCollide", function(outEnt, data) hook.Run("Ragdoll Collide", ragdoll, data) end)
timer.Simple(0, function() timer.Simple(0, function()
if !IsValid(ragdoll) then return end if !IsValid(ragdoll) then return end
@ -212,13 +176,17 @@ hook.Add("HomigradDamage", "zcnpci", function(ent, dmginfo)
if dmginfo:IsDamageType(DMG_BULLET + DMG_BUCKSHOT + DMG_BLAST) then if dmginfo:IsDamageType(DMG_BULLET + DMG_BUCKSHOT + DMG_BLAST) then
if dmginfo:GetDamage() > 3 then if dmginfo:GetDamage() > 3 then
table.insert(npcs_to_fake, ent) table.insert(npcs_to_fake, ent)
--local attacker_angle = dmginfo:GetAttacker():EyeAngles()
--local normal = attacker_angle:Forward(normal)
--ent.npcfakeknockback = normal * 7 * 3
end end
elseif dmginfo:IsDamageType(DMG_CLUB + DMG_SLASH) then elseif dmginfo:IsDamageType(DMG_CLUB + DMG_SLASH) then
local attacker = dmginfo:GetAttacker() local attacker = dmginfo:GetAttacker()
if !IsValid(attacker) then return end if !IsValid(attacker) then return end
if attacker.HasWeapon == nil then return end
local fists = attacker:HasWeapon("weapon_hands_sh") local fists = attacker:HasWeapon("weapon_hands_sh")
if !fists then fists = attacker:HasWeapon("weapon_hg_coolhands") end if !fists then fists = attacker:HasWeapon("weapon_hg_coolhands") end

View file

@ -99,8 +99,6 @@ local minimum_down_time = CreateConVar("zcnpci_down_time", "5", {FCVAR_ARCHIVE,
-- Unfaking -- Unfaking
local can_unfake = CreateConVar("zcnpci_unfake_enabled", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Whether an NPC can unfake") local can_unfake = CreateConVar("zcnpci_unfake_enabled", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Whether an NPC can unfake")
local unfake_time = CreateConVar("zcnpci_unfake_time", "1.5", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Time it takes for an NPC to unfake") local unfake_time = CreateConVar("zcnpci_unfake_time", "1.5", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Time it takes for an NPC to unfake")
local movement_sensitivity = CreateConVar("zcnpci_movement_sensitivity", "40", {FCVAR_ARCHIVE, FCVAR_REPLICATED})
local death_timer = CreateConVar("zcnpci_death_timer", "-1", {FCVAR_ARCHIVE, FCVAR_REPLICATED})
-- Targeting -- Targeting
local npc_targeting_enabled = CreateConVar("zcnpci_npc_targeting_enabled", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Should NPCs target downed NPCs") local npc_targeting_enabled = CreateConVar("zcnpci_npc_targeting_enabled", "1", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Should NPCs target downed NPCs")
@ -201,7 +199,6 @@ function MODULE:Init()
self.LastThink = CurTime() self.LastThink = CurTime()
self.LastFakeUpCheck = CurTime() self.LastFakeUpCheck = CurTime()
self.LastPosCheck = target:GetPos() self.LastPosCheck = target:GetPos()
self.SpawnTimestamp = CurTime()
self.bullseye = ents.Create("npc_ragdoll_target") self.bullseye = ents.Create("npc_ragdoll_target")
self.bullseye:SetPos(target:GetPos()) self.bullseye:SetPos(target:GetPos())
@ -397,26 +394,16 @@ function MODULE:PhysicsSimulate(phys, dt)
return false -- Cut the bullshit return false -- Cut the bullshit
end end
if (death_timer:GetFloat() != -1) and ((CurTime() - self.SpawnTimestamp) > death_timer:GetFloat()) then
target.organism.alive = false
end
if (!target.organism.alive) then if (!target.organism.alive) then
-- If the NPC is dead, they probably aren't coming back; don't bother bringing them back to life -- If the NPC is dead, they probably aren't coming back; don't bother bringing them back to life
self:Remove() self:Remove()
return false -- Cut the bullshit return false -- Cut the bullshit
elseif ( elseif (target.organism.consciousness <= 0.5) or ((target.organism.lleg >= 0.85) and (target.organism.rleg >= 0.85)) then
(target.organism.consciousness <= 0.4) or
((target.organism.lleg >= 0.85) and (target.organism.rleg >= 0.85)) or
(target.organism.spine1 == 1) or
(target.organism.spine2 == 1) or
(target.organism.spine3 == 1)
) then
target.StartDie = cur_time target.StartDie = cur_time
return false return false
end end
if (self.LastPosCheck:DistToSqr(target:GetPos()) > (movement_sensitivity:GetFloat() ^ 2)) then if (self.LastPosCheck:DistToSqr(target:GetPos()) > (32 ^ 2)) then
self.LastPosCheck = target:GetPos() self.LastPosCheck = target:GetPos()
target.StartDie = cur_time target.StartDie = cur_time
end end
@ -452,9 +439,6 @@ function MODULE:PhysicsSimulate(phys, dt)
ent:SetSkin(target:GetSkin()) ent:SetSkin(target:GetSkin())
ent:AddFlags(target.respawn_data.flags)
ent:AddSpawnFlags(target.respawn_data.spawn_flags)
if target.citizentype then if target.citizentype then
ent:SetKeyValue("citizentype", target.citizentype) ent:SetKeyValue("citizentype", target.citizentype)
end end
@ -510,8 +494,7 @@ function MODULE:PhysicsSimulate(phys, dt)
self.unfaker:SetPos(target:GetPos()) self.unfaker:SetPos(target:GetPos())
self.unfaker:SetNWEntity("parent", target) self.unfaker:SetNWEntity("parent", target)
self.unfaker:SetNWEntity("parent_npc", ent) self.unfaker:SetNWEntity("parent_npc", ent)
self.unfaker:SetNWFloat("fake_start", self.FakeUpStart)
self.unfaker:SetNWFloat("fake_end", self.FakeUpEnd)
target:SetRenderMode(RENDERMODE_NONE) target:SetRenderMode(RENDERMODE_NONE)
ent:SetRenderMode(RENDERMODE_NONE) ent:SetRenderMode(RENDERMODE_NONE)

View file

@ -208,11 +208,7 @@ function MODULE:PhysicsSimulate(phys, dt)
-- If the NPC is dead, they probably aren't coming back; don't bother bringing them back to life -- If the NPC is dead, they probably aren't coming back; don't bother bringing them back to life
self:Remove() self:Remove()
return false -- Cut the bullshit return false -- Cut the bullshit
elseif ( elseif (target.organism.consciousness <= 0.3) then
(target.organism.consciousness <= 0.4) or
(target.organism.spine2 == 1) or
(target.organism.spine3 == 1)
) then
return false return false
end end