What do you want to achieve? Keep it simple and clear!
some sort of a timeout that checks if player has been sprinting, and if not hten regenerate stamina
What is the issue? Include screenshots / videos if possible!
i dont know how to set a custom timeout
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
i did look but nothing seemed to work, i also asked ai, but it didnt solve the issue
server script
local stopLCtrlhold = false
game.ReplicatedStorage.events.keyPress.OnServerEvent:Connect(function(plr,keycode,id) --keycode and id are being sent from localscript, keycode is self explanatory, id: if 1 then player pressed ctrl, if 0 then player released ctrl
if keycode == 'LCtrl' then
if id == 1 then
stopLCtrlhold = false
if game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value >= 10 then
plr.Character.Humanoid.WalkSpeed = 40
repeat
game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value -= 1
game.ReplicatedStorage.events.sprint:FireClient(plr,game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value,game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.max.Value) --fires client to change UI stamina bar (and i just realised i could have done it here)
task.wait(0.2)
until game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value <= 0 or stopLCtrlhold == true
plr.Character.Humanoid.WalkSpeed = 16
end
elseif id == 0 then
stopLCtrlhold = true
end
end
end)
if possible, i need this system in a serverscript (exploiers issue)
feel free to ask questions about this code because i`ve been writing it for only me to understand
You should not handle sprinting on the server. Make everything on the client, as for regenerating the stamina after not sprinting for a while, id use threads
(client)
local stamina = 0
local thread
function changeSprint(sprinting)
if thread then pcall(task.cancel, thread) end
if sprinting then
-- player starts sprinting
humanoid.WalkSpeed = 40
thread = task.defer(function() -- start removing stamina untill sprinting changes or goes below 0
while true do
stamina -= 1
if stamina <= 0 then
changeSprint(false)
break
end
task.wait(1)
end
end)
return
end
-- player stops sprinting
humanoid.WalkSpeed = 16
thread = task.delay(2, function() -- after 2 seconds start regenerating
while stamina < 100 do
stamina += 1
task.wait(.1)
end
end)
end
note that this isnt the full code and i haven’t tested it
What stops the exploiter from setting their walkspeed to any value?
I would not bother with such a thing; you can opt for client sided anti cheats (altough not the most secure and you should not rely solely on them; will stop most kiddos) or a server sided teleport check
local spRegenThread : thread = nil
local function RegenerateSp()
-- regen some sp every seconds
end
SprintStarted.Event:Connect(function()
if spRegenThread then
task.cancel(spRegenThread)
spRegenThread = nil
end
-- decrease sp over time
end)
SprintEnded.Event:Connect(function()
spRegenThread = task.delay(waitTime, RegenerateSp)
end)
when i`m standing still, i could run. I fixed this but if i start running and then stand still i could still run in place
in some circumstances, while regenerating stamina, i could sprint and stamina would still regenerate
so if somebody knows how to fix at least one of them, let me know
first point is irrelevant to stamina regeneration. you cannot both standing still and run. i think you are talking about the animation though. but again irrelevant to the regen script.
second point when you sprint, you have to cancel the regen thread like i suggested to do. I don’t know how you signal for the “sprint start” so you should adapt to your own method. when you sprint, you cancel the thread and do the decrease stamina logic
all stamina logic is being held on script i wrote in the topic, heres the modified code (with task.cancel):
local stopLCtrlhold = false
local spRegenThread = nil
game.ReplicatedStorage.events.keyPress.OnServerEvent:Connect(function(plr,keycode,id)
if keycode == 'LCtrl' then
if id == 1 then
if plr.Character.Humanoid.MoveDirection == Vector3.new(0,0,0) then return end
stopLCtrlhold = false
if game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value >= 10 then
game.ReplicatedStorage.events.anihmatey:FireClient(plr,'run',true)
plr.Character.Humanoid.WalkSpeed = 40
if spRegenThread then
task.cancel(spRegenThread)
spRegenThread = nil
end
repeat
game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value -= 1
plr.Character.HumanoidRootPart.staminaBarLocal.bg.upper.Text = game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value
game:GetService('TweenService'):Create(plr.Character.HumanoidRootPart.staminaBarLocal.Frame,TweenInfo.new(0.03,Enum.EasingStyle.Linear,Enum.EasingDirection.Out),{Size = UDim2.new(0.2,0,game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value/game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.max.Value*-1)}):Play()
task.wait(0.1)
until game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value <= 0 or stopLCtrlhold == true
plr.Character.Humanoid.WalkSpeed = 16
game.ReplicatedStorage.events.anihmatey:FireClient(plr,'run',false)
end
elseif id == 0 then
spRegenThread = task.delay(1,function()
repeat
game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value += 1
plr.Character.HumanoidRootPart.staminaBarLocal.bg.upper.Text = game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value
game:GetService('TweenService'):Create(plr.Character.HumanoidRootPart.staminaBarLocal.Frame,TweenInfo.new(0.03,Enum.EasingStyle.Linear,Enum.EasingDirection.Out),{Size = UDim2.new(0.2,0,game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value/game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.max.Value*-1)}):Play()
task.wait(0.05)
until game.ServerStorage.users[plr.Name.."_"..plr.UserId].stamina.Value == 100
end)
stopLCtrlhold = true
end
end
end)
this is the video of a problem i am describing (the second one)
Hey! a time ago i did a stamina system that you have to wait until it regenerates, the problem is that the code is a really mess, I’ll try to making it more readble
there are quite a lot of condition checks here. also i am not sure if the press event, will it keep firing when the player hold the button?
my code assume you would only get sprint begin and end event once they changed.
you shall add some print() to see whether you get multiples of press event coming in so potentially it creates multiple regen threads and not cancelling the existing one properly
local defaultWalkSpeed = 16
local runSpeed = 26
local stamina = 100
local maxStamina = 100
local minStaminaToRun = 10
local staminaPerSecond = 1
local staminaRegenPerSecond = 1
local counter = 0
local isRunning = false
local isExhuasted = false
function StopRunning()
character.Humanoid.WalkSpeed = defaultWalkSpeed
PlayNoRun:Play()
end
function StartRunning()
if stamina >= minStaminaToRun and CanRun and humanoid.MoveDirection.Magnitude > 0 then
counter = 0
PlayRun:Play()
isRunning = true
character.Humanoid.WalkSpeed = runSpeed
end
end
function BindRunning(actionName: string, InputState: Enum.UserInputState)
if actionName == "Run" then
if InputState == Enum.UserInputState.Begin then
if not isExhuasted then
StartRunning()
else
StopRunning()
end
else
StopRunning()
isRunning = false
task.spawn(function()
while counter <= 2 and not isRunning do
counter += 1
task.wait(1)
end
end)
end
end
end
task.spawn(function()
while wait(.1) do
if not isRunning and stamina < maxStamina and counter >= 2 then
stamina += staminaRegenPerSecond
elseif isRunning and humanoid.MoveDirection.Magnitude > 0 and stamina > 0 then
stamina -= staminaPerSecond
end
if stamina > 0 then
isExhuasted = false
else
isExhuasted = true
StopRunning()
isRunning = false
end
end
end)
I know its not the best code, but you can enhance it, im showing you the logic about this, any question is welcome (also in my code you cant run if your stamina is < 10%, so you will have to wait until it regenerates)
local char = script.Parent.Parent.Character or script.Parent.Parent.CharacterAdded:Wait()
local runTrack = char.Humanoid.Animator:LoadAnimation(game.ReplicatedStorage.anims.run)
game.ReplicatedStorage.events.anihmatey.OnClientEvent:Connect(function(name,state)
if state == true then
if name == 'run' then runTrack:Play() end
elseif state == false then
if name == 'run' then runTrack:Stop() end
end
end)
script for getting player input:
local uis = game:GetService('UserInputService')
uis.InputBegan:Connect(function(i,g)
if g then return end
if i.KeyCode == Enum.KeyCode.LeftControl then
game.ReplicatedStorage.events.keyPress:FireServer('LCtrl',1)
end
end)
uis.InputEnded:Connect(function(i,g)
if i.KeyCode == Enum.KeyCode.LeftControl and not g then
game.ReplicatedStorage.events.keyPress:FireServer('LCtrl',0)
end
end)
P.S: i already fixed the problem (look previous messages)
EDIT: i fixed second issue by checking moveDirection every tick (stamina loss tick) and if it equals to 0, break from cycle
if plr.Character.Humanoid.MoveDirection.Magnitude == 0 then
game.ReplicatedStorage.events.anihmatey:FireClient(plr,'run',false)
break
end