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 ! 
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 ! 
(char min)