I made a rebirthing system but if the player clicks the button too fast it rebirths them multiple times and puts them into negatives
I have tried adding a debounce but that still doesnt help
here is a video as an example
here are the scripts
local script:
script.Parent.ConfirmRebirth.Activated:Connect(function()
local db = false
if not db then
if Power.Value >= requiredAmount then
Remotes.Rebirth:FireServer(requiredAmount)
db = true
task.wait(5)
db = false
end
end
end)
Use math.clamp() to ensure the final value remains above 0:
Example:
local Data = clientProfile.Data
-- 0 defines the lowest value it can be and math.huge defines the highest value
Data.Wins = math.clamp(Data.Wins - amount, 0, math.huge)
Data.Power = math.clamp(Data.Power - amount, 0, math.huge)
Move the requirement check and the cooldown to the server-side. The client is faster, which is the issue here. Since the server takes time to complete requests, people can rebirth again because the data is not set by the server yet. The client is always faster.
Unless I’m misunderstanding your point, the main issue in the code from the original post is not necessarily that the client is faster. The primary issue was highlighted by @Verbolten_Jason, which is that the debounce was being initialized within the function itself.
Because of this, every time the function runs, the debounce is immediately being set to false, which disregards the 5 second wait that was included at the end of the function as soon as the function is run again.
-- LocalScript code from original post
script.Parent.ConfirmRebirth.Activated:Connect(function() -- Function activated on button activation
local db = false -- Sets the debounce to false immediately
if not db then --[[ Because debounce was set to false within the function,
this condition will ALWAYS be met --]]
if Power.Value >= requiredAmount then
Remotes.Rebirth:FireServer(requiredAmount)
db = true -- Even though debounce is set back to true
task.wait(5) -- And then it waits 5 seconds
db = false --[[ Setting the debounce back to false here wouldn't do
anything for the next time the function is run because the debounce is
immediately set to false at the start of the function.
You can test this by adding print statements before the task.wait(5) and then
after the task.wait(5), and if you rapidly activate the function while
meeting the prior conditional statements, it'll print the first statements
right away and then the second statements would appear 5 seconds out from
the times that the function was run for each of the previous activations --]]
end
end
end)
Consequently, the solution that would help make sure that players could not repetitively fire the RemoteEvent is to initialize the debounce variable before the function starts so that its current value is not immediately overridden.
Example Revision
local debounce = false --[[ Sets the initial value of debounce to false before
the function starts to ensure that its current value is not overridden when
the player activates the button.
--]]
script.Parent.ConfirmRebirth.Activated:Connect(function()
if not debounce then -- Checking immediately if debounce is not true
debounce = true --[[ If so, then we set debounce to true so that if the
player decides to activate the button again, the first condition will not be
met until debounce has been set back to false after 5 seconds
at the end of the function.
--]]
if Power.Value >= requiredAmount then
Remotes.Rebirth:FireServer(requiredAmount)
end
task.wait(5) --[[ Separating this from the conditional statement above
ensures that it will always wait 5 seconds before setting debounce to false,
whether or not the player's Power.Value exceeded that of requiredAmount --]]
debounce = false
end
end)
However, I do agree that it is a good idea to add the debounce and the sanity checks to the serverside, too. Ideally, you have it on both sides:
It’s there on the client-side to provide immediate feedback (such as having an indicator appear to let the player know that they need to wait a certain amount of time before activating the button again if they try to press the button when debounce is still set to true)
It’s there on the server-side to ensure it’s not being abused by exploiters who have circumnavigated the cooldown and sanity checks on the client-side. If you (*the original poster of the thread) take anything away from this, it’s to make sure to always sanity check on the server side, because it’s not guaranteed that the client is telling the truth!!
And although that solves the primary issue that could enable players to get into the situation where they may accidentally cause their Wins / Power leaderstats to decrease into the negatives, one way to be 100% sure that the updated values cannot go below 0 would be to
Combined, those solutions prevent players from being able to activate the RemoteEvent too quickly and ensures that any edge cases where the server script could deduct their Wins / Powers below 0 won’t actually happen (but also make sure to check if they have reached the requiredAmount on the server before deducting from their Wins / Power).
And I want to clarify that @ShaShxa is correct with the idea that the client is faster than the server, because the inputs that the client makes would need to be communicated with the server, and then the changes that the server makes need to be communicated back to the client.
However, in this particular case, the issue described in the original post cannot be completely attributed to the sheer speed of the client, because:
The debounce was not set up correctly
There was nothing being done on the server-side to:
Verify that the player had enough Wins / Power
Ensure that the new values for the player’s Wins / Power would not go below 0.
Hope that I was able to provide some more insight into the suggested solutions and ideas during this thread If I missed anything or was mistaken about something I mentioned, please let me know!