Hello!
I’ve been making a simple script where if a certain button is pressed, a remote event will fire.
However, the remote event fires mutliple times. About every 1 time I click “E” it fires around 11 times.
I want the remote event to fire only ONCE when I press “E”
I also have the problem where when the remote event is SPAMMED, after the cooldown is done, it fires again.
Heres the local script in StarterCharacterScripts:
cooldown = false
local player = game.Players.LocalPlayer
repeat wait() until player.Character.Humanoid
local Special = game.ReplicatedStorage:WaitForChild("Special")
local ShowKnightEvent = game.ReplicatedStorage:WaitForChild("ShowSpecialKnife")
local humanoid = player.Character.Humanoid
local mouse = player:GetMouse()
local character = player.Character
local HPR = character:WaitForChild("HumanoidRootPart")
mouse.KeyDown:connect(function(key)
if not cooldown then
if key == "e" then
cooldown = true
Special:FireServer()
ShowKnightEvent:FireServer()
wait(20)
cooldown = false
end
elseif cooldown == true then
print("still on special cooldown")
end
end)
I would check the time since the event was last fired on the server, not the client. An exploiter can delete your LocalScript and rewrite it to fire constantly.
Fortunately, LuaU has something that can help here, called tick(). This is a measure of the time that has elapsed since January 1st, 1970, and can be used to relatively count time.
Instead, on a server script, try something similar to:
local time_since_last_fired : number = tick()
event.OnServerEvent:Connect(function(plyr : Player)
-- If the current time since 1970/01/01 minus the time since the
-- event was last fired, and time_since_last_fired was updated
-- is less than 10 seconds, halt the function
if tick() - time_since_last_fired < 10 then return end
-- Update the above value to the time the event was fired
time_since_last_fired = tick()
end)
Note that this will be applicable to all players that fire the event, meaning that every player will have to wait until the cooldown has elapsed.
If you want to fix this, I suggest appending the player’s name & time_since_last_tick to a table, and then checking from there.
I think your problem is the wait(20) which stops the function for 20 seconds and then the debounce runs which cause the player to be able to spam it so many times.
should probably try using UserInputService like below and check key before cooldown if its even the right input
with the way you where doing it I think any key pressed would cause it to fire to the last if statement and print
local player = game.Players.LocalPlayer
repeat wait() until player.Character.Humanoid
local Special = game.ReplicatedStorage:WaitForChild("Special")
local ShowKnightEvent = game.ReplicatedStorage:WaitForChild("ShowSpecialKnife")
local humanoid = player.Character.Humanoid
local mouse = player:GetMouse()
local character = player.Character
local HPR = character:WaitForChild("HumanoidRootPart")
local UserInputService = game:GetService('UserInputService')
local cooldown
UserInputService.InputBegan:Connect(function(InputObject, onGui)
if InputObject.KeyCode == Enum.KeyCode.E then
if cooldown then
print("still on special cooldown")
else
cooldown = true
Special:FireServer()
ShowKnightEvent:FireServer()
wait(20)
cooldown = nil
end
end
end)
also as stated above you should probably have a server side cool down to keep this from being hacked/repeat fired
local cooldownplayers = {}
local cooldowntime = 3
game.ReplicatedStorage.RemoteEvent.OnServerEvent:Connect(function(player)
if not cooldownplayers[player] then
print('success')
spawn(function() -- In a spawn function so that the function does not stop.
cooldownplayers[player] = true
task.wait(cooldowntime)
cooldownplayers[player] = false
end)
else
print('not success')
end
end)
try this, i’ve explained all changes and uses in the script
local cooldown = false
local uis = game:GetService("UserInputService") --First I would replace mouse.KeyDown() with uis since KeyDown is depricated
uis.InputBegan:Connect(function(key,typing)
if typing then return end --This will stop the function if the player is typing in a textbox of some sort (like the chat)
if key.KeyCode == Enum.KeyCode.E then --first we get then enum keycode by doing key.keycode
if not cooldown then --then we check if cooldown is false ("not cooldown" is the same thing as "cooldown == false")
cooldown = true
Special:FireServer()
ShowKnightEvent:FireServer()
delay(20,function() --using delay to prevent any possible yielding
cooldown = false
end)
elseif cooldown then --same thing here just putting cooldown is the same thing as "cooldown == true"
print("cooldown is active")
end
end
end)
cooldown = false
local player = game.Players.LocalPlayer
repeat wait() until player.Character.Humanoid
local Special = game.ReplicatedStorage:WaitForChild("Special")
local ShowKnightEvent = game.ReplicatedStorage:WaitForChild("ShowSpecialKnife")
local humanoid = player.Character.Humanoid
local mouse = player:GetMouse()
local character = player.Character
local HPR = character:WaitForChild("HumanoidRootPart")
mouse.KeyDown:Connect(function(key)
if key == "e" and cooldown == false then
Special:FireServer()
ShowKnightEvent:FireServer()
cooldown = true
task.wait(20)
cooldown = false
elseif key == "e" and cooldown == true then
print("still on special cooldown")
end
end)
What do you mean by it will automatically fire? If your spamming it then that is the cause of it firing again after the cooldown.
mouse.KeyDown:Connect(function(key)
if key == "e" and cooldown == false then
Special:FireServer()
ShowKnightEvent:FireServer()
cooldown = true
task.wait(20)
cooldown = false
end
if key == "e" and cooldown == true then
print("still on special cooldown")
end
end)