So, it looks like you have portions of your stamina system on the server, and portions of it on the client. I’d recommend putting it all in the same place just to make things easier (though it is possible to have them separate if you insist). I’d recommend the client-side since you’re working with tools, and because generally it’s better to do movement modification on the client-side anyway.
Since it sounds like you’ll be using multiple tools, and each tool will be modifying the same stamina system, I’d recommend you use a ModuleScript
on the client that all the LocalScript
s for the tools can access. I recommend this since it’ll be easy to keep track of what the current stamina is and update all the other tools with the current stamina when we modify it. I like to put my clients’ modules in game.ReplicatedStorage
. For this example, lets name this module “StaminaModule”.
`ModuleScript` in `game.ReplicatedStorage` named "StaminaModule"
-- // In a ModuleScript in game.ReplicatedStorage
local module = {}
local currentlyRegening = false
local regenIncrement = 1 -- // How fast the player will regain stamina
module.maxStamina = 100
module.currentStamina = module.maxStamina
-- // Where you should put whatever tween you are using.
function StaminaUITween()
-- // If you're adjusting the size of a GUI object, and `1` is the size when
-- // it is full, use something like this:
guiObject:TweenSize( -- // You'll have to define 'guiObject' with whatever you're animating
UDim2.new(module.currentStamina/module.maxStamina, 0, guiObject.Size.Y.Scale, 0), -- // endSize (required)
Enum.EasingDirection.In, -- // easingDirection (default Out)
Enum.EasingStyle.Sine, -- // easingStyle (default Quad)
.08, -- // time (default: 1)
true -- // should this tween override ones in-progress? (default: false)
)
end
function RegenStamina()
if (currentlyRegening) then -- // Don't want to start multiple regen loops
return nil
end
currentlyRegening = true
coroutine.wrap(function() -- // Create a seperate thread so we don't yield every time we modify the stamina
print("We have started regeneration stamina")
while (module.currentStamina < module.maxStamina) do
module.currentStamina = math.min(module.currentStamina + regenIncrement, module.maxStamina)
StaminaUITween() -- // Tween the stamina guiObject
wait(.1) -- // Our loop's yield
end
print("We have regenerated back to full stamina")
currentlyRegening = false -- // Make it so we can start the regeneration loop if needed
end)()
end
-- // Changes the module.currentStamina to whatever <newStamina> is equal to
function module.ModifyStamina(newStamina)
if (not tonumber(newStamina)) then
warn("Failed to update stamina, `newStamina` was not a number")
return nil
end
module.currentStamina = math.clamp(newStamina, 0, module.maxStamina) -- // Set the new stamina while making sure it is a valid number that stamina could be
if (module.currentStamina < module.maxStamina) then
print("We have modified the current stamina to", module.currentStamina)
RegenStamina() -- // Start regenerating the stamina
else
StaminaUITween() -- // Tween the stamina guiObject
end
end
print("Stamina module has been successfully 'require'-d ")
return module
Now that we have the stamina module setup, we have to actually utilize it in whatever tool that we’ve got.
`LocalScript` for an example `Tool` object
-- // This is a `LocalScript` inside of a `Tool` object
local staminaModule = require(game.ReplicatedStorage:WaitForChild("StaminaModule"))
local staminaRequired = staminaModule.maxStamina * .10 -- // It takes 10% of our maximum stamina to perform an action with this tool
-- // When we activate the tool
script.Parent.Activated:Connect(function()
if (staminaModule.currentStamina >= staminaRequired) then -- // Make sure we have enough stamina
print("We have enough stamina to preform an action with", script.Parent.Name .. "!")
print("Subtracting stamina!")
staminaModule.ModifyStamina(staminaModule.currentStamina - staminaRequired)
-- // Do whatever the tool is supposed to do here
end
end)
Sorry, I may have used some complicated stuff here, I’ll link some stuff here if you want to understand:
ModuleScript
coroutine
GuiObject:TweenSize()
Hopefully this helps!