Struggling with stamina system

i have this stamina system script for running:

local plr = game.Players.LocalPlayer
local Character = plr.Character or plr.CharacterAdded:Wait()
local Humanoid = Character:WaitForChild("Humanoid")

local UIS = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local TweenService = game:GetService("TweenService")
local Camera = workspace.CurrentCamera

local RunAnim = Humanoid:LoadAnimation(script:WaitForChild("Sprint"))
local JumpAnim = Humanoid:LoadAnimation(script:WaitForChild("Jump"))

-- State Variables
local Running = false
local notMoving = true
local isOnGround = true
local Jumped = false
local originalSpeed = Humanoid.WalkSpeed

-- Stamina Variables
local MaxStamina = 100
local Stamina = MaxStamina
local StaminaDrainRate = 10 -- How much stamina is drained per second while running
local StaminaRegenRate = 5  -- How much stamina regenerates per second when not running
local SprintDuration = 10  -- How long the player can sprint before stopping
local CooldownTime = 10    -- Cooldown time before player can sprint again

-- Timing Variables
local SprintStartTime = 0
local CanSprint = true
local CooldownEndTime = 0

-- UI Elements
local PlayerGui = plr:WaitForChild("PlayerGui")
local StaminaGui = PlayerGui:FindFirstChild("StaminaGui")

if not StaminaGui then
	warn("StaminaGui not found in PlayerGui.")
	return
end

local StaminaBar = StaminaGui:FindFirstChild("StaminaBar")
local Fill = StaminaBar and StaminaBar:FindFirstChild("Fill")

if not StaminaBar or not Fill then
	warn("StaminaBar or Fill frame not found in StaminaGui.")
	return
end

----------------- Changeable ---------------------

local RunButton = Enum.KeyCode.LeftShift
local newSpeed = 22 -- Speed you want while running
local DefaultFieldOfView = 55 -- Default FOV
local SprintFieldOfView = 75 -- Running FOV
local MobileButton = PlayerGui:FindFirstChild("MobileGUI"):FindFirstChild("MobileButtons"):FindFirstChild("RunButton")

if not MobileButton then
	warn("MobileButton not found in MobileGUI.")
	return
end

--------------------------------------------------

Camera.FieldOfView = DefaultFieldOfView

local function UpdateFOV()
	if Running and not notMoving then
		-- Player is sprinting and moving
		local goal = { FieldOfView = SprintFieldOfView }
		local info = TweenInfo.new(0.5)
		local tween = TweenService:Create(Camera, info, goal)
		tween:Play()
	else
		-- Player is not sprinting or not moving
		local goal = { FieldOfView = DefaultFieldOfView }
		local info = TweenInfo.new(1)
		local tween = TweenService:Create(Camera, info, goal)
		tween:Play()
	end
end

local function UpdateStamina()
	if Running then
		-- Drain stamina while running
		Stamina = math.max(0, Stamina - StaminaDrainRate * RunService.RenderStepped:Wait())
		if Stamina == 0 then
			Stop()
		end
	else
		-- Regenerate stamina when not running
		Stamina = math.min(MaxStamina, Stamina + StaminaRegenRate * RunService.RenderStepped:Wait())
	end

	-- Update the stamina bar fill
	if Fill then
		Fill.Size = UDim2.new(Stamina / MaxStamina, 0, 1, 0) -- Adjust the size of the fill frame based on current stamina
	end
end

local function StartCooldown()
	CanSprint = false
	CooldownEndTime = tick() + CooldownTime
	print("Sprint cooldown started.")
	while tick() < CooldownEndTime do
		RunService.RenderStepped:Wait() -- Wait until cooldown period is over
	end
	CanSprint = true
	print("Sprint cooldown ended.")
end

local function Run()
	if Stamina == MaxStamina and isOnGround and CanSprint then
		if Running then
			print("Already sprinting.")
			return
		end

		Running = true
		SprintStartTime = tick()
		RunAnim:Play()
		Humanoid.WalkSpeed = newSpeed
		UpdateFOV()
		print("Sprint started.")

		-- Connect to Heartbeat to automatically stop sprint after duration
		local sprintHeartbeatConnection
		sprintHeartbeatConnection = RunService.Heartbeat:Connect(function()
			if tick() - SprintStartTime >= SprintDuration then
				Stop()
				sprintHeartbeatConnection:Disconnect() -- Disconnect after stopping sprint
			end
		end)

		coroutine.wrap(StartCooldown)() -- Start cooldown in a separate coroutine
	elseif not CanSprint then
		print("Cannot sprint due to cooldown.")
	end
end

local function Stop()
	if Running then
		Running = false
		RunAnim:Stop()
		Humanoid.WalkSpeed = originalSpeed
		UpdateFOV()
		print("Sprint stopped.")
	end
end

MobileButton.MouseButton1Click:Connect(function()
	if Running then
		Stop()
	else
		Run()
	end
end)

UIS.InputBegan:Connect(function(input, isTyping)
	if isTyping then return end
	if input.KeyCode == RunButton then
		Run()
	end
end)

UIS.InputEnded:Connect(function(input)
	if input.KeyCode == RunButton then
		Stop()
	end
end)

RunService.Heartbeat:Connect(function()
	notMoving = Humanoid.MoveDirection.Magnitude == 0
	if notMoving then
		Stop()
	end

	if Running and (Humanoid:GetState() == Enum.HumanoidStateType.Physics or
		Humanoid:GetState() == Enum.HumanoidStateType.Seated or
		Humanoid:GetState() == Enum.HumanoidStateType.Swimming or
		Humanoid:GetState() == Enum.HumanoidStateType.Climbing or
		Humanoid:GetState() == Enum.HumanoidStateType.Dead) then
		Stop()
	end

	if Running and Humanoid:GetState() == Enum.HumanoidStateType.Jumping then
		Jumped = true
		RunAnim:Stop()
		JumpAnim:Play()
	end

	if Running and Jumped and Humanoid:GetState() == Enum.HumanoidStateType.Landed then
		Jumped = false
		RunAnim:Play()
	end

	if Running and (not script:FindFirstChild("RunEnabled") or not script.RunEnabled.Value) then
		Stop()
	end

	isOnGround = Humanoid.FloorMaterial ~= Enum.Material.Air
	UpdateFOV()
	UpdateStamina()
end)

but when i let go of sprinting early, my stamina goes up, but the cooldown goes back…
anyway to fix this so i can still sprint until it fully goes to zero??

3 Likes