Keybinds are spammable for a short time before they are put on cooldown

I have a keybind (h) to fire an event in my game
It is only supposed to fire once, but if you spam it fast enough you can fire it around 10+ times before it is put onto cooldown

code

local player = game.Players.LocalPlayer
local event = game.ReplicatedStorage.Sacrifice
local UIS = game:GetService("UserInputService")
local cd = false
local mouse = player:GetMouse()
local effect = game.Lighting.SacrificeEffect


mouse.KeyDown:Connect(function(key)
	key = key:lower()
	if key == 'h' and cd == false and not player.Character:FindFirstChild("Sacrificed") then
		cd = true
		local fade = player.PlayerGui.SPELLFLASH.Red
		local tween = game.TweenService:Create(fade, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {["BackgroundTransparency"] = 0})
		local tween2 = game.TweenService:Create(fade, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {["BackgroundTransparency"] = 1})
		event:FireServer()
		cd = false
		player.Character.ChildRemoved:Connect(function()
			if not player.Character:FindFirstChild("Sacrificed") then
				local fade = player.PlayerGui.SPELLFLASH.Red
				local tween = game.TweenService:Create(fade, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {["BackgroundTransparency"] = 0})
				local tween2 = game.TweenService:Create(fade, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {["BackgroundTransparency"] = 1})
			end
		end)
	end
end)

server code

local event = game.ReplicatedStorage.Sacrifice
local anim = script.Animation

event.OnServerEvent:Connect(function(player)
	local char = player.Character
	local hum = player.Character:WaitForChild("Humanoid")
	local energy = hum:WaitForChild("sacEnergy")
	local maxenergy = hum:WaitForChild("MaxSac")
	local loadanim = hum:LoadAnimation(anim)
	if not player.Character:FindFirstChild("Sacrificed") then
		game.ReplicatedStorage.Events.SpellFOV:FireClient(player)	
		loadanim:Play()
		wait(1)
		char.LowerTorso.Dagger.Transparency = 1
		char.RightHand.Dagger.Transparency = 0
		
		wait(1)
		hum:TakeDamage(10)	
		local val = Instance.new("BoolValue")
		val.Name = "Sacrificed"
		val.Parent = char
		if energy.Value < maxenergy.Value then	
			energy.Value += 35
			wait(3)
			char.LowerTorso.Dagger.Transparency = 0
			char.RightHand.Dagger.Transparency = 1	
			wait(15)
			val:Destroy()
			loadanim:Stop()
		end	
	end
end)

You are able to spam it due to the fact that in the server sided code, you wait 2 seconds before making the BoolValue, in that 2 seconds, the user is still able to click the button. To prevent this, you could add a debounce on the client side that waits for the BoolValue to be created.

	cd = true
	local fade = player.PlayerGui.SPELLFLASH.Red
	local tween = game.TweenService:Create(fade, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {["BackgroundTransparency"] = 0})
	local tween2 = game.TweenService:Create(fade, TweenInfo.new(1, Enum.EasingStyle.Linear, Enum.EasingDirection.In), {["BackgroundTransparency"] = 1})
	event:FireServer()
    player.Character:WaitForChild("Sacrificed")
	cd = false

PS.: You should use UserInputService instead of mouse.KeyDown

1 Like

I’ve been told this a lot but I can never get UserInputService to work properly for me.

Why, what’s the issue with it?

I’m not sure really, but when I try to do keybinds it just doesn’t detect input at all

Show me an example of what you are trying to do, and make sure it’s a localscript either in StarterPlayerScripts, or StarterCharacterScripts

local UIS = game:GetService("UserInputService")

UIS.InputBegan:Connect(function(key)
	if key.KeyCode == Enum.KeyCode.B then
		print("pressed b")
	end
end)

this is a local script in startercharacterscripts, and when i press B nothing is printed (nvm there was a typo in my script in studio it prints now)

but my main issue with UserInputService is the holding keybinds

I can script the actual keybinds fine but if I try to do something like make the player take damage while they hold M for example, when they release M they keep taking damage

You can use InputEnded to detect when the user stopped holding it, and use UIS:IsKeyDown to detect when the player is holding it.

UIS.InputBegan:Connect(function(input, gpe)
    if gpe then return end
    while UserInputService:IsKeyDown(Enum.KeyCode.M) do
        print("holding M")
        task.wait()
    end
end)

UIS.InputEnded:Connect(function(input, gpe)
    if gpe then return end
    if input.KeyCode == Enum.KeyCode.M then
       print("stopped holding M")
    end
end)

i can do this fine however like i said if i try to damage them while they hold M they still get damaged after they stop holding M

It works fine for me, are you sure you wrote it correctly?

local UIS = game:GetService("UserInputService")
local player = game:GetService("Players").LocalPlayer
local char = player.Character

UIS.InputBegan:Connect(function(input, gpe)
	if gpe then return end
	while UIS:IsKeyDown(Enum.KeyCode.M) do
		char:FindFirstChild("Humanoid"):TakeDamage(10)
		task.wait(2)
	end
end)

UIS.InputEnded:Connect(function(input, gpe)
	if gpe then return end
	if input.KeyCode == Enum.KeyCode.M then
		print("stopped holding M")
	end
end)
1 Like

I meant if I fire an event to the server and damage them on the server, when I try to stop it, it doesn’t stop.

Could you write the code and send how you tried it?

yes

local script

UIS.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then return end
	if input == Enum.KeyCode.M then
		game.ReplicatedStorage.DamageStart:FireServer()	
	end
end)

UIS.InputEnded:Connect(function(input, gameProcessed)
	if gameProcessed then return end
	if input == Enum.KeyCode.M then
		game.ReplicatedStorage.DamageEnd:FireServer()
	end
end)

server

game.ReplicatedStorage.DamageStart.OnServerEvent:Connect(function(player)
     repeat
     wait(2)
     player.Character.Humanoid:TakeDamage(10)
     until
		
game.ReplicatedStorage.DamageEnd.OnServerEvent:Connect(function(player)
		end)		
	end
end)

i originally used a different loop to do the damage and it worked until i tried to stop the loop
i think it was a “repeat until” loop i used before

What you could do is the following:

-- client

UIS.InputBegan:Connect(function(input, gameProcessed)
	if gameProcessed then return end
	if input.KeyCode == Enum.KeyCode.M then
		game.ReplicatedStorage.DamageStart:FireServer()	
	end
end)

UIS.InputEnded:Connect(function(input, gameProcessed)
	if gameProcessed then return end
	if input.KeyCode == Enum.KeyCode.M then
		game.ReplicatedStorage.DamageEnd:FireServer()
	end
end)
-- server
_G.TakingDamage = false

game.ReplicatedStorage.DamageStart.OnServerEvent:Connect(function(player)
    _G.TakingDamage = true
    repeat
        wait(2)
        player.Character.Humanoid:TakeDamage(10)
    until _G.TakingDamage = false
end)

game.ReplicatedStorage.DamageEnd.OnServerEvent:Connect(function(player)
    _G.TakingDamage = false
end)
1 Like

i’ll try this now

thank you for all your help!

No problem, let me know if you have any other questions.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.