Fall Damage script

Fall Damage
Hi !
I will explain how to calculate the fall damage thanks to the height of the fall :

  1. Get Y of the player with Character:GetPrimaryPartCFrame().Position.Y !
  2. When the player fall define his height !
  3. When the player land define his height !
  4. Check if the player land in the water, if the player land in water and the height is <100 kill the player else apply the damage by subtracting the height of when you fall from that of when you land .

Schema :

Finish !

I now show you the script placed in ServerScriptService :
TUTO

game.Players.PlayerAdded:Connect(function(Player)
	Player.CharacterAdded:Connect(function(Character)
		local Humanoid = Character:FindFirstChildOfClass("Humanoid")
		local YF
		local YL

		Humanoid.StateChanged:Connect(function(OldState, NewState)
			if NewState == Enum.HumanoidStateType.Freefall then
				YF = Character:GetPrimaryPartCFrame().Position.Y
			elseif OldState == Enum.HumanoidStateType.Freefall and NewState ~= Enum.HumanoidStateType.Swimming then
				YL = Character:GetPrimaryPartCFrame().Position.Y
				if YF > YL and YF - YL < -20 then
					Humanoid:TakeDamage(YF - YL*-1)
				elseif YF - YL > 20 then
					Humanoid:TakeDamage(YF - YL)
				end
			elseif OldState == Enum.HumanoidStateType.Freefall and NewState == Enum.HumanoidStateType.Swimming then
				YL = Character:GetPrimaryPartCFrame().Position.Y
				if YF > YL and YF - YL < -100 or YF - YL > 100 then
					Humanoid:TakeDamage(Humanoid.MaxHealth)
				end
			end
		end)
	end)
end)

Now I let you send me your positive/negative feedback :

Is there a good explanation ?
  • This topic is well explained !
  • This topic is poorly explained !

0 voters

Was this topic useful to you ?
  • This topic was useful to you !
  • This topic wasn’t useful to you !

0 voters

Have a good day ! :grinning:

24 Likes

It would be nice, if the explanation was increased with images

1 Like

Why are you changing the Y variable in a seperate loop instead of putting it in the heartbeat event?

2 Likes

Alright, I’ll make sure to improve it ! :grin:
with pictures for better understanding ! :wink:

You can if you want to do it, it’s just that I prefer to separate the information from the script so that it is better understood, in any case I understand my script better like that! :grinning:

Sorry for the delay but it’s done ! :wink::grinning:

Can you, if you put a negative opinion, explain it to me so that I can improve the resource ? :grin:

Instead of using .StateChanged twice, just use elseif:



Humanoid.StateChanged:Connect(function (oldState, newState)
	if newState == Enum.HumanoidStateType.Landed then
		YL = Y
		if YF - YL > 100 and TouchWater then --MinEightForTakeDamageIfThePlayerTouchWater--
			Humanoid:TakeDamage(100) --ApplyDamage--
		else
			if YF - YL > 30 then  --MinEightForTakeDamage--
				Humanoid:TakeDamage(YF-YL) --ApplyDamage--
			end
		end
    elseif newState == Enum.HumanoidStateType.Freefall then
		YF = Y
	end
end)

Also, try including stuff like this all in one loop

Here’s it included in the heartbeat:

RunService.Heartbeat:Connect(function()
    Y = Character:WaitForChild("HumanoidRootPart").Position.Y
	local BodyPos = Player.Character.HumanoidRootPart.CFrame
	local x, y, z = BodyPos.X, BodyPos.Y, BodyPos.Z

	local min, max = Vector3.new(x + 0.01, y + 0.01, z + 0.01), Vector3.new(x - 0.01, y - 0.01, z - 0.01)
	local region = Region3.new(max, min)
	region = region:ExpandToGrid(4)

	if region then
		local material = workspace.Terrain:ReadVoxels(region, 4)
		if material[1][1][1] == Enum.Material.Water then
			TouchWater = true
		else
			TouchWater = false
		end
	end
end)

Another small thing I noticed

if region then
		local material = workspace.Terrain:ReadVoxels(region, 4)
		if material[1][1][1] == Enum.Material.Water then
			TouchWater = true
		else
			TouchWater = false
		end
	end

material[1][1][1] == Enum.Material.Water returns a bool, so you can just make TouchWater it:

if region then
	local material = workspace.Terrain:ReadVoxels(region, 4)

	TouchWater = (material[1][1][1] == Enum.Material.Water)
end

Hopefully this helps! Thank you for your contribution! :grinning:

2 Likes

Sorry I’m new in the programmation ! :sweat_smile:
I’ll improve myself, and for a better understand of my script I need to separate them but I think I am wrong and your right ! :grin:
Have a nice day ! :yum:

1 Like

I’ve learn a lot of time and now I’ve do that new version of the code ! :yum:
Have a nice day ! :wink:

1 Like

Sorry to revive this topic but you could also use HumanoidRootPart.AssemblyLinearVelocity.Y to check whether the player is falling, how long the player has been falling, and even the speed of the player falling. Sorry if my grammar sucks, I tried my best to explain.

3 Likes

Hi ! :yum:
Check how long the player has been falling does’nt work ! :smile:
But the other method works fine, I just want to tell you that method ! :grin:
Have a nice day ! :wink:

1 Like

Hi, FireStrykerAzul! I can give you an example to check how long the player fell.

The example is right here if you need it:

local isFalling = false
local count = false
local timee = 0

function timerStart()
	while wait() do
		if count == true then
			timee = timee + 73
		end
	end
end

coroutine.wrap(timerStart)()

while true do
	repeat wait() until HumanoidRootPart.AssemblyLinearVelocity.Y < 0
	if isFalling == false then
		print("player is falling")
		isFalling = true
		count = true
	end
	repeat wait() until HumanoidRootPart.AssemblyLinearVelocity.Y >= 0
	isFalling = false
	print("player landed. He was in the air in " .. timee .. " milliseconds")
	count = false
	timee = 0
end

By the way. I’m going on vacation tomorrow, which will take 14 days, so I can’t respond to you if you write respond back tomorrow.

Have a good day.

2 Likes

This is good, however making it local is pretty unsafe. Exploiters can either steal your code, modify your code, or delete the local script. To make it so they can’t do any of that you must make it on the server. In your case making it server sided would be very easy, I will put code below that will be what a server sided version of this would be.

-- Server Script in StarterCharacterScripts.

Character = script.Parent -- no point in finding localplayer character if it's parented in the character
Humanoid = Character:WaitForChild("Humanoid")
YF = nil
YL = nil

Humanoid.StateChanged:Connect(function(OldState, NewState)
	if NewState == Enum.HumanoidStateType.Freefall then
		YF = Character:GetPrimaryPartCFrame().Position.Y
	elseif NewState == Enum.HumanoidStateType.Landed or NewState == Enum.HumanoidStateType.Running then
		YL = Character:GetPrimaryPartCFrame().Position.Y
		if YF == nil then return end
		if YF - YL > 25 then
			Humanoid:TakeDamage(YF - YL)
		end
	elseif OldState == Enum.HumanoidStateType.Freefall and NewState == Enum.HumanoidStateType.Swimming then
		YL = Character:GetPrimaryPartCFrame().Position.Y
		if YF - YL > 100 then
			Humanoid:TakeDamage(Humanoid.MaxHealth)
		end
	end
end)
1 Like

Here it shows it being a local script, I thought you couldn’t edit player health locally?

1 Like

Thank you very much I’ve try to make a code like you, time falling == fall damage, but I made a mistake in my script ! :sweat_smile:
Have a nice day ! :smiley:

Ok, I will modify the topic in a few day ! :grinning:
Thank you so much ! :yum:
Have a good day ! :wink:

You can edit player health locally because the Humanoid only can get in StarterCharacterScript and some server script ! :yum:
I hope that was helpful ! :wink:
Have a nice day ! :smiley:

You shouldnt be able to control player health locally, as that would allow a ton of godmode exploits to exist, which dont work because of that, fe removes that ability.

1 Like

Instead of using local script, use server script instead.

1 Like