Help on stamina bar script

Hi I have been trying to make a stamina bar script

I have 2 main issues

1.) How should I go about subtracting stamina from the players current stamina in the server script
dont mind the current method that has “while max stamina”

2.)Also how do I make the local script change the gui in my local script I used udim.2 new

sorry for the mess first time asking for help on the dev forum. I am also willing to take feedback on how to properly use the devforum thank you in advance

Local script down here

local userInput = game:GetService('UserInputService')
local Player = game:GetService('Players')
local replicatedStorage = game:GetService("ReplicatedStorage")



local sprintSpeed = 50
local walkSpeed = 16 
local player = Player.LocalPlayer 

local function BeginSprint(input, gameProcessed)
	if not gameProcessed then
		if input.UserInputType == Enum.UserInputType.Keyboard then
			local keycode = input.KeyCode
			if keycode == Enum.KeyCode.LeftShift then
				print("start")
				replicatedStorage.RemoteEvents.Sprint:FireServer("Began")
			end
		end
	end 
end




local function EndSprint(input, gameProcessed)
	if not gameProcessed then
		if input.UserInputType == Enum.UserInputType.Keyboard then
			local keycode = input.KeyCode
			if keycode == Enum.KeyCode.LeftShift then
				print("stop")
				replicatedStorage.RemoteEvents.Sprint:FireServer("Ended")
			end
		end
	end 
end


userInput.InputBegan:Connect(BeginSprint)
userInput.InputEnded:Connect(EndSprint)

replicatedStorage.RemoteEvents.StaminaUpdate.OnEvent:Connect(function(stamina, maxStamina)
	Player.LocalPlayer.PlayerGui.Stamina.Bar.Size = UDim2.new(0,(stamina/maxStamina)*.2, 0, 29)
end)  

serverscript

local replicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local runService = game:GetService("RunService")
local sprintSpeed = 50
local walkSpeed = 16 
local maxStamina = 500 
local sprintingPlayer = {}

Players.PlayerAdded:Connect(function(player)
	local stamina = Instance.new("IntValue", player)
	stamina.Value = maxStamina
	stamina.Name = "Stamina"
	
	stamina.Changed:Connect(function(property)
		replicatedStorage.RemoteEvents.StaminaUpdate:FireClient(player, stamina.Value, maxStamina)
	end)
end)

replicatedStorage.RemoteEvents.Sprint.OnServerEvent:Connect(function(player, state)
	print("hello")
	local humanoid = player.Character.Humanoid
	if state == "Began" then
		humanoid.WalkSpeed = sprintSpeed
		while maxStamina > 0 do
			maxStamina = maxStamina -1
		end
		print("com")
		print(maxStamina)
	elseif state == "Ended" then
		humanoid.WalkSpeed = walkSpeed
		print("bust")
	end
end)


2 Likes

For the server script, you created an IntValue, but you never parented it to the character or in a folder.
Once parented lets say to the character, then on the while loop, substract that specific IntValue inside the character

local replicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local runService = game:GetService("RunService")
local sprintSpeed = 50
local walkSpeed = 16 
local maxStamina = 500 
local sprintingPlayer = {}

Players.PlayerAdded:Connect(function(player)
	local stamina = Instance.new("IntValue", player)
	stamina.Value = maxStamina
	stamina.Name = "Stamina"
	
	local CHAR = player.Character or player.CharacterAdded -- Find the character
	stamina.Parent = CHAR -- parent the IntValue
	
	stamina.Changed:Connect(function(property)
		replicatedStorage.RemoteEvents.StaminaUpdate:FireClient(player, stamina.Value, maxStamina)
	end)
end)

replicatedStorage.RemoteEvents.Sprint.OnServerEvent:Connect(function(player, state)
	print("hello")
	local isStamina = player.Character:FindFirstChild("Stamina") -- Find the IntValue
	if isStamina then
		local humanoid = player.Character.Humanoid
		if state == "Began" then
			humanoid.WalkSpeed = sprintSpeed
			while isStamina.Value > 0 do  -- substract from the IntValue
				isStamina.Value = isStamina.Value -1
			end
			print("cum")
			print(isStamina.Value)
		elseif state == "Ended" then
			humanoid.WalkSpeed = walkSpeed
			print("bust")
		end
	end
end)
1 Like

There are a couple of Issues with your Script, some are minor, while some are bigger and completely unnecessary to have at all.

To Start off, I see no purpose to Have a sprintingPlayer table, you can just use this RemoteEvent to fire when the State Changes, Plus, the Player is the first argument within a Server Event, This will make it much easier for you to keep track of the Player.

For your IntValue creation, There is a reason Developers never use the Second Argument to Parent:

It causes Preformace issues.
You should Also first (before anything else) Apply the Name, then the Properties, this should be the “proper” way to Create an Instance

local stamina = Instance.new("IntValue") -- Create Instance
stamina.Name = "Stamina" -- Prioritize this FIRST (Always)
stamina.Value = maxStamina -- Apply Properties
stamina.Parent = player -- Prioritize this LAST (Always)

Your Server script doesn’t require a while loop to function, if anything its a waste of Server Resources to be using it for this purpose, this is what makes an inefficient system, Instead it would be best Practice to use math.clamp for this case, math.clamp will limit the Value between the minimum value and maximum value, this is useful because because if a number is over or below a limit, it will automatically be set to this value, Here is an Example:

isStamina.Value = math.clamp(isStamina.Value - 1, 0, 100)
-- 0 is the minimum
-- 100 is the maximum

or, if you only plan to set one limit for a certain part, you can use math.min() or math.max() to handle this:

isStamina.Value = math.max(0, isStamina.Value - 1) -- returns the Largest Value
isStamina.Value = math.min(100, isStamina.Value - 1) -- returns the Smallest Value

Why?

4 Likes

To change the bar size of the GUI for the client. You could use that remote event you are firing, sending the value of stamina, while 1 in Udim in scale would be full bar, and just transform the 500 max val to be 500 = 1. So 250 would be 0.5

Details. I dont think that using the state sent by the client is the best idea to read when the player is spending stamina. Would be trusting the client and could glitch.

Maybe reading on ServerSide when the player is walking would be better than trusting what client is saying about their state

2 Likes

Thank you for this and the stuff above!! ^^

If you dont mind helping again

line 15 is throwing this error at me

ServerScriptService.StaminaServer:15: invalid argument #3 (Instance expected, got RBXScriptSignal) -

1 Like

Sorry, I made a few mistakes, I didnt notice you actually parented the IntValue to player. And I forgot to add a :Wait on the character.
Lets dump that. Parent the IntValue to player, which ofc its a best idea, cause the character model will be destroyed when player dies, I was just giving an example, use this on playerAdded instead:

game.Players.PlayerAdded:Connect(function(player)
	local stamina = Instance.new("IntValue")
	stamina.Value = 500
	stamina.Name = "Stamina"

	stamina.Parent = player
	
	stamina.Changed:Connect(function(property)
		replicatedStorage.RemoteEvents.StaminaUpdate:FireClient(player, stamina.Value, maxStamina)
	end)
end)

btw, the Changed event on that IntValue, the “property” is actually the new value gotten, so you could do this too:

stamina.Changed:Connect(function(property)
		replicatedStorage.RemoteEvents.StaminaUpdate:FireClient(player, property, maxStamina)
end)

Hi I changed the script a bit and it keeps on subtracting until the stamina becomes 0. If dosent seem to check the state if its == began/ended

local replicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local runService = game:GetService("RunService")
local sprintSpeed = 50
local walkSpeed = 16 
local maxStamina = 500 

Players.PlayerAdded:Connect(function(player)
	local stamina = Instance.new("IntValue")
	stamina.Value = 500
	stamina.Name = "Stamina"

	stamina.Parent = player
	
	stamina.Changed:Connect(function(property)
		replicatedStorage.RemoteEvents.StaminaUpdate:FireClient(player, property, maxStamina)
	end)
end)

replicatedStorage.RemoteEvents.Sprint.OnServerEvent:Connect(function(player, state)
	print("hello")
	local isStamina = player:FindFirstChild("Stamina") -- Find the IntValue
	if isStamina then
		local humanoid = player.Character.Humanoid
		if state == "Began" then
			humanoid.WalkSpeed = sprintSpeed
			while isStamina.value > 0 do
				isStamina.Value = isStamina.Value -1
				wait(.1)
			end
			print("com")
			print(maxStamina)
			print(state)
		elseif state == "Ended" then
			humanoid.WalkSpeed = walkSpeed
			print("bust")
		end
	end
end)


1 Like

Yup, because you are never stopping that while loop. You could break the loop, or change the approach and dont use a loop to reduce the value.

A while loop will run forever until you break it.

	while isStamina.value > 0 do
		isStamina.Value = isStamina.Value -1
		if StopTheLoop then
            warn("loop is stopping")
			break
		end
		wait(.1)
	end
1 Like

Problem Solved:

I did not remember the state of the player in the function so it kept on running
and I send the wrong values

replicatedStorage.RemoteEvents.Sprint.OnServerEvent:Connect(function(player, state)
	print("hello")
	local isStamina = player:FindFirstChild("Stamina") -- Find the IntValue
	if isStamina then
		local humanoid = player.Character.Humanoid
		if state == "Began" then
			humanoid.WalkSpeed = sprintSpeed
			while isStamina.value > 0 and humanoid.WalkSpeed == sprintSpeed do
				isStamina.Value = isStamina.Value -1
				wait(.1)
			end
			humanoid.WalkSpeed = walkSpeed
			print("com")
			print(maxStamina)
			print(state)
		elseif state == "Ended" then
			humanoid.WalkSpeed = walkSpeed
			print("bust")
		end
	end
end)

1 Like

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