local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local stamina = 100
local function refill()
-- Ensuring that the while-loop would definitely cancel
-- This must NEVER be set to false ever again after being set to true or it might all happen within the iteration and the while-loop won't stop
local isJumping = false
spawn(function()
isJumping = char.Humanoid.Jumping:Wait()
end) -- This has to be local or else it may be set to false again within the iteration
wait(3) -- We can afford a wait because isJumping will never be set to false again after the player jumped for the first time since iterating. If it's set to true while waiting, then the while-loop won't run.
while stamina < 100 and not isJumping do -- Add until stamina is full but if the player jumped since beginning iteration, it will cancel.
stamina = stamina + 1
if stamina == 10 then
-- Undo the effect from being banned from jumping due to lack of stamina
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
end
print('Refilling, stamina is', stamina)
wait(.1)
end
end
char.Humanoid.Jumping:Connect(function(starting)
if starting then
print("Jumped")
stamina = stamina - 10
if stamina < 10 then
-- This will only take effect for the NEXT jump so you need to disable jumping a bit earlier
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
print("Next jump blocked! Stamina is", stamina)
end
else -- When the player exits jump
print("Jump event exited with stamina", stamina)
refill()
end
end)
Alternate solutions include tweening the stamina value. This could clean up the code a bit since tweening, unlike while-loops, doesn’t block the thread so there’s no need to mess around with threading. They can also be canceled directly so you’d just need to cancel the tween when a jump is detected. Keep in mind, though, that you’d still need to find a way to re-enable jumping for the player once the stamina surpasses 10.
If you want to use a global isJumping
variable for canceling refills, then you’d need to refill and set isJumping
to false
on the Landed
event through Humanoid.StateChanged
and then you can rely on the refill loop to cancel because isJumping
won’t be set to true (jumps) then false (lands) within one iteration unless jumping and landing in your game takes less than 0.1 seconds. However, you wouldn’t be able to wait() for 3 seconds like I did because the player may jump within that time and you’d probably have to check tick() in the loop like you did in your original post.
Alternate solution with refilling on land instead of jump exit
--[[
Alternate jump script using except refill begins on land
]]
local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local stamina = 100
local function refill()
-- Ensuring that the while-loop would definitely cancel
-- This must NEVER be set to false ever again after being set to true or it might all happen within the iteration and the while-loop won't stop
local isJumping = false
spawn(function()
isJumping = char.Humanoid.Jumping:Wait()
end) -- This has to be local or else it may be set to false again within the iteration
wait(3) -- We can afford a wait because isJumping will never be set to false again after the player jumped for the first time since iterating. If it's set to true while waiting, then the while-loop won't run.
while stamina < 100 and not isJumping do -- Add until stamina is full but if the player jumped since beginning iteration, it will cancel.
stamina = stamina + 1
if stamina == 10 then
-- Undo the effect from being banned from jumping due to lack of stamina
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
end
print('Refilling, stamina is', stamina)
wait(.1)
end
end
char.Humanoid.StateChanged:Connect(function(oldState, newState)
if newState == Enum.HumanoidStateType.Jumping then
print("Jumped")
stamina = stamina - 10
if stamina < 10 then
-- This will only take effect for the NEXT jump so you need to disable jumping a bit earlier
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
print("Next jump blocked! Stamina is", stamina)
end
elseif newState == Enum.HumanoidStateType.Landed then -- When the player lands
print("Jump landed with stamina", stamina)
refill()
end
end)
Alternate solution with global isJumping and refill beginning on land
--[[
Alternate jump script using global isJumping taking advantage of relibability with Landed
]]
local player = game.Players.LocalPlayer
local char = player.Character or player.CharacterAdded:Wait()
local stamina = 100
local isJumping = false -- Now it's global and is set to true/false depending on jumping/landing
local function refill()
isJumping = false
-- We CAN'T afford a wait because isJumping can be set to true then false, failing to cancel the loop during a 3 second wait
local t = tick()
while stamina < 100 and not isJumping do -- Add until stamina is full but if the player jumped since beginning iteration, it will cancel.
if tick() - t >= 3 then
stamina = stamina + 1
if stamina == 10 then
-- Undo the effect from being banned from jumping due to lack of stamina
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, true)
end
print('Refilling, stamina is', stamina)
end
wait(.1)
end
end
char.Humanoid.StateChanged:Connect(function(oldState, newState)
if newState == Enum.HumanoidStateType.Jumping then
print("Jumped")
isJumping = true
stamina = stamina - 10
if stamina < 10 then
-- This will only take effect for the NEXT jump so you need to disable jumping a bit earlier
char.Humanoid:SetStateEnabled(Enum.HumanoidStateType.Jumping, false)
print("Next jump blocked! Stamina is", stamina)
end
elseif newState == Enum.HumanoidStateType.Landed then -- When the player lands
print("Jump landed with stamina", stamina)
refill()
end
end)
If you have any questions about how this works even after reading through my fairly extensive comments, just ask!