Stamina system regeneration

I am trying to create a stamina system similar to a souls game in which actions consume stamina. Everything is working as intended, however I do not know how to make it so that stamina regen is halted temporarily when you do an action. I am currently setting a boolean to true/false in order to start stamina regen, however this comes with some problems.

When I try to disable regen, for example, I want the regen to come back a second after the action is done. However, this gets weird when you string several actions together such as this:
The dash and run buttons are connected, you have to hold the dash button to start running.

  1. The player dashes/rolls, cancelling the stamina regen and enabling it after 1 second
  2. The player starts running before the stamina regen comes back
  3. Pressing the dash button should cancel stamina regen, however because of the roll prior, the regen comes back while the player runs

This is obviously an issue, however I do not know a way in which I can fix it. I was thinking of potentially checking if another input was made before the boolean changes to false again, however I don’t exactly know how to create this considering how the stamina system stretches through several scripts.

I will post the code if necessary, however a fair amount of it might not have much correlation to the issue at hand, considering how it also functions as the code for the roll.

https://gyazo.com/8ab8af5327f44926d6d07cf49dc58d67
If you notice the top left, the stamina still regenerates while the player runs.

2 Likes

I’ve had an issue similar to this before.

Make sure to put a variable stating if the player is running or not, that way you can use it in an if statement to judge whether you start regenerating stamina or not

This best works when there is an inputEnded function

I also recommend using a variable to test how many times sprint has been activated.
Here is a snip-it of my code from an old game of mine (Pay attention to the threads variable)
This is being activated after the input has begin

if input.KeyCode == Enum.KeyCode.LeftShift then
		old_speed = character.Humanoid.WalkSpeed
		running = true
		SprintValue.Value = true
		threads = threads + 1
		print(threads)
		while stamina > 0 and running do
			if character.Humanoid.WalkSpeed > old_speed + Sprint_Add then
				old_speed = character.Humanoid.WalkSpeed - Sprint_Add
			end
			character.Humanoid.WalkSpeed = old_speed + Sprint_Add
			stamina = stamina - 1
			script.Parent:TweenSize(UDim2.new(stamina/100,0,1,0),"Out","Linear",0)
			wait()
			if stamina <= 0 then
				character.Humanoid.WalkSpeed = old_speed
			end
		end
	end

This is being activated after the input has ended (There is more code behind it but this post was getting too long)

while stamina < 100 and not running do
			if cooldown == true then
				cooldown = false
				wait(1.5)
				if threads - 1 ~= 0 then
					threads = threads - 1
					print(threads)
					return
				else
					threads = threads - 1
					print(threads)
				end
			end

Hope this helped

1 Like

I am using a boolean value located in ReplicatedStorage. I am now also trying to use UserInputService based on your response, however what I thought might work does not stop the stamina from regenerating. Basically what I am doing now is using UIS to check for when input involving the spacebar begins and ends.

actionCheck is the value which starts and stops the stamina regen, while currentAction just checks if the player is still rolling, stopping actionCheck from starting up.

UIS.InputBegan:Connect(function(key)
	if key == Enum.KeyCode.Space then
		actionCheck.Value = true
	end
end)

UIS.InputEnded:Connect(function(key)
	if key == Enum.KeyCode.Space then
		if currentAction.Value == false then
			task.wait(1)
			actionCheck.Value = false
		else
			currentAction.Changed:Wait()
		end
	end
end)

Any idea on what I am doing wrong?

1 Like

Alright so this may be just a bit late but I have worked out a solution to this issue.
One of the problems faced while trying to initially script this had been that all parts of the moveset which consume stamina were placed into separate scripts. This can be solved in two ways.

  • Use global variables through either module scripts or _G
  • Move everything to one script

For the purpose of the game I have done both.
From there it became a simple solution of just using tick() and measuring from when an action was last performed.

To demonstrate, here are parts of the script for the stamina system I am using:

--module script
local module = {
	["maxStamina"] = 80,
	["stamina"] = 80,
	["exhausted"] = false, -- prevents any actions if stamina is depleted
	["currentAction"] = false,
	["lastAction"] = tick() --the main variable that determines when stamina should regen
}

return {
	get = function(item)
		return module[item]
	end,
	
	set = function(item, value)
		module[item] = value
	end,

-- get and set basically just are for retrieving the variables in another script
	
	depleteStamina = function(amnt)
		module.stamina -= amnt

		if module.stamina <= 0 then
			module.stamina = 0
			module.exhausted = true
			return false
		else
			return true
		end
-- the two returns here are just for stopping held actions such as running if stamina is out

	end
}

-- local moveset script - part that handles stamina regen
RS.RenderStepped:Connect(function()
	if tick() - genMod.get("lastAction") >= 2  then -- after two seconds remove exhausted and regenerate stamina
		genMod.set("exhausted", false)

		genMod.set("stamina", genMod.get("stamina") + 0.75)

		if genMod.get("stamina") > genMod.get("maxStamina") then genMod.set("stamina", genMod.get("maxStamina")) end
	end
end)

This code has been able to work for me for some time now as this was made about a month ago.

1 Like

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