Fall damage not working in ragdoll using Physics humanoid state

I just made a fall damage system which I’m pretty happy with. It works to my liking, however the one problem is that when ragdolled players fall they don’t take damage until they get up from being ragdolled because the player takes damage when their state changes from Freefall or Physics (the state that ragdolled players are in until they get up).

humanoid.StateChanged:Connect(function()
	local fallDistance = 0
	local y
	while humanoid:GetState() == Enum.HumanoidStateType.Freefall or humanoid:GetState() == Enum.HumanoidStateType.Physics do
		y = character.HumanoidRootPart.Position.Y
		wait(0.05)
		if y > character.HumanoidRootPart.Position.Y then
			fallDistance = fallDistance + (y - character.HumanoidRootPart.Position.Y)
		end	
	end
	local damage = 0
	if fallDistance > 15 then
		damage = math.clamp(fallDistance - 25, 0, math.huge)
	end
	if damage > 5 then
		if damage < humanoid.Health then
			humanoid.Health = humanoid.Health - math.clamp(damage, 0, humanoid.MaxHealth)
			character.HumanoidRootPart.Fall:Play()
			if damage >= humanoid.MaxHealth / 3 then
				local ragdollFolder = Instance.new("Folder")
				ragdollFolder.Name = "Ragdolled"
				ragdollFolder.Parent = character
				game:GetService("Debris"):AddItem(ragdollFolder, damage / 15)
				character.HumanoidRootPart.Crack:Play()
			end
		elseif damage >= humanoid.Health then
			humanoid.Health = 1
			local knockFolder = Instance.new("Folder")
			knockFolder.Name = "Knocked"
			knockFolder.Parent = character
			game:GetService("Debris"):AddItem(knockFolder, 15)
			character.HumanoidRootPart.Bonebreak:Play()
			tagTarget(character, 15)
		end
	end	
end)
1 Like

Hmm, so I believe when you say they dont take damage until the while loop breaks i.e. the state changes to break the while condition

perhaps have a check when the magnitude between each y position is very low? i.e. the distance between each point is miniscule to the point that it represents that the player is no longer falling, then break the loop and deal the damage.

theoretically you could also take a average to verify that the player has infact stopped falling, in order to prevent false positives, you could also do a raycast shooting from the players body which might be better actually

I suggest using a very small raycast shooting from player’s body and going in the -y direction and checking if it hit something then break loop and deal damage. (should go without saying the raycast should filter descendants of character to avoid false positive)

raycast code should be within the while loop as well.

You could also try to use the else block for your inner if statement in while loop. I’m not sure if it would work though but you have multiple options you can look into

1 Like

Sorry for the late reply but you can check if the floor material is air,if is air is freefall if not is landed ! :grinning:

wow I am not sure why I did not think of that–

@LinkTheHero I believe using @FireStrykerAzul solution should work flawlessly:

https://developer.roblox.com/en-us/api-reference/property/Humanoid/FloorMaterial

1 Like

Well I am now using a function called takeFallDamage that procs fall damage on the player based on a fallDistance variable. Inside the function it resets the fall distance variable to 0. There’s a while loop for the freefall state type (non-ragdolled players falling) that tracks the distance that the player fell, increases the fall distance variable, and then when the while loop breaks (state type changed from freefall) it fires the fall damage function. There’s another while loop for the ragdoll state type that works the same way, except because the while loop does not break until they exit the ragdoll state type the function is instead called from a humanoid.Touched event.

2 Likes

cool, have a nice day ! :wink:
(char min)