While loop executing precisely 6 times ignoring yielding and ignoring change of variables

I am trying to make a fall damage script without using the humanoid.StateChanged event so that fall damage can happen even when the player is ragdolled.

The script is the following:

task.spawn(function()

	local function onHitGround(distance:number) -- the "damage" function is from a ModuleScript and the function is way too big to copy, but it isn't the issue (removing it makes the same thing happen)
		local damage = distance - 5
		local leftLeg, rightLeg, torso = Limbs["Left Leg"], Limbs["Right Leg"], Limbs.Torso
		if leftLeg and not leftLeg:GetAttribute("Cut") then
			if rightLeg and not rightLeg:GetAttribute("Cut") then
				damage /= 2
				Damage(true, damage, rightLeg, velocityDamageStats, nil, nil, nil, "Fall Damage")
			end
			Damage(true, damage, leftLeg, velocityDamageStats, nil, nil, nil, "Fall Damage")
		else
			if rightLeg and not rightLeg:GetAttribute("Cut") then
				Damage(true, damage, rightLeg, velocityDamageStats, nil, nil, nil, "Fall Damage")
			elseif torso then
				Damage(true, damage, torso, velocityDamageStats, nil, nil, nil, "Fall Damage")
			end
		end
	end

	local last_Y = Torso.Position.Y -- last Y level of the torso from the previous loop
	local falling_Y = last_Y -- the Y level of the torso at the moment it starts falling
	local wasFalling = false -- to check if the character was falling during the previous loop

	while humanoid.Health > 0 do
		task.wait(1)
		local current_Y = Limbs.Torso.Position.Y

		local isFalling = (current_Y < last_Y) -- checks if the character is falling in the current loop

		if isFalling and not wasFalling then -- checks if it is currently falling and was not falling before
			falling_Y = current_Y
			print("Falling")
		elseif not isFalling and wasFalling then -- checks if it is currently not falling but was falling before
			local dist = falling_Y - current_Y
			if dist > 10 then
				onHitGround(dist)
				print("Fallen")
			end
		end

		wasFalling = isFalling
		last_Y = current_Y
	end
end)

Theorically, “onHitGround” is supposed to be called only once until the character falls from 10 studs again, but for some reason is called 6 times instantaneously (and I know it’s instantaneous because I tested the script using “task.wait(1)” instead of “task.wait()” and the loop executed 6 times without yielding). The number of times “onHitGround” is called is always 6 times and never varies.

I’ve also noticed that “wasFalling” does not set to “false” even when I explicitely set it to “false”. It’s like I have to set “wasFalling” to false 6 times for it to finally register that the variable has been set to false.

I can’t find any cause of this issue. I don’t know if I’m missing anything. I’ve tried finding posts of people with a similar issue, but it seems like I’m the first that it has ever happened. I am genuinely confused about how this could happen.

If you print(time()) before the task.wait then afterwards what does it show? Add a counter to see how many time the loop runs.

local loopCount = 0
while humanoid.Health > 0 do
    print("Before wait time: " .. time())
    task.wait(1)
    print("After wait time: " .. time())
    loopCount += 1
...
end
print("While loop ran: " .. loopCount .. " times.")

Looks like wasFalling is being set to isFalling (which is probably true) at the end of each while loop. You probably want to be setting it in your “if isFalling and not wasFalling then” add wasFalling = true.

if isFalling and not wasFalling then -- checks if it is currently falling and was not falling before
	falling_Y = current_Y
	print("Falling")
	wasFalling = true --set it true here
elseif not isFalling and wasFalling then -- checks if it is currently not falling but was falling before
	local dist = falling_Y - current_Y
	if dist > 10 then
		onHitGround(dist)
		print("Fallen")
        wasFalling = false --set it false here
	end
end
wasFalling = isFalling --likely a problem

You may also want to pad the isFalling = (current_Y < last_Y) a pinch, otherwise it will probably be true even if your moving a tiny little bit (0.0001) on Y.

Thank you for trying to help me.

Turns out I’m stupid and missed that I put the whole thing inside a for loop iterating over every body part of the character. It’s why onHitGround is always executed 6 times and never more or less, because there are 6 limbs in the R6 rig :sob:

Again, thank you for your time.

In my defense, the beginning of the limb for loop is 80 lines above the fall damage part

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.