I need help with my stamina system!

Hello everyone!
I currently give up, I’ve been coding this stamina system for about 3 days now I tried and tried and came here for help.

The problem is with refilling my stamina after draining, it works for a bit then it freaks out and bugs like crazy.

My stamina is inspired by Reason 2 Die’s Stamina system preview down (What I want my stamina to look like) below:

My Stamina showcase (tried to compress it so save some quality):

My full script is listed below also:


--// Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

--// Client
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

local Player = Players:GetPlayerFromCharacter(Character)

--// Variables
local SprintTick = 0

--// Status
local Status = Character:WaitForChild("Status")
local Checks = Status:WaitForChild("Checks")
local Stamina = Status:WaitForChild("Stamina")
local IsSprinting =Checks:WaitForChild("IsSprinting").Value

--// Functions
local function RefillStam()
	task.wait(3)
	while (Stamina.Value < Stamina.MaxValue) and not IsSprinting do
		local CalcStam = (Stamina.MaxValue/100) * 1.25

		Stamina.Value = Stamina.Value + CalcStam
		task.wait(0.25)
		print(1)
	end
end

RunService.Heartbeat:Connect(function()
	if tick() - SprintTick > 0.25 then
		SprintTick = tick()
		if not IsSprinting and (Stamina.Value < Stamina.MaxValue) then
			RefillStam()
			return
		end
	end
end)

What my script basically does on the server is check if the player is not sprinting then it checks if we enough stamina then it supposed to wait 3 seconds before checking if we aren’t sprinting and have enough stamina again, then it calculates the amount of stamina to regenerate and wait .25 seconds and repeat.

I know my code is kinda dumb like why combine a while loop with runservice.heartbeat I just got nothing as I am a beginner since I started 3 months ago please tell me what I’m doing wrong.

2 Likes

There is a Health script within the Characters on the workspace, are you accounting for that?
Also pretty sure Stepped is fast enough for this and Heartbeat is way over doing it.

(also stepped works in any type of script)

1 Like

Try replacing

local IsSprinting =Checks:WaitForChild("IsSprinting").Value

To

local IsSprinting =Checks:WaitForChild("IsSprinting")

And replace

not IsSprinting

To

IsSprinting.Value == false

I am new to dev forum but i have been a developer for years

Hello, first, congrats on learning how to script it’s a long journey but take your time.
Now onto the code fix.

You have a few things that seem to be due to a lack of understanding:

  1. Object Values
    When dealing with object values and creating a variable you don’t include .Value in the variable. This is because you need to find the value when the variable is called, not defined aka do
    local IsSprinting = Checks:WaitForChild("IsSprinting")
    not
    local IsSprinting = Checks:WaitForChild("IsSprinting").Value
  2. Debounces
    This is how you make sure your functions aren’t stepping on each other’s toes. So simply have a variable (in this case local refilling) that lets you know this functions is already running
  3. RunService
    You don’t seem to know whats the difference is between renderstepped, stepped, and heartbeat. So ill just attach a link that should help with that.
  4. Not vs == false
    You use not (variable) a lot in your code and I would be careful as you should only use it when you know what the variable should be or when checking if something exists. If you are only having a function run with something is false just do == false, It also helps with readability!
    Anyways here’s your fixed code!
repeat task.wait() until game:GetService("Players"):GetPlayerFromCharacter(script.Parent) ~= nil

--// Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

--// Client
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

local Player = Players:GetPlayerFromCharacter(Character)

--// Variables
local Refilling = false
local Pause = false
local SprintTick = 0

--// Status
local Status = Character:WaitForChild("Status")
local Checks = Status:WaitForChild("Checks")

local Stamina = Status:WaitForChild("Stamina")
local IsSprinting =Checks:WaitForChild("IsSprinting").Value

--// Functions
local function RefillStam()
	-- Everytime I stop sprinting I would like to add a delay here before regenerating stamina ( task.wait(3) doesn't seem to work )
	if Refilling then return end
        Refilling = true
	if Pause then 
		task.wait(3)
		Pause = false
	end
	
	if (Stamina.Value < Stamina.MaxValue) and not IsSprinting and _G.CanUse(Character, "StamRegen") then
		local CalcStam = (Stamina.MaxValue/100) * 1.25
		Stamina.Value = Stamina.Value + CalcStam
		task.wait(0.25)
	end
	Refilling = false
end

RunService.Heartbeat:Connect(function()
	if Humanoid.Health == 0 or not Character.Parent then
		return
	end

	if tick() - SprintTick > 0.25 then
		SprintTick = tick()
		if Checks:WaitForChild("IsSprinting").Value then
			Stamina.Value -= 5
			Pause = true
		end
	end

	RefillStam()
end)

Stamina Fix.lua (1.5 KB)

The health doesn’t affect the script at all, also stepped can’t be ran on a server script.

My apologies forgot you did this on the server (You shouldn’t btw) to fix the code simply switch back to .Heartbeat

Thanks for the help but I still need help on adding a delay before regenerating and after sprinting.
Also edited your fix abit.

New code:

repeat task.wait() until game:GetService("Players"):GetPlayerFromCharacter(script.Parent) ~= nil

--// Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

--// Client
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

local Player = Players:GetPlayerFromCharacter(Character)

--// Variables
local Refilling = false

local SprintTick = 0

--// Status
local Status = Character:WaitForChild("Status")
local Checks = Status:WaitForChild("Checks")

local Stamina = Status:WaitForChild("Stamina")
local IsSprinting =Checks:WaitForChild("IsSprinting").Value

--// Functions
local function RefillStam()
	-- Everytime I stop sprinting I would like to add a delay here before regenerating stamina ( task.wait(3) doesn't seem to work )
	if Refilling then return end
	Refilling = true
	if (Stamina.Value < Stamina.MaxValue) and not IsSprinting and _G.CanUse(Character, "StamRegen") then
		local CalcStam = (Stamina.MaxValue/100) * 1.25
		Stamina.Value = Stamina.Value + CalcStam
		task.wait(0.25)
	end
	Refilling = false
end

RunService.Heartbeat:Connect(function()
	if Humanoid.Health == 0 or not Character.Parent then
		return
	end
	
	if tick() - SprintTick > 0.25 then
		SprintTick = tick()
		if Checks:WaitForChild("IsSprinting").Value then
			Stamina.Value -= 5
		end
	end

	RefillStam()
end)

Ignore these lines of code.

_G.CanUse(Character, "StamRegen")

	if tick() - SprintTick > 0.25 then
		SprintTick = tick()
		if IsSprinting then
			Stamina.Value -= 5
		end
	end

Once again this has to deal with denounces, look at how I used the variable pause to achieve your goal.

repeat task.wait() until game:GetService("Players"):GetPlayerFromCharacter(script.Parent) ~= nil

--// Services
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

--// Client
local Character = script.Parent
local Humanoid = Character:WaitForChild("Humanoid")

local Player = Players:GetPlayerFromCharacter(Character)

--// Variables
local Refilling = false
local Pause = false
local SprintTick = 0

--// Status
local Status = Character:WaitForChild("Status")
local Checks = Status:WaitForChild("Checks")

local Stamina = Status:WaitForChild("Stamina")
local IsSprinting =Checks:WaitForChild("IsSprinting").Value

--// Functions
local function RefillStam()
	-- Everytime I stop sprinting I would like to add a delay here before regenerating stamina ( task.wait(3) doesn't seem to work )
	if Refilling then return end
        Refilling = true
	if Pause then 
		task.wait(3)
		Pause = false
	end
	
	if (Stamina.Value < Stamina.MaxValue) and not IsSprinting and _G.CanUse(Character, "StamRegen") then
		local CalcStam = (Stamina.MaxValue/100) * 1.25
		Stamina.Value = Stamina.Value + CalcStam
		task.wait(0.25)
	end
	Refilling = false
end

RunService.Heartbeat:Connect(function()
	if Humanoid.Health == 0 or not Character.Parent then
		return
	end

	if tick() - SprintTick > 0.25 then
		SprintTick = tick()
		if Checks:WaitForChild("IsSprinting").Value then
			Stamina.Value -= 5
			Pause = true
		end
	end

	RefillStam()
end)
1 Like

Thank you so much I honestly I would never solved my problem!

Much more simpler than I imagined. :pray:

1 Like

No problem, make sure to post it as a solution if it helped (the large explanation I’ll edit it).
And I highly recommend reading up on the topics I posed, best of luck on your journey!

1 Like

Will do!, also I would like to say “IsSprinting” wasn’t a ObjectValue it’s a DoubleConstrainedValue I should’ve clarified more. Anyways have a good day.

You too! (also use math.clamp instead of DoubleConstrainedValue, since that’s deprecated)

1 Like

Brutal “help”. I have a working version but think I’m out …

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