Efficient way to regenerate stamina

Hi, I made a stamina handler and it works but I can’t find a way to regenerate the stamina without breaking the script.

LocalScript

local Player = game.Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait(0.15)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local TweenService = game:GetService("TweenService")
local EventFolder = ReplicatedStorage.Events
Character:WaitForChild("Humanoid")
task.wait(1.25)

local Stamina = {
	CurrentStamina = Character.PlayerValues.Stamina,
	MaxStamina = 3000
};
Stamina.CurrentStamina.Value = Stamina.MaxStamina

local SwordLevels = {
	Light = Stamina.MaxStamina/8, -- Max stamina divided by 8, 8 slashes before running out
	Medium = Stamina.MaxStamina/6,
	Heavy = Stamina.MaxStamina/4
};

local Bar = script.Parent.Bar
EventFolder.Sword.Slash.OnClientEvent:Connect(function(SwordLevel)
	if SwordLevel == "Light" and Stamina.CurrentStamina.Value ~= 0 then
		Stamina.CurrentStamina.Value -= SwordLevels.Light
	end
	if SwordLevel == "Medium" and Stamina.CurrentStamina.Value ~= 0 then
		Stamina.CurrentStamina.Value -= SwordLevels.Medium
	end
	if SwordLevel == "Heavy" and Stamina.CurrentStamina.Value ~= 0 then
		Stamina.CurrentStamina.Value -= SwordLevels.Heavy
	end
end)

Stamina.CurrentStamina:GetPropertyChangedSignal("Value"):Connect(function()
	print(Stamina.CurrentStamina.Value)
	local size = Stamina.CurrentStamina.Value / Stamina.MaxStamina;
	if size > 1 then
		size = 1
	end
	Bar:TweenSize(UDim2.new(size, 0,1, 0), "Out", Enum.EasingStyle.Quad, 0.25, true, nil);
	if Stamina.CurrentStamina.Value == 0 then
		EventFolder.Sword.ChangeStatus:FireServer("False")
	end
end)

-- This is what I have and it doesn't work
spawn(function()
	while EventFolder.Sword.Slash.Changed and Stamina.CurrentStamina.Value ~= Stamina.MaxStamina or Stamina.CurrentStamina.Value <= Stamina.MaxStamina do
		if Stamina.CurrentStamina.Value == Stamina.MaxStamina then
			break;
		end
		Stamina.CurrentStamina.Value += 60
	end
end)

The slash event is fired through a server script inside a weapon. Everytime the weapon is slashed it fires so I know when it is slash then it consumes stamina depending on how heavy or light the weapon is.

if Stamina.CurrentStamina.Value == 0 then
		EventFolder.Sword.ChangeStatus:FireServer("False")
	end

this changes the sword to stop the player from slashing when the stamina reaches 0.

You need some kind of global to keep track of the regenerate “event”. It should start out as nil and be set to an event when regeneration starts. Once stamina is full again, disconnect the event and set it to nil. Each time you swing you can check for this event and stop it if it exists, delay for a couple seconds, then try to start the event.

Ok, so I should make a RegenStamina event and I should call stuff from the client and use a global script to handle the rest?

The script does not need to be global, just the variable that tracks whether regeneration is happening. It can be defined at the top of the script.

Ok, I don’t understand what you mean about the variable being global, can you explain that to me

local regenEvent = nil --Initially there is no regen because the stamina starts full

Stamina.CurrentStamina:GetPropertyChangedSignal("Value"):Connect(function()
	--If the stamina is now less than full
		wait(staminaRegenDelay)

	--Check if regenEvent is nil, if it is:
		regenEvent = RunService.Stepped:Connect(funtion()
			--:Disconnect() regenEvent when its full, and set regenEvent to nil
		end)

	--Otherwise, already regening, don't do anything
end)
1 Like

Interesting, I thought you were talking about remote events but this looks way more efficient

Be careful as I just made an important edit. You can use a thread with a while loop as your regen function or have it attached to RunService.Stepped but don’t do both.

Hey, sorry for this but do you know how I can cancel the regeneration when I detect a slash?
I tried doing something but it didn’t work

local regenEvent = nil
Stamina.CurrentStamina:GetPropertyChangedSignal("Value"):Connect(function()
	-- Handles Tweening
	local size = Stamina.CurrentStamina.Value / Stamina.MaxStamina;
	if size > 1 then
		size = 1
	end
	Bar:TweenSize(UDim2.new(size, 0,1, 0), "Out", Enum.EasingStyle.Quad, 0.25, true, nil);
	-- Handles Status
	if Stamina.CurrentStamina.Value == 0 then
		EventFolder.Sword.ChangeStatus:FireServer("False")
		script.Breathing:Play()
	else
		script.Breathing:Stop()
	end
	-- Handles Regeneration
	if Stamina.CurrentStamina.Value < Stamina.MaxStamina then
		wait(Settings.RegenDelay)
		if regenEvent == nil then
			regenEvent = RunService.Stepped:Connect(function()
				if EventFolder.Sword.Slash.Changed then
					regenEvent:Disconnect();
					regenEvent = nil
				end
				if Stamina.CurrentStamina.Value == Stamina.MaxStamina or Stamina.CurrentStamina.Value >= Stamina.MaxStamina then
					regenEvent:Disconnect();
					regenEvent = nil
				end
				Stamina.CurrentStamina.Value += Settings.AmountRegen
			end)
		end
	end
end)

After this line disconnect the regen event and set it to nil.

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