Today BIS added new command triggerTimeoutCurrent that allows you to check the current remaining time of a trigger timeout. This made me look into trigger timeouts, something I haven’t done in previous trigger blog post. So as you have guessed already, today I will focus on timeouts.

When trigger is activated you can delay the onActivationStatement  execution simply by setting trigger timeout with setTriggerTimeout command. Once set countdown is over, the statement will run. This made me think about setTimeout command in JavaScript. In JavaScript you can pass a function to this command together with required delay, which in turn sets a timer and delays function execution. Can the same be done in SQF? You betcha!

All we need is to set a trigger with desired timeout to be triggered immediately upon creation.  For this it is enough to just set conditionStatement of the trigger to true to make the trigger think it was triggered (triggerActivated though will return true only when onActivationStatement is executed). After we are done with the countdown, we will delete the trigger. So here is a bunch of code for you to explore and play with.

  • Function to create and return timeout object:
KK_fnc_setTimeout = { private "_tr"; _tr = createTrigger [ "EmptyDetector", [0,0,0] ]; _tr setTriggerTimeout [ _this select 2, _this select 2, _this select 2, false ]; _tr setTriggerStatements [ "true", format [ "deleteVehicle thisTrigger; %2 call %1", _this select 0, _this select 1 ], "" ]; _tr };
  • Function to return number of seconds left:
KK_fnc_currentTimeout = { if (isNull _this) exitWith {0}; if (triggerTimeoutCurrent _this < 0) exitWith { (triggerTimeout _this) select 0 }; triggerTimeoutCurrent _this };
  • Function to stop timeout in progress (returns true on success):
KK_fnc_clearTimeout = { if (isNull _this) exitWith {false}; deleteVehicle _this; true };
  • Some sample function to call:
fnc_hello = {hint "hello"};
  • Activate 10 seconds timeout:
_timeout = [fnc_hello, [], 10] call KK_fnc_setTimeout;
  • Query remaining time
_remaining = _timeout call KK_fnc_currentTimeout;
  • Check if timeout is still active
_active = !isNull _timeout;
  • Stop timeout
_success = _timeout call KK_fnc_clearTimeout;

Pretty much all you need to create and manage timeouts. This way you can also easily create multiple timeouts since each timeout is a separate trigger object. But what if we want a repeated timeout? In JavaScript such command is called setInterval. Instead of repeatedly creating and deleting the trigger, we are going to create one trigger and keep on activating and deactivating it instead. Look at the code below to see how it is done in case you need to deactivate a trigger with a script in your projects.

  • Function to create and return interval object:
KK_fnc_setInterval = { private "_tr"; _tr = createTrigger [ "EmptyDetector", [0,0,0] ]; _tr setTriggerTimeout [ _this select 2, _this select 2, _this select 2, false ]; _tr setTriggerStatements [ "thisTrigger getVariable ['act', true]", format [ "thisTrigger setVariable ['act', false]; %2 call %1", _this select 0, _this select 1 ], "thisTrigger setVariable ['act', true]" ]; _tr };
  • Some example of setting an interval:
fnc_time = {player sidechat str time}; myInterval = [fnc_time, [], 3] call KK_fnc_setInterval;

Now, the triggers are imprecise in nature. If you want precise intervals use while loops and time check. A trigger will check its timeout once every 0.5 seconds. Because of this there always be up to extra 0 – 0.5 seconds inaccuracy on each timeout, not to mention that when trigger is created it takes up to 0.5 seconds before it even goes live. So if you are setting an interval to let’s say 3 seconds, this literally means: “check interval NOT more than ABOUT once every 3 seconds“. For default 0.5 seconds check you can pass 0 as timeout param.

This inaccuracy could be somewhat negligible at bigger intervals. 0.5 second in 60 seconds interval for example is nothing. So if you need every minute check, it is probably better to create a trigger with 60 seconds timeout than while true loop with sleep 60. Oh and you can remove and query intervals with KK_fnc_clearTimeout and KK_fnc_currentTimeout respectively. Just remember that trigger statements are local, if you want absolute network sync, run timeouts on the server only and broadcast the changes.

Above is a simple countdown I made to demonstrate the new triggerTimeoutCurrent command. But, but, but the triggers are imprecise? Well, while trigger checks on its own timeout every 0.5 seconds there is no reason for us to do the same. We can check the timeout every frame for a better accuracy, thanks to the new command. Here is the code from the video:

_tr1 = createTrigger ["EmptyDetector", [0,0,0]]; _tr1 setTriggerTimeout [10, 10, 10, false]; _tr1 setTriggerStatements [ "true", "deleteVehicle thisTrigger", "" ]; 0 = _tr1 spawn { waitUntil {triggerTimeoutCurrent _this > 0}; waitUntil { if (floor triggerTimeoutCurrent _this <= 0) exitWith {true}; hintSilent parseText format [ "<t size='10' color='#ff0000' shadow='2'>%1</t>", floor triggerTimeoutCurrent _this ]; false }; hint ""; "HelicopterExploSmall" createVehicle position player; };


EDIT: Removed redundant code and made neater. Also please note BIS made some changes to trigger functionality since this post, so the code on video now counts down from 9 not 10.

Triggers V3