Stamina Recharge rate stacks during wait timer when spamming sprint button

I have a Stamina script that is almost complete, however there is quite a notable bug that easily be exploited. Specifically, the user’s stamina can recharge faster than intended when spamming LeftMouse during the recharge (wait) phase (which suspends the script for 5 seconds as punishment for being exhausted).

StaminaStackBug.wmv (4.3 MB)

My guess is that the recharge value (0.085) is being stacked every time I press LeftShift during recharge.

I have tried adding a break function, canActivate logics, looked online to see anything similar, but no luck. Any suggestions would be extremly helpful.

Script:

Summary
-- Originally scripted by AdvancedDrone -- 

-- Variables --

local camera = game.Workspace.CurrentCamera
local TweeningService = game:GetService("TweenService")
local UIS = game:GetService('UserInputService')
local Bar = script.Parent:WaitForChild('STMBackground'):WaitForChild('Bar')
local player = game.Players.LocalPlayer
local NormalWalkSpeed = 8
local NewWalkSpeed = 13
local power = 10
local sprinting = false

repeat wait() until game.Players.LocalPlayer.Character
local character = player.Character

-- Tween Functions --

-- sprinting

local FOVChanges = {
	FieldOfView = 72
}
local TweenInformation = TweenInfo.new(
	1, -- tween length
	Enum.EasingStyle.Quint, -- easing Style
	Enum.EasingDirection.Out, -- easing Direction
	0, -- repetition time
	false, -- reverse?
	0 -- delay
)

local tween = TweeningService:Create(camera, TweenInformation, FOVChanges)

-- walking

local FOVChanges2 = {
	FieldOfView = 70
}
local TweenInformation2 = TweenInfo.new(
	1, -- tween length
	Enum.EasingStyle.Quint, -- easing Style
	Enum.EasingDirection.Out, -- easing Direction
	0, -- repetition time
	false, -- reverse?
	0 -- delay
)

local tween2 = TweeningService:Create(camera, TweenInformation2, FOVChanges2)

-- Functions --

local STMBackground = script.Parent:WaitForChild('STMBackground')

-- Function to smoothly change the BorderColor3
local function changeBorderColor(targetColor, duration)
	local initialColor = STMBackground.BorderColor3
	local startTime = tick()
	local endTime = startTime + duration

	local function updateColor()
		local currentTime = tick()
		if currentTime >= endTime then
			STMBackground.BorderColor3 = targetColor
			return true
		else
			local lerpedColor = Color3.new(
				initialColor.r + (targetColor.r - initialColor.r) * ((currentTime - startTime) / duration),
				initialColor.g + (targetColor.g - initialColor.g) * ((currentTime - startTime) / duration),
				initialColor.b + (targetColor.b - initialColor.b) * ((currentTime - startTime) / duration)
			)
			STMBackground.BorderColor3 = lerpedColor
			return false
		end
	end

	while not updateColor() do
		wait() -- Wait for the next frame
	end
end

-- Function to flash BorderColor3 multiple times and reset it
local function flashAndResetBorderColor(targetColor, flashCount, flashSpeed, duration)
	for i = 1, flashCount do
		changeBorderColor(targetColor, flashSpeed)
		wait(flashSpeed)
		changeBorderColor(Color3.new(80/255, 80/255, 80/255), flashSpeed)
		wait(flashSpeed)
	end

	wait(duration) -- Wait for the specified duration before resetting
	changeBorderColor(Color3.new(80/255, 80/255, 80/255), flashSpeed)
end

-- Event Handlers --

UIS.InputBegan:connect(function(key, gameProcessed)
	if key.KeyCode == Enum.KeyCode.LeftShift and gameProcessed == false then
		character.Humanoid.WalkSpeed = NewWalkSpeed
		sprinting = true
		while power > 0 and sprinting do
			power = math.max(power - .03, 0)
			Bar.Size = UDim2.new(1, 0, power / 10, 0)
			tween:Play()
			wait()
			if power <= 0 then
				-- Trigger the flashing effect with your desired parameters
				coroutine.wrap(flashAndResetBorderColor)(Color3.new(27/255, 42/255, 53/255), 5, 0.5, 5)
				
				-- Reset WalkSpeed and FOVChanges when stamina is exhausted
				character.Humanoid.WalkSpeed = NormalWalkSpeed
				camera.FieldOfView = 70
			end
		end

		-- When stamina gets fully depleted, temporarily increase the wait time
		if power <= 0 then
			increasedWait = true
			wait(5) -- Increase the wait time to 5 seconds
			increasedWait = false -- Reset the flag
		end
	end
end)

UIS.InputEnded:connect(function(key, gameProcessed)
	if key.KeyCode == Enum.KeyCode.LeftShift and gameProcessed == false then
		character.Humanoid.WalkSpeed = NormalWalkSpeed
		sprinting = false
		while power < 10 and not sprinting do
			power = math.min(power + .03, 10)
			Bar.Size = UDim2.new(1, 0, power / 10, 0)
			tween2:Play()

			-- Stamina Recharge Delay
			if increasedWait then
				wait(5) -- Increase the wait time to 5 seconds when fully depleted
			else
				wait(0.085) -- Adjust the time (in seconds) for the recharge rate you desire
			end

			wait()
			if power <= 0 then
				character.Humanoid.WalkSpeed = NormalWalkSpeed
			end
		end
	end
end)
1 Like