I’m working on abilities and it seems like cooldowns should be handled by the server to prevent exploiters from spamming the ability, however, it seems like I also need to handle cooldown on the client to prevent particle and animation spam which is just for cosmetic.
What’s the best way to do this though? Currently the ability cooldowns are stored on the server so my options are either put them in replicated storage or use remote events/functions or perhaps there’s a completely different approach to do this?
This is my current code.
-- Client
function Input:InputBegan(inputObject, gameProcessed)
if UI:GetCurrentMenu() == "StartScreen" then PressAnyKeyToStart(inputObject) return end
if self.Player.Class ~= nil then
if inputObject.UserInputType == Keybinds.PrimaryAttack then
local requestAttackTime = ReplicatedStorage.Remotes.RemoteFunction
local attackTime = requestAttackTime:InvokeServer()
if playersAttacking[game.Players.LocalPlayer.Name] and os.clock() - playersAttacking[game.Players.LocalPlayer.Name] < attackTime then
warn("We're already attacking")
return
end
playersAttacking[game.Players.LocalPlayer.Name] = os.clock()
Action:FireServer("PrimaryAttack",nil)
self.Player.Animation:PlayAnimation("Hit1")
return
end
end
end
-- Server
local function HandleAction(player,actionName,keycode)
-- Cooldown Check
local name = player.Name..actionName
local cooldown, attackTime = classModule[actionName](player.Character,true)
if playerCooldowns[name] and os.clock() - playerCooldowns[name] < cooldown then
warn("On cooldown")
return
end
-- Checks if they're doing another attack already
if playersAttacking[player.Name] and os.clock() - playersAttacking[player.Name] < attackTime then
-- warn("Player is already doing another action")
return
end
playerCooldowns[name] = os.clock()
playersAttacking[player.Name] = os.clock()
classModule[actionName](player.Character) -- Do ability
end
RequestAttackTime.OnServerInvoke = function(player)
return 0.7
end