I’ve made a Ragdoll Script which ragdolls the player while falling from a high place, but there’s one problem.
When the player spam jumps while walking, it ragdolls the player thinking they’re falling, same with small heights.
local player = game.Players.LocalPlayer
local char = script.Parent
local hum = script.Parent:WaitForChild("Humanoid")
local ragdolled = char:WaitForChild('Ragdolled')
local replicatedStorage = game:GetService("ReplicatedStorage")
hum.StateChanged:Connect(function(OldState, NewState)
if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
task.wait(0.5)
if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
replicatedStorage.RagdollServer:FireServer(char)
end
elseif hum:GetState() ~= Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
wait(5)
if hum:GetState() == Enum.HumanoidStateType.Physics then
replicatedStorage.GetUp:FireServer(char)
end
end
end)
local function change_state()
if ragdolled.Value then
hum:ChangeState(Enum.HumanoidStateType.Physics)
else
hum:ChangeState(Enum.HumanoidStateType.GettingUp)
end
end
ragdolled.Changed:Connect(change_state)
No you misunderstood.
If you checking your script closely, you will see that you’re making player ragdoll after they landed if they don’t land after 0.5 seconds. Meaning just by normal jump it might takes more than just 0.5 second to land which cause this issue.
So what @UwUanimsyt meaning is you should calculate the height from position player landed to position player jumped off if the height is more than , for example, 10 studs they will ragdoll.
(Also that BodyVelocity you’re using is for pushing, making force for object)
local maxFallTime = 5
local noDamage = 0.75
local human = player.Character:FindFirstChild("Humanoid")
local fallingTime = {}
human.StateChanged:Connect(function(old, new)
local ident = player.UserId
if new == Enum.HumanoidStateType.Freefall then
fallingTime[ident].start = os.clock()
elseif old == Enum.HumanoidStateType.Freefall then
fallingTime[ident].stop = os.clock()
local fallTime = (fallingTime[ident].stop - fallingTime[ident.start]) - noDamage
if fallTime >= maxFallTime then
human:TakeDamage(human.MaxHealth)
elseif fallTime > 0 then
human:TakeDamage(math.round((fallTime / maxFallTime) * human.MaxHealth))
end
end
end)
This does a few things, but basically, it checks the falling time and damages the player based on how long they fell.
Check if the new humanoid state is freefall. If it is, then it saves the current time using os.clock() which is high precision.
If the old state is freefall, then it save the current time again using os.clock(). Afterwards, it does a comparison between the two times (minus the dead time for no damage) to determine how much damage the humanoid should take. If the time is beyond the max fall time, then the humanoid is just outright killed. If the falling time is negative, which can happen if the falling time is less than the noDamage constraint, then no damage is done to the humanoid.
local player = game.Players.LocalPlayer
local char = script.Parent
local hum = script.Parent:WaitForChild("Humanoid")
local ragdolled = char:WaitForChild('Ragdolled')
local replicatedStorage = game:GetService("ReplicatedStorage")
hum.StateChanged:Connect(function(OldState, NewState)
if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
local humHeight = char:WaitForChild("HumanoidRootPart").Position.Y
repeat task.wait() until humHeight <= humHeight - 9
replicatedStorage.RagdollServer:FireServer(char)
elseif hum:GetState() ~= Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
wait(5)
if hum:GetState() == Enum.HumanoidStateType.Physics then
replicatedStorage.GetUp:FireServer(char)
script.PlayAnimation:FireServer()
end
end
end)
The problem is that you are using a Humanoid:StateChanged event, but you are not using the states that it’s giving you. The humanoid can be in only one state at a time. So the line
if hum:GetState() == Enum.HumanoidStateType.Freefall and hum:GetState() ~= Enum.HumanoidStateType.Jumping then
is pointless. Try the following code.
local playerService = game:GetService("Players")
local replicatedStorage = game:GetService("ReplicatedStorage")
-- Get the player's critical parts.
local player = playerService.LocalPlayer
local char = player.Character
while char == nil do
task.wait()
char = player.Character
end
local hum = char:WaitForChild("Humanoid")
local root = char:WaitForChild("HumanoidRootPart")
local ragdolled = char:WaitForChild('Ragdolled')
hum.StateChanged:Connect(function(OldState, NewState)
if newState == Enum.HumanoidStateType.Freefall then
task.spawn(function()
local humHeight = root.Position.Y
repeat
task.wait()
until humHeight <= humHeight - 9
replicatedStorage.RagdollServer:FireServer(char)
end)
elseif NewState ~= Enum.HumanoidStateType.Freefall and NewState ~= Enum.HumanoidStateType.Jumping then
task.delay(5, function()
if hum:GetState() == Enum.HumanoidStateType.Physics then
replicatedStorage.GetUp:FireServer(char)
script.PlayAnimation:FireServer()
end
end)
end
end)
I’m not too keen about having long waits inside an event handler. In general, an event handler is like a hardware interrupt service routine: Get in and get out, fast.
FYI, you can play animations from the client and it will replicate to all clients. No need to send an event to the server to start an animation.
hum.StateChanged:Connect(function(OldState, NewState)
if NewState == Enum.HumanoidStateType.Landed then
local Height = -root.Velocity.Y
if Height >= 10 then
replicatedStorage.RagdollServer:FireServer(char)
end
end
end)
You can just think like coding a fall damage (I stole it on youtube)