Loop inside remote event function doesn't stop even when the boolean is false

You can write your topic however you want, but you need to answer these questions:

  1. What do you want to achieve? Keep it simple and clear!

I have this code for a fire hose in my fire fighting game, and I want it to stop working when a certain “holding” boolean is false.

  1. What is the issue? Include screenshots / videos if possible!

The issue is that it won’t break when holding is false, but will when the table.find(QueryHitbox, Parts) is false (see below)

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

I actually have solved something similar in the past with a while loop, heres the code for it:

local holding: boolean
local rs = game:GetService("ReplicatedStorage")

rs.RemoteEvents.ToolEvents.ReduceWaterLevel.OnServerEvent:Connect(function(Player, Enabled: boolean)
	holding = Enabled
	local Character = Player.Character or Player.CharacterAdded:Wait()
	local WaterLevel: IntValue = Character:FindFirstChild("WaterLevel")
	
	
	if holding and WaterLevel.Value > 0 then
		while holding do
			WaterLevel.Value -= 1
			task.wait(0.8)
			if not holding or WaterLevel.Value == 0 then
				rs.RemoteEvents.ToolEvents.ReduceWaterLevel:FireClient(Player)
				break
			end
		end
	end
end)

This script handles the water level GUI for the fire hose, and similarly is deactivated once “holding” is false. However this actually does work, which is why I’m confused why the fire hose script doesn’t.

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Fire hose script (focus on the for loop part)

local rs = game:GetService("ReplicatedStorage")

rs.RemoteEvents.ToolEvents.FireHoseExtinguish.OnServerEvent:Connect(function(Player, Parts, Hitbox, QueryHitbox, processing, hold, PartsIndex)
	
	local holding = hold
	
	local debounce = false
	if holding then
		if Parts:FindFirstChild("FireEmitter") then
			local ExtinguishTime: IntValue = Parts.Time
			local FireEmitter: ParticleEmitter = Parts.FireEmitter
			local SmokeEmitter: ParticleEmitter = Parts.SmokeEmitter
			local ExtinguishSound: Sound = Parts.Extinguish
			local FireSound: Sound = Parts.FireSound
			local FireLight: PointLight = Parts.PointLight
			local DamageScript: Script = Parts.DealDamage
			local SpreadScript: Script = Parts.FireSpread

			for i = 0, 1, 0.1 do
				if holding == false or not table.find(QueryHitbox, Parts) then
					processing = false
					rs.RemoteEvents.ToolEvents.FireHoseExtinguish:FireClient(Player, processing)
					break
				end

				debounce = false
				processing = true
				rs.RemoteEvents.ToolEvents.FireHoseExtinguish:FireClient(Player, processing)

				QueryHitbox = workspace:GetPartBoundsInBox(Hitbox.CFrame, Hitbox.Size)
				FireEmitter.Transparency = NumberSequence.new(i)
				if FireEmitter.Transparency == NumberSequence.new(1) then
					if not debounce then
						DamageScript.Enabled = false
						SpreadScript.Enabled = false
						FireEmitter:Destroy()
						SmokeEmitter:Destroy()
						FireSound:Destroy()
						ExtinguishSound:Play()
						FireLight.Enabled = false
						debounce = true
					end
					processing = false
					rs.RemoteEvents.ToolEvents.FireHoseExtinguish:FireClient(Player, processing)
				end
				task.wait(ExtinguishTime.Value)
				print(holding, "Loop")
			end
		end
	end
end)
1 Like

The issue is most likely happening because the function that’s connected to an event is fired in a new thread each time the event is fired, so to fix this issue, you’ll need to run the loop within a thread, and cancel the thread when you wish to stop it:

local rs = game:GetService("ReplicatedStorage")

local thread

local function decreaseWaterLevel(WaterLevel: IntValue, Player)
	while true do
		WaterLevel.Value -= 1
		task.wait(0.8)

		if WaterLevel.Value == 0 then
			rs.RemoteEvents.ToolEvents.ReduceWaterLevel:FireClient(Player)
			break
		end
	end
end

rs.RemoteEvents.ToolEvents.ReduceWaterLevel.OnServerEvent:Connect(function(Player, Enabled: boolean)
	local Character = Player.Character or Player.CharacterAdded:Wait()
	local WaterLevel: IntValue = Character:FindFirstChild("WaterLevel")


	if Enabled and WaterLevel.Value > 0 then
		thread = task.spawn(decreaseWaterLevel, WaterLevel, Player)
	else
		if thread then task.cancel(thread) end
	end
end)

Thank you for this, but I actually found a simpler solution by simply adding an “IsHolding” BoolValue to the Character via a serverscript, then changing it’s value everytime the tool is activated.

Then, in the for loop, I just have to do “holding = IsHolding.Value” to keep checking the holding value.

New hose script:

local rs = game:GetService("ReplicatedStorage")

rs.RemoteEvents.ToolEvents.FireHoseExtinguish.OnServerEvent:Connect(function(Player, Parts, Hitbox, QueryHitbox, processing, hold, PartsIndex)
	local Character = Player.Character
	
	local IsHolding = Character:WaitForChild("IsHolding")
	local holding = IsHolding.Value
	
	local debounce = false
	if holding then
		if Parts:FindFirstChild("FireEmitter") then
			local ExtinguishTime: IntValue = Parts.Time
			local FireEmitter: ParticleEmitter = Parts.FireEmitter
			local SmokeEmitter: ParticleEmitter = Parts.SmokeEmitter
			local ExtinguishSound: Sound = Parts.Extinguish
			local FireSound: Sound = Parts.FireSound
			local FireLight: PointLight = Parts.PointLight
			local DamageScript: Script = Parts.DealDamage
			local SpreadScript: Script = Parts.FireSpread

			for i = 0, 1, 0.1 do
				holding = IsHolding.Value
				if holding == false or not table.find(QueryHitbox, Parts) then
					processing = false
					rs.RemoteEvents.ToolEvents.FireHoseExtinguish:FireClient(Player, processing)
					break
				end

				debounce = false
				processing = true
				rs.RemoteEvents.ToolEvents.FireHoseExtinguish:FireClient(Player, processing)

				QueryHitbox = workspace:GetPartBoundsInBox(Hitbox.CFrame, Hitbox.Size)
				FireEmitter.Transparency = NumberSequence.new(i)
				if FireEmitter.Transparency == NumberSequence.new(1) then
					if not debounce then
						DamageScript.Enabled = false
						SpreadScript.Enabled = false
						FireEmitter:Destroy()
						SmokeEmitter:Destroy()
						FireSound:Destroy()
						ExtinguishSound:Play()
						FireLight.Enabled = false
						debounce = true
					end
					processing = false
					rs.RemoteEvents.ToolEvents.FireHoseExtinguish:FireClient(Player, processing)
				end
				task.wait(ExtinguishTime.Value)
				print(holding, "Loop")
			end
		end
	end
end)

I hope this can help anyone who has similar problems. Thank you for trying to help me though

1 Like