How do I break this loop?

Hi! I’m trying to make a script where when a player clicks this GUI button (buy), it will give them money automatically and then when they click the sell button, it stops the loop. I’ve tried playing around with it and so far I’m unable to get what I desired. Can anyone help me?

income.OnServerEvent:Connect(function(player, check) -- if check is false then it breaks the loop
		while wait() do
		local ducats = player.leaderstats.Ducats
			ducats.Value = ducats.Value + 1
			
			if check == false then
			 break
		end
	end
end)
1 Like

I’m not sure why you would put a loop inside an event.
Put the loop elsewhere, so you don’t have to break it.

2 Likes

What iGottic said. Also try using return instead of break maybe? Not sure, should restructure how your system works so you don’t need to do this.

2 Likes

Your loop won’t break if you first fire the event with a truthy value and then false. This happens because each event firing is in a different thread and are independent of each other. As suggested, look into re-structuring how you go about the behavior you want.

1 Like

Well, I was thinking perhaps I would have a BoolValue or something like that, and when the Remote Event is fired, it would fire a script to activate the loop, but I’m not sure how to direct that loop into the player’s leaderstat’s points

I get what you’re trying to do. But each event is fired with a new coroutine/thread (which means it’s basically duplicated so it doesnt effect your other code or yield it). This means you will start a new loop. But end it. Try having the loop out of the event. And somewhere in the script. From there make a variable in the script and when the event fires change that variable. And then the loop broken.

Can you elaborate more on this…?

The check runs after it gives the player the “Ducats”, and why are you checking for the “check” false when you can just set it to false through the Local Script you fired the event with and then not fire it?

A loop in an event is extremely inefficient. You should also use a repeat until loop here, since it’s basically the same thing. Keep giving the player a ducat until check is false.

repeat
    ducats.Value = ducats.Value - 1
until not check

The reason why the loop never breaks is because check is never false. Since it’s a parameter, it never changes. Think of IntValue.Changed for example. Its value parameter is the new value of the IntValue. value is just a number. It never changes because it’s the parameter of an event. Exactly the same as making a variable for the IntValue’s value.

local value = IntValue.Value
--this variable is a number, not the property

The solution to your code is to get rid of the loop, that’s inefficient. Just have an if statement for check, where if it isn’t false you give the player a ducat.

income.OnServerEvent:Connect(function(player, check)
    if check then
        player.leaderstats.Ducats.Value = player.leaderstats.Ducats.Value + 1
    end
end)
local CanLoop = true

game.ReplicatedStorage.Event.OnServerEvent:Connect(function(Player, CanLoopValue)
	CanLoop = CanLoop
end)

while true do
	-- // Loop stuff.
	
	if CanLoop then
		-- // Execute
	else
		break
	end
	
	wait()
end

What i’m doing here is making references to a variable outside of that current coroutine. Then the while true loop will react differently when the CanLoop variable changes.

This is only an example of how to stop it. But you can’t create a new loop inside of an event as each event is unique and doesn’t reference to a past event.

I also thought of this:


game.ReplicatedStorage.Event.OnServerEvent:Connect(function(Player, CanLoopValue)
	if CanLoopValue then
		local Index = #Looped + 1
		Looped[Index] = CanLoopValue
		
		while true do
			if Looped[Index] then
				-- // Code
			else
				break
			end 
		end
	else
		for Index = 1, #Looped do
			Looped[Index] = false
		end
	end
end)```

what you did is kinda dumb because
an event doesn’t yield

that means if you do

income:FireServer(true) -- the loop will be on
income:FireServer(false) -- the loop will stop just when you will call the remote, but not stop the other one

kinda hard to explain but i hope you will get it
fix (tested!) :

local players = {}

income.OnServerEvent:Connect(function(player, check)
	if not players[player.UserId] then
		if check then
			players[player.UserId] = check
			while wait() do
				local ducats = player.leaderstats.Ducats
				ducats.Value = ducats.Value + 1
				if not players[player.UserId] then
					players[player.UserId] = nil
					break
				end
			end
		end
	else
		players[player.UserId] = check
	end
end)
2 Likes

Thank you! It works and I fully understand the mistake occured, haha.

Not sure what the game is about also, but I would really suggest against giving the client this much control unchecked.

If I were an exploiter, I could fire this event whenever I want and get free “ducats”.

Ahahaha, it’s a basic supply and demand ‘simulator’ and I made it that if the calculations are dependent on another value (the ducats value will be multiplied by another value that determines a ‘town’s’ twice prosperity rate (X) which could be a negative value, while at the same time deducted with rental fees (300 ducats worth) so in the end it concludes to Ducats.Value - 300 + (2X). So, if you run the event without knowing the background of the event, you’d end up making a huge loss if the server was having a bad time.

Thanks for the concern though, I’ll be more aware about this and may do something about it!