Stamina system for sprinting

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? a stamina system for sprinting

  2. What is the issue? I don’t know how to stop the player inside an InputBegan function

  3. What solutions have you tried so far? repeat functions

Basically I want the player to stop sprinting after the currentSprintValue hits zero, but however I try to do it, it always ends up buggy.

function stopRunning()
	hum.WalkSpeed = defaultWalkSpeed
	isSprinting = false
	sprintTween:Cancel()
	defaultTween:Play()
	task.wait(1.5)
	repeat
		task.wait(0.3)
		currentSprintValue += 1
		sprintText.Text = currentSprintValue.. "/100"
	until currentSprintValue == 100  or isSprinting == true
end

UIS.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.LeftShift and hum.MoveDirection.Magnitude > 0 and currentSprintValue > 0 then
		hum.WalkSpeed = sprintWalkSpeed
		isSprinting = true
		defaultTween:Cancel()
		sprintTween:Play()
		repeat
			task.wait(0.1)
			currentSprintValue -= 1
			sprintText.Text = currentSprintValue.. "/100"
		until currentSprintValue == 0  or isSprinting == false
	end
end)

UIS.InputEnded:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.LeftShift or currentSprintValue == 0 then
		stopRunning()
	end
end)

Can somebody hint me how to do that?

1 Like

What about, using a RunService connection that will constantly read the stamina value, when it reaches zero it will reduce the player’s speed?

When client starts to use stamina, the RunService will start to drain and read the stamina value, when it reaches zero it will change the speed back to normal.

In that way if player still pressing the left shift but stamina reached 0, it will stop

Honestly, not enough information for what the buggy part is, but I recommend to use <= since you are using a do while loop or in lua repeat unil.

Edit:

Same with this also recommend to use >=, the reason for this is to avoid the possibility of infinite loop.

hmmm alr, but what about regaining stamina after sprinting? I want to use a cooldown of a few seconds before the regeneration starts

I want it to decrease the walkspeed back to default after stamina is drained, but if I’ll try to do that inside InputBegan, it will intersect with the stopRunning() in InputEnded when the user stops holding left shift. They both end up going over the limit and give the player infinite stamina.

Whats the deal with implementing the regaining when having the RunService?
You can even do that the RunService controls everything, from draining, changing speed, and refilling too

well I simply don’t understand how to implement a cooldown, because RenderStepped is ran every frame. Should I make a tick() thing?

By adding if statements to the RunService you will control what is doing.
The debounce of the cooldown could be handled with a task.delay() to set to true or false any variable that the RunService is checking

Wel… actually this stamina thing brings to me lot of thoughts about the right implementation…

Is that stamina system important to your game mechanics?
Right now you are using a client side approach to control if player can use sprint or not. Thats easily exploitable. So, is stamina important for your game? (games where exploiters can run faster than others affects the experience?.. probably many of games)

ServerSide check then? checking and setting the speed of the player?
checking magnitude? being authoritative?
idk, lot of questions that are probably important, or just trust new patches against exploiters works better after roblox and synapse made team… idk

eh, since roblox partnered up with synapse I don’t think they will be poking around as much, and I don’t really care about exploiters in this game. It’s a singleplayer horror, so they don’t ruin anyone’s experience.

1 Like

Try using this:

local maxStamina = 100

local UIS = game:GetService"UserInputService"

local isSprinting
local stamina = maxStamina

local wait = task.wait

local function sprintLogic(isSprinting)
	if isSprinting then
		hum.WalkSpeed = sprintWalkSpeed
		sprintTween:Play()
		defaultTween:Cancel()
	else
		hum.WalkSpeed = defaultWalkSpeed
		sprintTween:Cancel()
		defaultTween:Play()
	end
end

UIS.InputBegan:Connect(function(input, gpe)
	if gpe then return end
	if input.KeyCode == Enum.KeyCode.LeftShift then
		isSprinting = true
		sprintLogic(isSprinting)

		while isSprinting and stamina > 0 do
			stamina -= 1
			sprintText.Text = stamina/maxStamina
			wait(0.1)
		end

		isSprinting = false
		sprintLogic(isSprinting)
	end
end)
UIS.InputEnded:Connect(function(input, gpe)
	if gpe then return end
	if input.KeyCode == Enum.KeyCode.LeftShift then
		isSprinting = false
		sprintLogic(isSprinting)

		repeat
			stamina += 1
			sprintText.Text = stamina/maxStamina
			wait(0.1)
		until isSprinting or stamina == maxStamina
	end
end)
1 Like

oh alright, I’ll see if it works

1 Like

I’m just creating some conversation and debate. What do you think about a RunService approach?

I did make a stamina system in the past and tried to use RunService loops, but found that using “traditional” loops worked better because they yield the script while they run which in a stamina system could be used to the scripter’s advantage to make the system much simpler

2 Likes

alright thanks, that works well! :smile:

2 Likes

actually there was a slight hitch: the stamina regened extremely fast if you’ll press shift again while it is already regening. I just made a check if it’s regening, before starting the said regen.

if not isRegening then
			task.wait(1.5)
			
			isRegening = true
			repeat
				stamina += 1
				sprintText.Text = stamina.. "/" ..maxStamina
				tweenBar(stamina/maxStamina)
				wait(0.1)
			until isSprinting or stamina == maxStamina
			
			isRegening = false
		end

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