I made a server-sided sprint that goes like this:
[1] - Gets input from the client when the player presses shift and passes it to the server.
[2] - The server places players into a table when input is begun and takes them out when the input is ended.
[3] - Runs a loop that repeats until they are put into/taken out of the table which subtracts/adds a set amount of stamina.
The problem is that when someone presses shift really fast, it regens/drains really fast as well. This would lead to players being able to just shift spam in order to get back to the max stamina after they run out.
(Ex. https://gyazo.com/3dc28ed6e0f9c5193d6477de1a9370af.gif)
Any ideas on what the problem could be?
Server
local PlayerService, RepStorage, RunService = game:GetService('Players'), game:GetService('ReplicatedStorage'), game:GetService('RunService') ; local Module = require(RepStorage:WaitForChild('Modules'):FindFirstChild('MechanicsModule')) ; local Events = RepStorage.RemoteEvents ; local Sprint, UpdateStamina = Events.Sprint, Events.StaminaUpdate ; local MaxStamina = Module.MaxStamina ; local SprintCost, SprintModifier, SprintRegen = Module.SprintCost, Module.SprintModifier, Module.SprintRegen ; local NormalSpeed = Module.NormalSpeed ; local SprintSpeed = Module.SprintSpeed ; local WaitTime = .01 ; local SprintingPlayers = {} ; function isPlayerInTable(Player) for Index, Value in pairs(SprintingPlayers) do if Player.Name == Value then return true end end end function Sprinting(Stamina, Player, Humanoid) for i, SprintingPlayer in pairs(SprintingPlayers) do if isPlayerInTable(Player) ~= true then print'no sprint' return end repeat if Module.IsMoving(Humanoid) and isPlayerInTable(Player) then if Stamina.Value >= SprintCost then Stamina.Value = Stamina.Value - SprintCost ; Humanoid.WalkSpeed = SprintSpeed ; wait(WaitTime) ; else Humanoid.WalkSpeed = NormalSpeed ; wait(WaitTime) ; end elseif not Module.IsMoving(Humanoid) and isPlayerInTable(Player) then if Stamina.Value < MaxStamina then Stamina.Value = Stamina.Value + SprintRegen ; Humanoid.WalkSpeed = NormalSpeed ; wait(WaitTime) ; end end wait() ; until not isPlayerInTable(Player) or Humanoid:GetState() == Enum.HumanoidStateType.Dead end end function NotSprinting(Stamina, Player, Humanoid) if #SprintingPlayers > 0 then for i, SprintingPlayer in pairs(SprintingPlayers) do if not isPlayerInTable(Player) then repeat if Stamina.Value < MaxStamina then Stamina.Value = Stamina.Value + SprintRegen ; Humanoid.WalkSpeed = NormalSpeed ; wait(WaitTime) ; elseif Stamina.Value > MaxStamina then Stamina.Value = MaxStamina end wait() ; until isPlayerInTable(Player) or Humanoid:GetState() == Enum.HumanoidStateType.Dead end end elseif #SprintingPlayers <= 0 and not isPlayerInTable(Player) then repeat if Stamina.Value < MaxStamina then Stamina.Value = Stamina.Value + SprintRegen ; Humanoid.WalkSpeed = NormalSpeed ; wait(WaitTime) ; elseif Stamina.Value > MaxStamina then Stamina.Value = MaxStamina end wait() ; until isPlayerInTable(Player) or Humanoid:GetState() == Enum.HumanoidStateType.Dead end end function AddToTable(Stamina, Player, Humanoid) if not isPlayerInTable(Player) then table.insert(SprintingPlayers, Player.Name) Sprinting(Stamina, Player, Humanoid) end end function RemoveFromTable(Stamina, Player, Humanoid) if #SprintingPlayers > 0 then for Index, Value in pairs(SprintingPlayers) do if Value == Player.Name then table.remove(SprintingPlayers, Index) ; NotSprinting(Stamina, Player, Humanoid) ; end end else NotSprinting(Stamina, Player, Humanoid) ; end end PlayerService.PlayerAdded:Connect(function(Player) Player.CharacterAdded:Connect(function(Character) local Root = Character:WaitForChild('HumanoidRootPart') or Character:FindFirstChild('HumanoidRootPart') ; local Stamina = Instance.new('IntValue', Root) ; Stamina.Name = 'Stamina' ; Stamina.Value = MaxStamina ; Stamina.Changed:Connect(function(Property) UpdateStamina:FireClient(Player, Stamina.Value, MaxStamina) end) end) end) Sprint.OnServerEvent:Connect(function(Player, State, Tick) local Character = Player.Character ; local Root = Character:WaitForChild('HumanoidRootPart') or Character:FindFirstChild('HumanoidRootPart') ; local Stamina = Root:FindFirstChild('Stamina') or Root:WaitForChild('Stamina') ; local Humanoid = Character:FindFirstChild('Humanoid') ; if State then if not isPlayerInTable(Player) then AddToTable(Stamina, Player, Humanoid) ; -- print(Player.Name, 'IS SPRINTING', State) ; end elseif not State then if isPlayerInTable(Player) then RemoveFromTable(Stamina, Player, Humanoid) -- print(Player.Name, 'STOPPED SPRINTING', State) ; end end end)
Client
InputService.InputBegan:Connect(function(Input, gameProcessed) if not gameProcessed then if Input.KeyCode == Enum.KeyCode.LeftShift then -- print(Player.Name, 'began sprinting') Sprint:FireServer(true) ; end end end) InputService.InputEnded:Connect(function(Input, gameProcessed) if not gameProcessed then if Input.KeyCode == Enum.KeyCode.LeftShift then -- print(Player.Name, 'stopped sprinting') Sprint:FireServer(false) ; end end end)
Since then I've fixed the issue, thanks for all suggestions, and whaaaa- table.find() is a thing?