Dead ragdoll stands up with GettingUp, Platformstanding HumanoidStateTypes disabled

Hello. This is my first devforum post (yay)

I am struggling with getting a dead NPC ragdoll to stay in ragdoll and not stand up right. So far I have gotten closer to the fix, but it still manages to stand up.

The code I’m willing to share:

function setupJoints(character)
	for i, motor6D in ipairs(character:GetDescendants()) do
		local r = character.PrimaryPart:FindFirstChild("Root")
		if r then
			r:Destroy()
		end
		if motor6D:IsA("Motor6D") and motor6D.Part0.Name ~= "HumanoidRootPart" then
			local attach0 = Instance.new("Attachment")
			local attach1 = Instance.new("Attachment")
			local ballSocket = Instance.new("BallSocketConstraint")
			local noCollision = Instance.new("NoCollisionConstraint")
			local isRoot = motor6D.Part0 == character.PrimaryPart
			ballSocket.Name = "HumanJoint"
			if not isRoot then
				ballSocket.LimitsEnabled = true
				ballSocket.TwistLimitsEnabled = true
				ballSocket.Restitution = 0.1--0.678--.567--.843
			end
			ballSocket.Attachment0 = attach0
			ballSocket.Attachment1 = attach1
			ballSocket.Parent = motor6D.Part0
			attach0.CFrame = motor6D.C0
			attach1.CFrame = motor6D.C1
			attach0.Parent = motor6D.Part0
			attach1.Parent = motor6D.Part1
			attach0.Name = "Attachment0Ragdoll"
			attach1.Name = "Attachment1Ragdoll"
			noCollision.Name = motor6D.Part0.Name.."And"..motor6D.Part1.Name
			noCollision.Part0 = motor6D.Part0
			noCollision.Part1 = motor6D.Part1
			noCollision.Parent = motor6D.Part0
			if motor6D.Name == "LeftKnee" then
				local leftKnee = Instance.new("HingeConstraint")
				motor6D.Part0:FindFirstChild("HumanJoint"):Destroy()
				leftKnee.Name = "Knee"
				leftKnee.Attachment0 = attach0
				leftKnee.Attachment1 = attach1
				leftKnee.Parent = motor6D.Part0
				leftKnee.LimitsEnabled = true
				leftKnee.UpperAngle = -10
				leftKnee.LowerAngle = -135
				leftKnee.AngularResponsiveness = 0.5
			elseif motor6D.Name == "RightKnee" then
				local rightKnee = Instance.new("HingeConstraint")
				motor6D.Part0:FindFirstChild("HumanJoint"):Destroy()
				rightKnee.Name = "Knee"
				rightKnee.Attachment0 = attach0
				rightKnee.Attachment1 = attach1
				rightKnee.Parent = motor6D.Part0
				rightKnee.LimitsEnabled = true
				rightKnee.UpperAngle = -10
				rightKnee.LowerAngle = -135
				rightKnee.AngularResponsiveness = 0.5
			elseif motor6D.Name == "LeftHip" then
				ballSocket.UpperAngle = 60
				ballSocket.TwistLowerAngle = -3
				ballSocket.TwistUpperAngle = 3
			elseif motor6D.Name == "RightHip" then
				ballSocket.UpperAngle = 60
				ballSocket.TwistLowerAngle = -3
				ballSocket.TwistUpperAngle = 3
			elseif motor6D.Part0.Name == "LowerTorso" then
				ballSocket.UpperAngle = 15
				ballSocket.TwistUpperAngle = 1
				ballSocket.TwistLowerAngle = -1
			elseif motor6D.Part0.Name == "UpperTorso" then
				ballSocket.UpperAngle = -10
			elseif motor6D.Name == "LeftAnkle" or motor6D.Name == "RightAnkle" then
				local hinge = Instance.new("HingeConstraint")
				motor6D.Part0:FindFirstChild("HumanJoint"):Destroy()
				hinge.Attachment0 = attach0
				hinge.Attachment1 = attach1
				hinge.Parent = motor6D.Part0
				hinge.LimitsEnabled = true
				hinge.UpperAngle = 0
				hinge.Restitution = 0
				hinge.LowerAngle = -45
				hinge.AngularResponsiveness = 0.5
			elseif motor6D.Name == "LeftWrist" or motor6D.Name == "RightWrist" then
				local hinge = Instance.new("HingeConstraint")
				motor6D.Part0:FindFirstChild("HumanJoint"):Destroy()
				hinge.Attachment0 = attach0
				hinge.Attachment1 = attach1
				hinge.Parent = motor6D.Part0
				hinge.LimitsEnabled = true
				hinge.UpperAngle = 20
				hinge.Restitution = 0
				hinge.LowerAngle = -20
				hinge.AngularResponsiveness = 0.5
			elseif motor6D.Name == "LeftShoulder" then
				ballSocket.UpperAngle = 30
				ballSocket.TwistLowerAngle = -30
				ballSocket.TwistUpperAngle = 30
			elseif motor6D.Name == "RightShoulder" then
				ballSocket.UpperAngle = 30
				ballSocket.TwistLowerAngle = -30
				ballSocket.TwistUpperAngle = 30
			elseif motor6D.Name == "LeftElbow" then
				ballSocket.LimitsEnabled = true
				ballSocket.TwistLimitsEnabled = true
				ballSocket.UpperAngle = 165
				ballSocket.TwistLowerAngle = 0
				ballSocket.TwistUpperAngle = 0
			elseif motor6D.Name == "RightElbow" then
				ballSocket.LimitsEnabled = true
				ballSocket.TwistLimitsEnabled = true
				ballSocket.UpperAngle = 165
				ballSocket.TwistLowerAngle = 0
				ballSocket.TwistUpperAngle = 0
			else
				ballSocket.LimitsEnabled = false
				ballSocket.TwistLimitsEnabled = false
			end
			if motor6D.Name == "Neck" then
				ballSocket.LimitsEnabled = true
				ballSocket.TwistLimitsEnabled = true
				ballSocket.UpperAngle = 0
				ballSocket.TwistUpperAngle = 45
				ballSocket.TwistLowerAngle = -45
			end
			if character.Humanoid.Health <= 0 then
				motor6D:Destroy()
				character.Humanoid:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding, false)
				for i,v in pairs(character:GetDescendants()) do
					if v:IsA("BasePart") and v.Name ~= "HumanoidRootPart" then
						local player = getNearestPlayer(character)
						v:SetNetworkOwner(player)
					end
				end
				character.Humanoid:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding, false)
				character.PrimaryPart.Name = "Rooty"
				spawn(function()
					while true do
						character.Humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
						character.Humanoid:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding, false)
						character.Humanoid:ChangeState(Enum.HumanoidStateType.Dead)
						game:GetService("RunService").Heartbeat:Wait()
					end
				end)
			end
		elseif motor6D:IsA("Motor6D") then
			local uc = Instance.new("UniversalConstraint")
			local attach0 = Instance.new("Attachment")
			local attach1 = Instance.new("Attachment")
			local noCollision = Instance.new("NoCollisionConstraint")
			uc.Attachment0 = attach0
			uc.Attachment1 = attach1
			uc.Parent = motor6D.Part0
			attach0.CFrame = motor6D.C0
			attach1.CFrame = motor6D.C1
			attach0.Parent = motor6D.Part0
			attach1.Parent = motor6D.Part1
			attach0.Name = "Attachment0Ragdoll"
			attach1.Name = "Attachment1Ragdoll"
			noCollision.Name = motor6D.Part0.Name.."And"..motor6D.Part1.Name
			noCollision.Part0 = motor6D.Part0
			noCollision.Part1 = motor6D.Part1
			noCollision.Parent = motor6D.Part0
		end
	end
end

function ragdoll(character)
	for i, motor6D in pairs(character:GetDescendants()) do
		if motor6D:IsA("Motor6D") then
			if character.Humanoid.Health > 0 then
				motor6D.Enabled = false
			else
				motor6D:Destroy()
			end
		end
	end
end

function dropWeapons(character)
	for i, v in pairs(character:GetDescendants()) do
		if v:IsA("Tool") then
			local oldCframe = v.Handle.CFrame
			v.Parent = workspace
			v.Handle.CFrame = oldCframe
		end
	end
end

function getNearestPlayer(npc)
	local closest = nil
	for _, player in pairs(game:GetService("Players"):GetPlayers()) do
		local char = player.Character or player.CharacterAdded:Wait()
		local humanoid = char:WaitForChild("Humanoid")
		if humanoid.Health > 0 then
			if not closest then
				closest = player
			else
				if (npc.PrimaryPart.Position - char.PrimaryPart.Position).Magnitude < (closest.PrimaryPart.Position - npc.PrimaryPart.Position).Magnitude then
					closest = player
				end
			end
		end
	end
	return closest
end

function setup(character)
	local humanoid = character:WaitForChild("Humanoid")
	character.PrimaryPart.CanCollide = false
	character.PrimaryPart.Massless = true
	humanoid.BreakJointsOnDeath = false
	humanoid.AutomaticScalingEnabled = false
	setupJoints(character)
	humanoid.Died:Connect(function()
		character.Humanoid:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding, false)
		humanoid.MaxSlopeAngle = 359
		ragdoll(character)
		dropWeapons(character)
		for i,v in pairs(character:GetDescendants()) do
			if v:IsA("BasePart") and v.Name ~= "HumanoidRootPart" then
				local player = getNearestPlayer(character)
				v:SetNetworkOwner(player)
			end
		end
		character.PrimaryPart.Name = "Rooty"
		while true do
			humanoid:SetStateEnabled(Enum.HumanoidStateType.GettingUp, false)
			humanoid:SetStateEnabled(Enum.HumanoidStateType.PlatformStanding, false)
			humanoid:ChangeState(Enum.HumanoidStateType.Dead)
			game:GetService("RunService").Heartbeat:Wait()
		end
	end)
end

As you can see, I have renamed the root part in order to prevent it from flying away, set every part’s network owner in the ragdoll to the nearest player to make it much smoother, renaming the root so that the Humanoid won’t make the ragdoll fly away, and I added a crude while loop to keep telling the ragdoll to not get up and to not use Platformstand.

The NPC still gets back up, sometimes.

In the video, I made a script to let the player fling the NPC and this help me to knock the NPC off their feet.

I have looked all over the devforum and internet and have not found a solid solution. Let me know if you have any ideas or I should post this in Engine Bugs due to the SetNetworkOwner() causing the humanoid issues most likely.

Thanks,
billybobpumpkin

2 Likes

Found the problem. It was due to setting the networkowner to the player, the player’s client still was making them get up.

2 Likes

Setting all the descendants of the corpse to BasePart:SetNetworkOwner(nil) didn’t work for me! I just destroyed Humanoid of the dead corpse, since it will be untouched!