So this is a punch script for whenever the player presses q, the original script was a local one inside StarterCharacterScripts. However i realised that the player can exploit in localscripts and change the debounce, therefore changing the cooldown of punches and beating everyone to death with the force of 1000 slaps.
here's the updated server-sided script that is inside StarterCharacterScripts
local UserInputService = game:GetService("UserInputService") game.Players.PlayerAdded:Connect(function(player) if player then print("player found") else error("player not found aaaaa") end local character = player.Character or player.CharacterAdded:Wait() local Root = character:WaitForChild("HumanoidRootPart") local Animation = character:WaitForChild("Humanoid"):LoadAnimation(script:WaitForChild("Animation")) local Debounce = 2 --might change if i add a training update local keybind = Enum.KeyCode.Q local CanPunch = true UserInputService.InputBegan:Connect(function(input, busy) if input.KeyCode == keybind and not busy then if CanPunch == true then CanPunch = false Animation:Play() Animation.Looped = false game.ReplicatedStorage.AttackRemote.Attack:FireServer() wait(Debounce) CanPunch = true end end end) end)
now as you can see i put in a PlayerAdded which im not sure is working or not so i used a print and error which doesnt show anything in the output so im kind of clueless there
now whenever i get rid of the old localscript this no longer works so clearly the old localscript is actually working and not the new server sided script for some reason and this shows NO ERRORS in the output
here is the old localscript
local UserInputService = game:GetService("UserInputService") local player = game.Players.LocalPlayer local character = player.Character or player.CharacterAdded:Wait() local Root = character:WaitForChild("HumanoidRootPart") local Animation = character:WaitForChild("Humanoid"):LoadAnimation(script:WaitForChild("Animation")) --Settings// local Debounce = 2 --might change if i add a training update local keybind = Enum.KeyCode.Q UserInputService.InputBegan:Connect(function(input, busy) if input.KeyCode == keybind and not busy then Animation:Play() Animation.Looped = false game.ReplicatedStorage.AttackRemote.Attack:FireServer() wait(Debounce) end end)
i really dont know what its deal is
An easy solution is to continue to method, but do your checks on the server where it cannot be exploited.
-- Client local userInputService = game:GetService('UserInputService') local Players = game:GetService('Players') local replicatedStorage = game:GetService('ReplicatedStorage') local Event = replicatedStorage:WaitForChild('RemoteEvent') local Player = Players.LocalPlayer userInputService.InputBegan:Connect(function(Input, gameProcessedEvent) if gameProcessedEvent then return end if Input.KeyCode == Enum.KeyCode.Q then Event:FireServer() end end)
And then for the server.
-- Server local replicatedStorage = game:GetService('ReplicatedStorage') local Event = replicatedStorage:WaitForChild('RemoteEvent') local Debounces = {} local debounceTime = 2 Event.OnServerEvent:Connect(function(Player) if not Collection[Player.Name] then Collection[Player.Name] = tick() end if tick() - Collection[Player.Name] > debounceTime then Collection[Player.Name] = tick() -- combat stuff here end end)
Basically you using tick() to calculate how long since they've lasted fired the remote, and it's been longer than the debounce time then it'll swing, otherwise won't do anything, and obviously it's on the server so they cannot spoof it whatsoever.