Trouble writing a reliable loop that ends on boolean change

Hello everyone. In general terms, I want to create a loop that ends on a boolean change. In my game’s situation, I’ve scripted a button that gives you a boolean and sets it to true. Then, a while loop gives you a reward every minute. When you press the button again, it sets the boolean to false, and logically that should stop the loop. Unfortunately, that’s not how it works and due to the long cooldown multiple loops run on one another when a player spams the button. The effect of this is having a constant flow of rewards until the player decides to stop. Due to this, in past projects that had these types of situations, I’ve put short wait periods with cooldowns after switching boolean values. This is obviously not efficient and slightly disrupts gameplay. I’ve been unable to find the right words for a solution apparently, so I’m making my own post. I’ll provide my scripts in the hopes I can clarify any confusion.

–server script (handles giving rewards)

local event = game.ServerStorage:WaitForChild("premEngage")
local module = require(game.ServerScriptService.rewardsModule)

event.Event:Connect(function(player1)
	--i've stopped here to get help from devforum so here's some sample code
	local inCage = player1:FindFirstChild("Stats"):FindFirstChild("InCage")
	
	while inCage.Value == true do
		wait(module.premiumRewards.cooldown)
		--code for running reward loop
	end
end)

–local script (handles disabling player gui and sending an event to a script that checks for premium (in case of exploiters trying to fire the remote event) and after verifying that the remote is genuine it sends a regular event to the server script above. I don’t think the verifying script is necessary, however I will provide it if asked.

local remote = game.ReplicatedStorage:WaitForChild("premCageEvent")
local unRemote = game.ReplicatedStorage:WaitForChild("premUnengage")
local player = game.Players.LocalPlayer


remote.OnClientEvent:Connect(function()
	local gui = player.PlayerGui
	local children = gui:GetChildren()
	for i,v in pairs(children) do
		v.Enabled = false
	end
	gui.premiumGui.Enabled = true
	gui.premiumGui.Frame.Visible = true
end)



local button = player.PlayerGui.premiumGui.Frame.TextButton

button.MouseButton1Up:Connect(function()
	unRemote:FireServer(player)
	local gui1 = player.PlayerGui
	local children1 = gui1:GetChildren()
	for i,v in pairs(children1) do
		v.Enabled = true
	end
	gui1.premiumGui.Enabled = false
	gui1.premiumGui.Frame.Visible = false
end)


player.CharacterAdded:Connect(function()
	unRemote:FireServer(player)
	local gui2 = player.PlayerGui
	local children2 = gui2:GetChildren()
	for i,v in pairs(children2) do
		v.Enabled = true
	end
	gui2.premiumGui.Enabled = false
	gui2.premiumGui.Frame.Visible = false
end)

–the “unremote” remote event was originally planned to stop the while loop by disabling the boolean on the server. If that’s a possible way, please tell me!

If whoever is reading this is unable to help me but see flaws in my code, please don’t hesitate to tell me! I’m relatively new to scripting and I’d love to hear feedback from you all.

Thanks!
~sick

1 Like

What about, making the Client to run the loop, with a wait(10). Then client fires a remote within that loop, servers gets the signal and checks a timestamp for that player stored into the module, if 60 seconds has passed, then give the prize to player.

Personally wouldnt like the server to run multiple loops for each players, I would give that task to the client. The client should ask the server, and server only checks if the previous timestamp and the current timestamp is enough long (60 seconds) to give the prize or not.

If the loop should only start and run after a player clicked the button, then adding a server debounce, once player clicks the button, the module table, has the timestamp and if the loop is running, but, even a exploiter tries to run the loop many times, server knows the timestamp and knows that only one loop should be running, easy to catch a exploiter that is trying to run more loops to get more prizes

1 Like

That makes sense! I will attempt to test something like this.

If it goes as planned, I will mark you as solution. Thanks you!

1 Like

Alrighty. With your help and a little thinking outside the box, I got it to work, even when i ran the remote 10 times, it still only gave me it every minute.

this was the only thing I had trouble with, however I made a folder in server storage that saved the time()'s output with one value and another string value it to the player. Then, when the remote was called, it would bring up the current time(). If the current time() subtracted by the player’s stored time was 60 or above, it will give the reward, then set the player’s time value in the folder to the current time(). I know theres some flaws in how i explained it but it works 100%, so thank you!

1 Like

Awesome to hear, Im not used to store values in folders, I like tables in modules, but both ways works great! Im glad I did help a little :3

1 Like

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