How to create a rigid ragdoll with similar pose to a player?

I would like to create a rigid ragdoll in the same position as a player, with a similar position and pose. I was previously attempting to make the ragdoll rigid by modified code from this old tool that moved ragdolls without changing their pose, but to no avail.


TOOL.AddToMenu		= false
TOOL.Category		= "Poser"
TOOL.Name			= "#Statue"
TOOL.Command		= nil
TOOL.ConfigName		= nil


TOOL.ClientConVar[ "unfreeze" ] = "1"

function TOOL:LeftClick( trace )

	if (!trace.Entity) then return false end
	if (!trace.Entity:IsValid()) then return false end
	if (trace.Entity:IsPlayer()) then return false end	
	if (trace.Entity:GetClass() != "prop_ragdoll" ) then return false end
	
	if ( CLIENT ) then return true end
	
	if (trace.Entity:GetPhysicsObjectCount() < 2 ) then return false end
		
	local ent = trace.Entity
	local unfreeze = utilx.tobool( self:GetClientNumber( "unfreeze" ) )
		
	// If it already has a StatueInfo table then it's already statued
	if ( ent:GetTable().StatueInfo != nil )  then return false end
	
	ent:GetTable().StatueInfo = {}
	ent:GetTable().StatueInfo.Welds = {}
	
	local bones = ent:GetPhysicsObjectCount()
	
	local forcelimit = 0
	
	// Weld each physics object together
	for bone=1, bones do
	
		local bone1 = bone - 1
		local bone2 = bones - bone
		
		// Don't do identical two welds
		if ( !ent:GetTable().StatueInfo.Welds[bone2] ) then
		
			local constraint1 = constraint.Weld( ent, ent, bone1, bone2, forcelimit )
			
			if ( constraint1 ) then
			
				ent:GetTable().StatueInfo.Welds[bone1] = constraint1
				self:GetOwner():AddCleanup( "constraints", constraint1 )
			
			end
			
		end
		
		local constraint2 = constraint.Weld( ent, ent, bone1, 0, forcelimit )
		
		if ( constraint2 ) then
		
			ent:GetTable().StatueInfo.Welds[bone1+bones] = constraint2
			self:GetOwner():AddCleanup( "constraints", constraint2 )
		
		end
		
		local effectdata = EffectData()
			 effectdata:SetOrigin( ent:GetPhysicsObjectNum( bone1 ):GetPos() )
			 effectdata:SetScale( 1 )
			 effectdata:SetMagnitude( 1 )
		util.Effect( "GlassImpact", effectdata, true, true )
		
	end
	
	if ( unfreeze == true ) then
	
		for bone=1,bones do
		
			local bone1 = bone - 1

			ent:GetPhysicsObjectNum( bone1 ):EnableMotion( true )
			ent:GetPhysicsObjectNum( bone1 ):Wake()
			
		end
		
	end
	
	return true

end


function TOOL:RightClick( trace )

	if (!trace.Entity) then return end
	if (!trace.Entity:IsValid()) then return end
	if (trace.Entity:IsPlayer()) then return end	
	if (trace.Entity:GetClass() != "prop_ragdoll" ) then return false end
	
	if ( CLIENT ) then return true end
	
	if (trace.Entity:GetPhysicsObjectCount() < 2 ) then return false end
	if (trace.Entity:GetTable().StatueInfo == nil )  then return false end
	
	local ent = trace.Entity

	
	// Remove each weld
	for key, val in pairs (ent:GetTable().StatueInfo.Welds) do
	
		if ( val && val:IsValid() ) then val:Remove() end
		
	end
	
	// Delete the statue table - it's no longer a statue
	ent:GetTable().StatueInfo = nil
	
	local bones = ent:GetPhysicsObjectCount()
	
	for bone=1, bones do
		local bone1 = bone - 1
		local effectdata = EffectData()
			 effectdata:SetOrigin( ent:GetPhysicsObjectNum( bone1 ):GetPos() )
			 effectdata:SetScale( 1 )
			 effectdata:SetMagnitude( 1 )
		util.Effect( "WheelDust", effectdata, true, true )		
	end
	
	return true
	
end



I was wondering if there was any relatively simple solution to this quandry, and if not, I can simply fall back on attempting to create constraints between the bones of the ragdoll. Thanks!

I don’t know how much access we have to a player’s playermodel’s pose, but here is some code I used to duplicate a server-side ragdoll to a client-side ragdoll, before I learned of

Entity:BecomeRagdollOnClient which did 90% of the work for me.

[lua]local csrag = ClientsideRagdoll(ent:GetModel(), ent:GetRenderGroup())

csrag:SetPos(ent:GetPos())
csrag:SetAngles(ent:GetAngles())

for b = 0, csrag:GetPhysicsObjectCount()-1 do
csrag:GetPhysicsObjectNum(b):SetPos(ent:GetPhysicsObjectNum(b):GetPos())
csrag:GetPhysicsObjectNum(b):SetAngles(ent:GetPhysicsObjectNum(b):GetAngles())
csrag:GetPhysicsObjectNum(b):EnableMotion(false)
end

csrag:SetNoDraw(false) – why the fuck is it true by default?

– for bone = 0, ent:GetBoneCount()-1 do
– csrag:SetBonePosition(bone, ent:GetBonePosition(bone)) – does both position and angles :slight_smile:
– end

for bone = 0, ent:GetBoneCount()-1 do
csrag:ManipulateBoneAngles(bone, ent:GetManipulateBoneAngles(bone))
csrag:ManipulateBonePosition(bone, ent:GetManipulateBonePosition(bone))
csrag:ManipulateBoneJiggle(bone, ent:GetManipulateBoneJiggle(bone))
csrag:ManipulateBoneScale(bone, ent:GetManipulateBoneScale(bone))
end

csrag:SetupBones()
– csrag:GetPhysicsObject():Sleep()[/lua]

I don’t remember how it works, why it works, what exactly each part does, or anything. You’ll have to figure that out yourself. What I DO remember is that face-posing doesn’t work because clientside ragdolls don’t support flex, but if you’re adapting this to server-side ragdolls, add some code to copy over the flex values with

Entity:SetFlexWeight and related functions.

Edit: wait, is your problem about creating and positioning the ragdoll, or just making it rigid? As far as rigidness goes, I’m pretty sure that there’s no way to do it other than making lots of welds. See the ‘Statue’ source code: https://github.com/garrynewman/garrysmod/blob/master/garrysmod/lua/autorun/properties/statue.lua