Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 115 additions & 21 deletions lua/autorun/standpose.lua
Original file line number Diff line number Diff line change
@@ -1,12 +1,74 @@
if game.SinglePlayer() then

if SERVER then

util.AddNetworkString("StandPose_Server")
util.AddNetworkString("StandPoser_Client")

net.Receive("StandPose_Server", function()
local rag = net.ReadEntity()
local ent = net.ReadEntity()
if (rag == ent) or not IsValid(rag) or not IsValid(ent) then return end
if rag:GetClass() ~= "prop_ragdoll" or ent:GetClass() ~= "prop_dynamic" then return end

for i = 0, rag:GetPhysicsObjectCount() - 1 do
local phys = rag:GetPhysicsObjectNum(i)
local b = rag:TranslatePhysBoneToBone(i)
local pos = net.ReadVector()
local ang = net.ReadAngle()
phys:EnableMotion(true)
phys:Wake()
phys:SetPos(pos)
phys:SetAngles(ang)
phys:EnableMotion(false)
phys:Wake()

end
ent:Remove()
end)

end

if CLIENT then

net.Receive("StandPoser_Client", function()
local rag = net.ReadEntity()
local ent = net.ReadEntity()
local PhysObjects = net.ReadInt(8)

net.Start("StandPose_Server")
net.WriteEntity(rag)
net.WriteEntity(ent)
for i = 0, PhysObjects do
local phys = rag:GetPhysicsObjectNum(i)
local b = rag:TranslatePhysBoneToBone(i)
local pos, ang = ent:GetBonePosition(b)
if pos == ent:GetPos() then
local matrix = ent:GetBoneMatrix(b)
if matrix then
pos = matrix:GetTranslation()
ang = matrix:GetAngles()
end
end
net.WriteVector(pos)
net.WriteAngle(ang)
end
net.SendToServer()
end)

end

end

local propt = {}

propt.MenuLabel = "Stand Pose"
propt.Order = 5000

propt.Filter = function( self, ent )
propt.Filter = function( self, ent, ply )
if ( !IsValid( ent ) ) then return false end
if ( ent:GetClass() != "prop_ragdoll" ) then return false end
if ( !gamemode.Call( "CanProperty", ply, "standpose", ent ) ) then return false end
return true
end

Expand All @@ -23,33 +85,65 @@ propt.Receive = function( self, length, player )
if ( !IsValid( rag ) ) then return end
if ( !IsValid( player ) ) then return end
if ( rag:GetClass() != "prop_ragdoll" ) then return end

local tr = util.TraceLine({start = rag:GetPos(),endpos = rag:GetPos() - Vector(0,0,3000),filter = rag})

if ( !properties.CanBeTargeted( rag, player ) ) then return end
if ( !self:Filter( rag, player ) ) then return end

local ragpos = rag:GetPos()
if not rag:IsInWorld() then
local _, max = rag:WorldSpaceAABB()
ragpos.z = max.z
end

local tr = util.TraceLine({start = ragpos, endpos = ragpos - Vector(0, 0, 3000), filter = rag})
if not util.IsInWorld(tr.HitPos) then
tr = util.TraceLine({start = player:EyePos(), endpos = ragpos, filter = {rag, player}})
end

local hpos = tr.HitPos
local ent = ents.Create("prop_dynamic")
ent:SetModel(rag:GetModel())
ent:SetPos(tr.HitPos)
local angle = (tr.HitPos - player:GetPos()):Angle()
ent:SetAngles(Angle(0,angle.y-180,0))
ent:SetPos(hpos)
local min = ent:WorldSpaceAABB()
local diff = hpos.z - min.z
local tool = player:GetTool("ragdollstand")
if tool and tool:GetClientNumber("use_bbox") == 1 then
ent:SetPos(hpos + Vector(0, 0, diff))
end
local angle = (hpos - player:GetPos()):Angle()
ent:SetAngles(Angle(0, angle.y - 180, 0))
ent:Spawn()
for i=0,rag:GetPhysicsObjectCount()-1 do
local phys = rag:GetPhysicsObjectNum(i)
local b = rag:TranslatePhysBoneToBone(i)
local pos,ang = ent:GetBonePosition(b)
phys:EnableMotion(true)
phys:Wake()
phys:SetPos(pos)
phys:SetAngles(ang)
if string.sub(rag:GetBoneName(b),1,4) == "prp_" then

if CLIENT then return true end
local PhysObjects = rag:GetPhysicsObjectCount() - 1

if game.SinglePlayer() then
timer.Simple(0.1, function()
net.Start("StandPoser_Client")
net.WriteEntity(rag)
net.WriteEntity(ent)
net.WriteInt(PhysObjects, 8)
net.Send(player)
end)
else -- if we're in multiplayer, we revert back to the old way stand pose worked, otherwise stuff will get weird
for i = 0, PhysObjects do
local phys = rag:GetPhysicsObjectNum(i)
local b = rag:TranslatePhysBoneToBone(i)
local pos, ang = ent:GetBonePosition(b)
phys:EnableMotion(true)
phys:Wake()
else
phys:EnableMotion(false)
phys:Wake()
phys:SetPos(pos)
phys:SetAngles(ang)
if string.sub(rag:GetBoneName(b), 1, 4) == "prp_" then
phys:EnableMotion(true)
phys:Wake()
else
phys:EnableMotion(false)
phys:Wake()
end
end
end
ent:Remove()
end

end

properties.Add("standpose",propt)
properties.Add("standpose", propt)
123 changes: 74 additions & 49 deletions lua/weapons/gmod_tool/stools/ragdollstand.lua
Original file line number Diff line number Diff line change
Expand Up @@ -4,54 +4,71 @@ TOOL.Name = "Stand Pose"
TOOL.Command = nil
TOOL.ConfigName = nil

TOOL.ClientConVar["use_bbox"] = 0

function TOOL:LeftClick(tr)
if self:GetStage() == 0 then

if !IsValid(tr.Entity) then return false end
if tr.Entity:GetClass() != "prop_ragdoll" then return false end

if CLIENT then return true end

self.SelectedEnt = tr.Entity
self:SetStage(1)
return true

else

local rag = self.SelectedEnt
if !IsValid(rag) then
self:SetStage(0)
return true
end

if CLIENT then return true end

local ent = ents.Create("prop_dynamic")
ent:SetModel(rag:GetModel())
ent:SetPos(tr.HitPos)
local angle = (tr.HitPos - self:GetOwner():GetPos()):Angle()
ent:SetAngles(Angle(0,angle.y-180,0))
ent:Spawn()
for i=0,rag:GetPhysicsObjectCount()-1 do
local phys = rag:GetPhysicsObjectNum(i)
local b = rag:TranslatePhysBoneToBone(i)
local pos,ang = ent:GetBonePosition(b)
phys:EnableMotion(true)
phys:Wake()
phys:SetPos(pos)
phys:SetAngles(ang)
if string.sub(rag:GetBoneName(b),1,4) == "prp_" then
phys:EnableMotion(true)
phys:Wake()

if !IsValid(tr.Entity) then return false end
if tr.Entity:GetClass() != "prop_ragdoll" then return false end

if CLIENT then return true end
self.SelectedEnt = tr.Entity
self:SetStage(1)
return true
else
phys:EnableMotion(false)
phys:Wake()

local rag = self.SelectedEnt
if !IsValid(rag) then
self:SetStage(0)
return true
end
end
ent:Remove()
self:SetStage(0)
return true


local hpos = tr.HitPos
local ent = ents.Create("prop_dynamic")
ent:SetModel(rag:GetModel())
ent:SetPos(hpos)
local min = ent:WorldSpaceAABB()
local diff = hpos.z - min.z
if self:GetClientNumber("use_bbox") == 1 then
ent:SetPos(hpos + Vector(0, 0, diff))
end
local angle = (hpos - self:GetOwner():GetPos()):Angle()
ent:SetAngles(Angle(0, angle.y - 180, 0))
ent:Spawn()

if CLIENT then return true end
local PhysObjects = rag:GetPhysicsObjectCount() - 1
if game.SinglePlayer() then
timer.Simple(0.1, function()
net.Start("StandPoser_Client")
net.WriteEntity(rag)
net.WriteEntity(ent)
net.WriteInt(PhysObjects, 8)
net.Send(self:GetOwner())
end)
else -- if we're in multiplayer, we revert back to the old way stand pose worked, otherwise stuff will get weird
for i = 0, PhysObjects do
local phys = rag:GetPhysicsObjectNum(i)
local b = rag:TranslatePhysBoneToBone(i)
local pos, ang = ent:GetBonePosition(b)
phys:EnableMotion(true)
phys:Wake()
phys:SetPos(pos)
phys:SetAngles(ang)
if string.sub(rag:GetBoneName(b), 1, 4) == "prp_" then
phys:EnableMotion(true)
phys:Wake()
else
phys:EnableMotion(false)
phys:Wake()
end
end
ent:Remove()
end
self:SetStage(0)
return true

end
end

Expand All @@ -65,9 +82,17 @@ end

if CLIENT then

language.Add("tool.ragdollstand.name","Stand Pose")
language.Add("tool.ragdollstand.desc","Position ragdolls in a standing pose.")
language.Add("tool.ragdollstand.0","Left Click to select a ragdoll.")
language.Add("tool.ragdollstand.1","Now click on a position where you want the ragdoll to stand or Right Click to cancel.")
language.Add("tool.ragdollstand.name", "Stand Pose")
language.Add("tool.ragdollstand.desc", "Position ragdolls in a standing pose.")
language.Add("tool.ragdollstand.0", "Left Click to select a ragdoll.")
language.Add("tool.ragdollstand.1", "Now click on a position where you want the ragdoll to stand or Right Click to cancel.")

function TOOL.BuildCPanel(CPanel)
local CB = vgui.Create("DCheckBoxLabel", CPanel)
CB:SetText("Use Bounding Box")
CB:SetConVar("ragdollstand_use_bbox")
CB:SetDark(true)
CPanel:AddItem(CB)
end

end
end