zcnpci/lua/entities/npc_ragdoll_unfaker.lua
2026-06-04 13:03:20 -04:00

130 lines
4.2 KiB
Lua

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",
}
-- 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()
if SERVER then
print("I AM SERVERSIDE")
self:SetModel("models/dav0r/hoverball.mdl")
end
if CLIENT then
print("I AM CLIENTSIDE")
end
end
function ENT:Think()
if CLIENT then
hook.Add("physics")
local old_ragdoll = self:GetNWEntity("parent")
local old_npc = self:GetNWEntity("parent_npc")
if IsValid(old_ragdoll) and IsValid(old_npc) then
local ragdoll = self.ragdoll
if !self.ready_to_animate then
self.ragdoll = ClientsideRagdoll(old_ragdoll:GetModel())
ragdoll = self.ragdoll
self.ragdoll:SetNoDraw(false)
self.ragdoll:DrawShadow(true)
SetRagdollPos(self.ragdoll, old_ragdoll:GetPos())
print(self.ragdoll)
print("SHOW UP YOU PIECE OF SHIT")
for i, name in pairs(bones_to_animate) do
local object = ragdoll:GetPhysicsObjectNum(ragdoll:TranslateBoneToPhysBone(ragdoll:LookupBone(name)))
local parent_object = old_ragdoll:GetBoneMatrix(old_ragdoll:LookupBone(name))
print(old_ragdoll)
--if !IsValid(parent_object) then continue end
object:SetPos(parent_object:GetTranslation())
object:SetAngles(parent_object:GetAngles())
end
self.ready_to_animate = true
end
local fake_start = self:GetNWFloat("fake_start")
local fake_end = self:GetNWFloat("fake_end")
local progress = (CurTime() - fake_start) / (fake_end - fake_start)
for i, name in pairs(bones_to_animate) do
local object = ragdoll:GetPhysicsObjectNum(ragdoll:TranslateBoneToPhysBone(ragdoll:LookupBone(name)))
local parent_bone = old_npc:LookupBone(name)
if parent_bone == -1 then continue end
local parent_bone_matrix = old_npc: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()
local old_bone_pos, old_bone_angle = object:GetPos(), object:GetAngles()
--parent_bone_angle.y = parent_bone_angle.y + 90
local shadow_data = {
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
self:NextThink(CurTime() + 0.1)
return true
end
function ENT:OnRemove()
if CLIENT then
if self.ragdoll then
self.ragdoll:Remove()
end
end
end