Compare commits

..

No commits in common. "72c451540218b065e7b818d4e488688670c9ade5" and "d9415d880f682d0a4b5030dc089bdb49542ffeca" have entirely different histories.

8 changed files with 93 additions and 384 deletions

View file

@ -4,8 +4,6 @@ Adds better NPC integration for the Garry's Mod addon Z-City. While Z-City has a
- 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.
- 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.
- 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 remover.
@ -14,9 +12,9 @@ This addon is based off of Kazarei's Euphoria, which in turn is a fork of Fedhor
## Known issues
- Bandages, tourniquets, etc. that are on the ragdoll or NPC body will not be there when they get back up. Don't know how to fix this right now, though if anyone experienced with Z-City's codebase would know how to I would appreciate knowing.
- The NPC getting up animation is quite ridiculous and a little ugly. Honestly, getting it to work that much was a struggle in itself and I'm terrified of trying to do anything more than that. If anyone else would like to do that, however, feel free to create a discussion and I can send you the source code link.
- Occasionally the game thinks that all damage is bullet damage? God knows why. I'll figure it out eventually.
- Bandages, tourniquets, etc. that are on the ragdoll or NPC body will not be there when they get back up. Don't know how to fix this unfortunately.
- NPCs currently instantly get up, with no animation. I plan on remedying this in the future.
- Enemy NPCs will not target living downed NPCs like how they do players. This will be fixed.
## Compatibility
@ -30,27 +28,10 @@ It is, however, not compatbile with:
- Most mods that modify the behavior of death ragdolls (Reagdoll, Artagdoll, especially Fedhoria.)
- Mods that automatically remove death ragdolls (it will delete all ragdolled NPCs, even if they're still alive! Try the built-in automatic corpse removal instead.)
## Todo list
## Future plans
Urgent shit:
No guarantees any of this will become real.
- Large amounts of damage (such as shotguns) fling NPC ragdolls to ridiculous lengths, sometimes severely injuring the player. While this is absolutely fucking hilarious, it also isn't the best experience.
Stuff to do:
- Facial expressions
- Actual specific reactions to being on fire / falling / lots of pain
- Wound holding
- NPCs should not stumble when dead
- Generally improve stumbling
Stuff to fix possibly:
- NPC targeting works, but works really weirdly (sometimes it just. keeps targeting corpses when it shouldn't.) Why? Who knows!!!!
- Look into improving the unfake animation? Really scared to try and touch it again but it would be worthwhile
Post release ideas:
- Localization support for other languages
- ReaSFX integration would probably be nice. I mean there's so many SFX packs to choose from, so I don't even have to pack it in
- To be entirely honest Fedhoria isn't the best addon out there for euphoria physics. Maybe rebase to another addon (or alternatively build a new one?)
- NPCs will back out of combat when injured.
- Friendly NPCs can heal each other.
- NPCs can heal themselves.

View file

@ -37,12 +37,6 @@ local function PopulateRagdollSBXToolMenu(pnl)
pnl:NumSlider("Wound grab time", "zcnpci_woundgrab_time", 0, 10, 3)
pnl:ControlHelp("How long the ragdoll should hold its wound.")
pnl:CheckBox("Allow getting up", "zcnpci_unfake_enabled")
pnl:ControlHelp("If enabled, NPCs will get back up if able.")
pnl:NumSlider("Get up time", "zcnpci_unfake_time", 0, 5, 3)
pnl:ControlHelp("How long the getting up animation lasts. Setting to 0 will disable the getting up animation.")
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.")

View file

@ -97,7 +97,7 @@ end
function ENT:Initialize()
if !self.Module then return end
if self.Module.Model then self:SetModel(self.Module.Model) end
self:SetModel(self.Module.Model)
for key, value in pairs(self.Module) do
if !self[key] then

View file

@ -1,99 +0,0 @@
AddCSLuaFile()
ENT.Type = "ai"
ENT.Base = "base_ai"
ENT.AutomaticFrameAdvance = true
local debug_show_ragdoll_targets = CreateConVar("zcnpci_debug_show_ragdoll_targets", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local function UpdateRelationship(ent, me)
if !IsValid(ent) or !ent:IsNPC() then return end
if ent:Disposition(me.dummy_entity) == D_HT then
ent:AddEntityRelationship(me, D_HT, -1)
end
end
local function RemoveRelationship(ent, me)
if !IsValid(ent) or !ent:IsNPC() then return end
if ent:Disposition(me.dummy_entity) == D_HT then
ent:AddEntityRelationship(me, D_NU, -1)
ent:ClearEnemyMemory(me)
if ent:GetEnemy() == me then
ent:SetEnemy(nil)
ent:ClearSchedule()
end
end
end
function ENT:Initialize()
if SERVER then
self:SetModel("models/maxofs2d/hover_basic.mdl")
self:SetCollisionGroup(COLLISION_GROUP_DEBRIS)
self:SetHullType(HULL_TINY_CENTERED)
self:SetNoDraw(!debug_show_ragdoll_targets:GetBool())
self.dummy_entity = ents.Create(self.ragdoll_to_follow.class_in_previous_life)
self.last_stop_targeting = nil
hook.Add("OnEntityCreated", "zcnpci-"..self:GetCreationID(), function(new_entity)
if !IsValid(new_entity) or !new_entity:IsNPC() then return end
if !self.last_stop_targeting then
UpdateRelationship(new_entity, self)
end
end)
end
end
function ENT:Think()
if SERVER then
local ragdoll = self.ragdoll_to_follow
if !IsValid(ragdoll) then return end
self:SetPos(ragdoll:GetPos())
self:SetNoDraw(!debug_show_ragdoll_targets:GetBool())
if !ragdoll.organism then return true end
local should_stop_targeting = (
(ragdoll.organism.consciousness <= 0.4) or
(ragdoll.organism.critical)
)
if should_stop_targeting != self.last_stop_targeting then
self.last_stop_targeting = should_stop_targeting
if should_stop_targeting then
self:SetColor(Color(255, 0, 0))
for i,ent in ipairs(ents.GetAll()) do
RemoveRelationship(ent, self)
end
else
self:SetColor(Color(0, 255, 0))
for i,ent in ipairs(ents.GetAll()) do
UpdateRelationship(ent, self)
end
end
end
self:NextThink(CurTime())
end
return true
end
function ENT:OnRemove()
if SERVER then
for i,ent in ipairs(ents.GetAll()) do
RemoveRelationship(ent, self)
end
self.dummy_entity:Remove()
hook.Remove("OnEntityCreated", "zcnpci-"..self:GetCreationID())
end
end

View file

@ -19,9 +19,7 @@ local treat_near_death_as_dead = CreateConVar("zcnpci_treat_near_death_as_dead"
local allow_extended_base_npcs = CreateConVar("zcnpci_allow_extended_base_npcs", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local allow_modded_npcs = CreateConVar("zcnpci_allow_modded_npcs", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local auto_enable_humanoid_npcs = CreateConVar("zcnpci_auto_enable_humanoid_npcs", 1, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local modded_npc_whitelist = CreateConVar("zcnpci_modded_npc_whitelist", "npc_example_class", bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local debug_ragdoll_all = CreateConVar("zcnpci_debug_ragdoll_all", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local modded_npc_whitelist = CreateConVar("zcnpci_modded_npc_whitelist", "nb_example", bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
-- The way I have to set up the npc whitelist client-side makes it so the host can't configure it without console commands, so we have to do this shit
local set_modded_npc_whitelist = concommand.Add("zcnpci_set_modded_npc_whitelist", function(ply, cmd, args)
@ -32,6 +30,8 @@ local set_modded_npc_whitelist = concommand.Add("zcnpci_set_modded_npc_whitelis
modded_npc_whitelist:SetString(args[1])
end)
local debug_ragdoll_all = CreateConVar("zcnpci_debug_ragdoll_all", 0, bit.bor(FCVAR_ARCHIVE, FCVAR_REPLICATED))
local last_dmgpos = {}
local last_hitgroup = {}
local last_attacker = {}
@ -121,11 +121,6 @@ hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll)
ragdoll:GetPhysicsObject():SetVelocity(ent.npcfakeknockback)
end
local velocity = ragdoll:GetPhysicsObject():GetVelocity()
print(velocity)
print(max_clamp)
-- For some reason, citizen types such as rebels, medics, refugees, etc. use a keyvalue.
-- That keyvalue does not transfer over to the ragdoll, despite it looking like the NPC,
-- and you have to manually save it to the ragdoll to be able to make it work.
@ -133,11 +128,9 @@ hook.Add("CreateEntityRagdoll", "zcnpci", function(ent, ragdoll)
ragdoll.citizentype = ent:GetInternalVariable("citizentype")
timer.Simple(0, function()
if !IsValid(ragdoll) then return end
ragdoll.organism.alive = true
ragdoll:SetRenderMode(RENDERMODE_NORMAL)
if !IsValid(ragdoll) then return end
zcnpci.StartModule(ragdoll, "stumble_legs", phys_bone, lpos)
last_dmgpos[ent] = nil
@ -146,44 +139,36 @@ end)
hook.Add("HomigradDamage", "zcnpci", function(ent, dmginfo)
if !enabled:GetBool() or !IsValid(dmginfo) then return end
if !ent:IsNPC() then
if !ent.organism or !ent.StartDie then return end
if dmginfo:IsDamageType(DMG_BULLET + DMG_BUCKSHOT + DMG_BLAST + DMG_CLUB + DMG_SLASH + DMG_GENERIC) then
-- Reset ragdoll get up timer -- don't want someone getting up mid-curbstomp
ent.StartDie = CurTime()
print("I'M HIT FOR "..dmginfo:GetDamage())
end
return
end
last_dmgpos[ent] = dmginfo:GetDamagePosition()
last_dmgpos[ent] = dmginfo:GetDamage()
last_attacker[ent] = dmginfo:GetAttacker()
if dmginfo:IsDamageType(DMG_BULLET + DMG_BUCKSHOT + DMG_BLAST) then
if dmginfo:GetDamage() > 3 then
table.insert(npcs_to_fake, ent)
local attacker_angle = dmginfo:GetAttacker():EyeAngles()
local normal = attacker_angle:Forward(normal)
ent.npcfakeknockback = normal * dmginfo:GetDamage() * 0
end
elseif dmginfo:IsDamageType(DMG_CLUB + DMG_SLASH) then
local attacker = dmginfo:GetAttacker()
if !IsValid(attacker) then return end
local fists = attacker:HasWeapon("weapon_hands_sh")
if !fists then fists = dmginfo:GetAttacker():HasWeapon("weapon_hg_coolhands") end
local fists = dmginfo:GetAttacker():GetWeapon("weapon_hands_sh")
if !IsValid(fists) then fists = dmginfo:GetAttacker():GetWeapon("weapon_hg_coolhands") end
local attacker = dmginfo:GetAttacker()
print(fists.InLegKick)
-- Kicks should knock NPCs down
if IsValid(dmginfo:GetInflictor()) and fists and attacker.InLegKick and ((attacker.InLegKick + 0.1) > CurTime()) then
if IsValid(dmginfo:GetInflictor()) and IsValid(fists) and attacker.InLegKick and ((attacker.InLegKick + 0.1) > CurTime()) then
table.insert(npcs_to_fake, ent)
print("ADD TO LIST!!!")
local attacker_angle = dmginfo:GetAttacker():EyeAngles()
@ -302,6 +287,8 @@ hook.Add("Tick", "zcnpci", function()
end
end
end
PrintTable(npcs_to_fake)
-- NPC faking is in a seperate area because we want NPCs to ragdoll as soon as they can
for i,ent in pairs(npcs_to_fake) do
@ -317,6 +304,13 @@ hook.Add("Tick", "zcnpci", function()
end
end)
--[[hook.Add("OnNPCKilled", "Fedhoria", function(ent, attacker, inflictor)
if (!enabled:GetBool() or !npcs:GetBool()) then return end
if (!ent:IsNPC() or dmginfo:GetDamage() < ent:Health()) then return end
last_dmgpos[ent] = dmginfo:GetDamagePosition()
end)]]
hook.Add("OnEntityCreated", "zcnpci", function(ent)
if !IsValid(ent) then return end

View file

@ -40,31 +40,6 @@ local twitchable_bone_names = {
"ValveBiped.Bip01_L_Foot"
}
local fakeup_bone_names = {
"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 fakeup_bone_down_names = {
"ValveBiped.Bip01_R_Forearm",
"ValveBiped.Bip01_L_Forearm",
"ValveBiped.Bip01_R_Thigh",
"ValveBiped.Bip01_L_Thigh",
}
-- Local Copies of Functions for Optimization
local math_Clamp = math.Clamp
local math_Rand = math.Rand
@ -94,11 +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", "5", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Down time!!!!!!!!!")
-- Unfaking
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 minimum_down_time = CreateConVar("zcnpci_down_time", "3", {FCVAR_ARCHIVE, FCVAR_REPLICATED}, "Down time!!!!!!!!!")
--[[-------------------------------------------------------------------------
Tug function
@ -194,13 +165,7 @@ function MODULE:Init()
self.AnimationRollEndTime = 0
self.StopProcessing = false
self.LastThink = CurTime()
self.LastFakeUpCheck = CurTime()
self.bullseye = ents.Create("npc_ragdoll_target")
self.bullseye:SetPos(target:GetPos())
self.bullseye.ragdoll_to_follow = target
self.bullseye:Spawn()
self.bullseye:Activate()
self.LastPhysProcess = CurTime()
-- Add damping to all bones.
local phys = self:GetPhysicsObject()
@ -224,21 +189,12 @@ end
---------------------------------------------------------------------------]]
function MODULE:Think()
--if (CurTime() - self.LastThink) < 1 then return end
local target = self:GetTarget()
if (CurTime() - self.LastThink) < 1 then return end
if !IsValid(target) then return end
self.LastThink = CurTime()
local phys = target:GetPhysicsObject()
if target.FakeUp then
print("fucking it")
local parent = self.FakeParent
if !IsValid(parent) then return end
--parent:FrameAdvance(FrameTime())
end
if !IsValid(phys) or !phys:IsAsleep() then return end
@ -286,84 +242,15 @@ end
Physics Simulation Hook (FIXED)
---------------------------------------------------------------------------]]
function MODULE:PhysicsSimulate(phys, dt)
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(); self.bullseye:Remove(); return false end
if target.FakeUp then
local parent = self.FakeParent
if !IsValid(parent) then
self:Remove()
return false
end
if !self.ModelBoneList then
self.ModelBoneList = {}
local i = 0
while i < target:GetBoneCount() do
table.insert(self.ModelBoneList, target:GetBoneName(i))
i = i + 1
end
end
local animation_progress = (CurTime() - self.FakeUpStart) / (self.FakeUpEnd - self.FakeUpStart)
--[[util.TraceLine({
start = parent:GetPos() + Vector(0, 128, 0),
endpos = parent:GetPos(),
collisiongroup = COLLISION_GROUP_NPC
})]]
for i,v in pairs(fakeup_bone_down_names) do
local object = target:GetPhysicsObjectNum(target:TranslateBoneToPhysBone(target:LookupBone(v)))
object:SetMass(0.5)
end
for i,v in pairs(fakeup_bone_names) do
local object = target:GetPhysicsObjectNum(target:TranslateBoneToPhysBone(target:LookupBone(v)))
local parent_bone = parent:LookupBone(v)
if parent_bone == -1 then continue end
local parent_bone_matrix = parent:GetBoneMatrix(parent_bone)
if !parent_bone_matrix then continue end
local parent_bone_pos, parent_bone_angle = parent_bone_matrix:GetTranslation(), parent_bone_matrix:GetAngles()
parent_bone_angle.y = parent_bone_angle.y + 90
local shadow_data = {
secondstoarrive = 0.01,
pos = LerpVector(animation_progress, object:GetPos(), parent_bone_pos),
angle = LerpAngle(animation_progress, object:GetAngles(), parent_bone_angle),
maxspeed = 400,
maxangular = 2000,
maxspeeddamp = 60,
maxangularspeeddamp = 600,
}
-- 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()
object:EnableGravity(false)
object:Wake()
i = i + 1
end
return false
end
--print((CurTime() - self.LastPhysProcess) < 0.05)
--if (CurTime() - self.LastPhysProcess) < (1 /) then return false end())
phys:Wake()
--self.bullseye:SetAngles(target:EyeAngles())
if not IsValid(target) then self:Remove(); return false end
target.is_npc_corpse = true
@ -385,117 +272,71 @@ function MODULE:PhysicsSimulate(phys, dt)
if !target.organism then
self:Remove()
self.bullseye:Remove()
return false -- Cut the bullshit
end
if (!target.organism.alive) then
-- If the NPC is dead, they probably aren't coming back; don't bother bringing them back to life
self:Remove()
self.bullseye:Remove()
return false -- Cut the bullshit
elseif (target.organism.consciousness <= 0.5) or ((target.organism.lleg >= 0.85) and (target.organism.rleg >= 0.85)) then
target.StartDie = cur_time
return false
end
if ((CurTime() - self.LastFakeUpCheck) >= 1.0) and (can_unfake:GetBool()) then
self.LastFakeUpCheck = CurTime()
-- Getting up
-- Don't need to check for consciousness and the like because we've done it already above
if (
(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) and
(target.organism.consciousness > 0.65) and
!target:IsOnFire()
) then
local ent = ents.Create(target.class_in_previous_life)
ent:SetPos(target:GetPos())
ent:SetModel(target:GetModel())
ent:SetMaterial(target:GetMaterial())
-- This basically checks if the NPC will be in collision with anything when it spawns.
-- Side note: the mins and maxs values are slightly larger than the default npc_citizen
-- hitboxes, mostly because I assume that most humanoid NPCs will be around that size.
local tracehull = util.TraceHull({
start = target:GetPos(),
endpos = target:GetPos(),
mins = Vector(-20, -20, 0),
maxs = Vector(20, 20, 84),
mask = MASK_NPCSOLID,
filter = { target }
})
ent:SetSkin(target:GetSkin())
if (
(!tracehull.Hit) and
(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) and
(target.organism.consciousness > 0.65) and
!target:IsOnFire()
) then
local ent = ents.Create(target.class_in_previous_life)
ent:SetPos(target:GetPos())
ent:SetModel(target:GetModel())
ent:SetMaterial(target:GetMaterial())
if target.citizentype then
ent:SetKeyValue("citizentype", target.citizentype)
end
for i = 0, target:GetNumBodyGroups() - 1 do
ent:SetBodygroup(i, target:GetBodygroup(i))
end
ent:Spawn()
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
ent:CallOnRemove("organism", hg.organism.Remove, ent)
hg.send_bareinfo(ent.organism)
ent:SetSkin(target:GetSkin())
if target.citizentype then
ent:SetKeyValue("citizentype", target.citizentype)
end
for i = 0, target:GetNumBodyGroups() - 1 do
ent:SetBodygroup(i, target:GetBodygroup(i))
end
ent:Spawn()
target:Remove()
end)
ent:SetNotSolid(true)
ent:SetNPCState(NPC_STATE_NONE)
self.StopProcessing = true
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
target.organism = nil
ent:CallOnRemove("organism", hg.organism.Remove, ent)
hg.send_bareinfo(ent.organism)
ent:SetSkin(target:GetSkin())
for i = 0, target:GetNumBodyGroups() - 1 do
ent:SetBodygroup(i, target:GetBodygroup(i))
end
end)
target.FakeUp = true
self.FakeParent = ent
self.FakeUpTime = unfake_time:GetFloat()
self.FakeUpEnd = CurTime() + self.FakeUpTime
self.FakeUpStart = CurTime()
ent:SetAngles(Angle(0, math.random(-180, 180), 0))
local phys = target:GetPhysicsObject()
phys:EnableGravity(false)
target:SetNotSolid(true)
target:SetMoveType(MOVETYPE_NONE)
ent:SetRenderMode(RENDERMODE_NONE)
timer.Simple(self.FakeUpTime, function()
if !IsValid(ent) then return end
ent:SetNotSolid(false)
ent:SetNPCState(NPC_STATE_IDLE)
ent:SetRenderMode(RENDERMODE_NORMAL)
target:Remove()
self:Remove()
end)
self.bullseye:Remove()
return false
end
self:Remove()
return false
end
local phys_bone_id = phys:GetID()
@ -563,8 +404,6 @@ end
function MODULE:OnRemove()
local timer_name = "Fedhoria_FallingLegs_Twitch_" .. self:EntIndex()
timer_Remove(timer_name)
if IsValid(self.bullseye) then self.bullseye:Remove() end
end
--[[-------------------------------------------------------------------------

View file

@ -123,7 +123,7 @@ function MODULE:Init()
if seq then self:ResetSequence(seq) end
local target = self:GetTarget()
self:SetPlaybackRate(1)
self.LastCollideTime = 0
self.LastGroundCollideTime = 0
@ -170,10 +170,7 @@ end
function MODULE:PhysicsSimulate(phys, dt)
local cur_time = CurTime()
local target = self:GetTarget()
if !IsValid(target) then self:Remove(); return false end -- если цели нет, то идем нахуй
if !target.organism then self:Remove(); return false end
if target.FakeUp then self.AnimationRollEndTime = 0; return false end
if not IsValid(target) then self:Remove(); return false end -- если цели нет, то идем нахуй
-- проверка на физику
if cur_time < self.AnimationRollEndTime then

View file

@ -279,8 +279,6 @@ local trace = {output={}}
local tr = trace.output
function MODULE:PhysicsSimulate(phys, dt)
if self.FakeUp then return end
local phys_bone = phys:GetID()
local target = self:GetTarget()
@ -293,11 +291,6 @@ function MODULE:PhysicsSimulate(phys, dt)
local st = stumble_time:GetFloat()
-- End stumbling if player is dead
if !target.organism or !target.organism.alive then
st = 0
end
if (st <= 0) then
self:Remove()
return false
@ -305,6 +298,16 @@ function MODULE:PhysicsSimulate(phys, dt)
local f = 1 - (CurTime() - self.Created) / st
--RagMod Reworked support
if ragmod and ragmod:IsRagmodRagdoll(target) then
local owner = target:GetOwningPlayer()
if !IsValid(owner) or !owner:Alive() then
f = 0
else
f = 1
end
end
if (f <= 0) then
self:Remove()
return false