[HELP] toggle (true/false) with TriggerClientEvent

Hi guys, I’m trying to start a timer only if “toggle” is set to true via TriggerClientEvent("gnc_motels:toggleTimer", true), but it seems that the timer doesn’t want to stop if toggle is set to “falseTriggerClientEvent("gnc_motels:toggleTimer", false)

Code example:

Client side:

RegisterNetEvent("gnc_motels:toggleTimer")
AddEventHandler("gnc_motels:toggleTimer", function (toggle)
	local id = GetPlayerServerId(PlayerId())
    time = 10
	Citizen.CreateThread(function()
		Citizen.Wait(2000)
		while time ~= 0 and toggle do
			Citizen.Wait(1000)
			time = time - 1
			print(time)
		end
		time = 10
		TriggerServerEvent("gnc_motels:payKey", id)
	end)
end)

Server side:

RegisterCommand('stopTimer', function(source, args, RawCommand)
    TriggerClientEvent("gnc_motels:toggleTimer", source, false)
end)

RegisterCommand('startTimer', function(source, args, RawCommand)
    TriggerClientEvent("gnc_motels:toggleTimer", source, true)
end)

Basically I would like the timer to stop after executing the “stopTimer” command or vice versa, thanks everyone in advance for the help :heart:

This is an easy fix.
Let me explain so you can hopefully avoid this issue in the future. :slightly_smiling_face:

toggle” is locally scoped to the client event “gnc_motels:toggleTimer”. It’s a parameter that is received by the event, and used in the event handler function. Parameters are locally scoped.

If you aren’t aware, the “scope” is the area something exists and can be accessed. In this case, just within that instance of the function. Unless you take a parameter and assign it to a variable OUTSIDE the scope of the function, it doesn’t exist anywhere else. It also doesn’t exist inside the same function if called again. Only for the time it was called. Each time you call it, a NEW version of “toggle” is created, so having a different value can’t change the value from a previous call.

The issue you are having is, you are calling the event handler function a second time, expecting it to change the previous value of toggle. But it’s a new instance of toggle. How do we avoid this? Easy! Assign “toggle” to a variable outside the scope of the function. And in this case, instead of checking that “toggle” is true in the loop, check the new variable, after we assign the new value.

local timerEnabled = false

RegisterNetEvent("gnc_motels:toggleTimer")
AddEventHandler("gnc_motels:toggleTimer", function(toggle)
	local id = GetPlayerServerId(PlayerId())
	timerEnabled = toggle
	time = 10
	Citizen.CreateThread(function()
		Citizen.Wait(2000)
		while time ~= 0 and timerEnabled do
			Citizen.Wait(1000)
			time = time - 1
			print(time)
		end
		time = 10
		TriggerServerEvent("gnc_motels:payKey", id)
	end)
end)

What you can also do is check if the loop is already running, to avoid it running twice. Not sure if you need this, but if so, here you go. I also removed the “Citizen.” prefixes because they aren’t needed and I removed the “AddEventHandler” because you can put it’s event in RegisterNetEvent. It’s an old practice of separating them and this looks much neater but runs the same.

local timerEnabled = false

RegisterNetEvent("gnc_motels:toggleTimer", function(toggle)
	local id = GetPlayerServerId(PlayerId())
	timerEnabled = toggle
	if toggle and not timerEnabled then
		time = 10
		CreateThread(function()
			Wait(2000)
			while time ~= 0 and timerEnabled do
				Wait(1000)
				time = time - 1
				print(time)
			end
			time = 10
			TriggerServerEvent("gnc_motels:payKey", id)
		end)
	end
end)

If this helped you, please mark it as a solution so others can learn about scoping too! :spades:

2 Likes

Thank you for this explanation and for your time, I really appreciate the effort you took to respond to my post, thank you again. :heart: