Hey there, everyone. So, here’s the rundown. When the player presses CTRL, they kneel. I have a custom stamina and health regeneration system in place where if the player is kneeling, their stamina and health regeneration speed is increased. When the player stands back up, their regeneration speeds go back to normal.
This is all triggered when the player presses CTRL. A local script detects the player’s keypress with userInputService and then fires a serverEvent to increase or decrease the stamina by 1.5x. So, my question is: How can I prevent exploiters from firing the serverEvent from the client if the userInputService is only available in a local script?
Local Script
Button.InputBegan:Connect(function(Input)
if Input.KeyCode == Enum.KeyCode.LeftControl then
if not debounce then
debounce = true
CrouchedEvent:FireServer(true)
Animate1 = Humanoid:LoadAnimation(Crouch)
Animate1:Play()
Humanoid.WalkSpeed = 0
else
CrouchedEvent:FireServer(false)
Animate1:Stop()
Humanoid.WalkSpeed = 16
debounce = false
end
end
end)
Server Script (Event Handler)
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CrouchedEvent = ReplicatedStorage.Events:WaitForChild("CrouchedEvent")
local function updateStats(player, crouched)
if crouched then
player:WaitForChild("stats").regen.Value *= 1.5
player:WaitForChild("stats").stamRegen.Value *= 1.5
else
player:WaitForChild("stats").regen.Value /= 1.5
player:WaitForChild("stats").stamRegen.Value /= 1.5
end
end
CrouchedEvent.OnServerEvent:Connect(updateStats)
So instead of the client telling the server true or false, just fire with no arguments. Check on the server if they are in the crouchingPlayers table; if they are remove them from the table and reset their speed/stamina. If they are not, add them to the table and set their speed/stamina.
You can also add a debounce on the server. You can keep track of when the player last fired the RemoteEvent and only allow change their stats every X seconds.
Adding a debounce would definitely help secure it. But if the event were fired (by, let’s say an exploiter), they would still be added to the table. And they would only need to fire the event once to be added to the table, increasing their stamina and health regeneration without ever actually kneeling. Removing the true and false arguments is a good idea, but ultimately, will that help secure the event?
What keeps you from changing the walkspeed on the server so anyone who fires the remote can’t just fire it and keep their original walkspeed?
Also, you can use constant stamina values or booleans rather than multiplying it every single time the remote is fired
Here’s a bad example script to show you how you could implement the logic for this
local Stamina = Player:WaitForChild("stats"):WaitForChild("Stamina")
while task.wait() do
Stamina.Value += stamRegen.Value * (Crouching and 1.5 or 1)
end
Since the client can play any animation it wants and change its walkspeed, you need some kind of anti cheat.
If your goal is to have the player not be moving to have increased stat regeneration, then you can check the velocity and position of the HumanoidRootPart to see if they are actually staying still.
As for securing RemoteEvents, I generally like to have the client pass in as little information as possible through a RemoteEvent; not sure if it’s the best way of going about it but .
I like this idea a lot. A really simple solution. If they were to fire the event, then they’d still technically be kneeling and would be unable to move.