waitUntil: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
No edit summary
m (Text replacement - "|= Game name" to "|Game name=")
(32 intermediate revisions by 12 users not shown)
Line 1: Line 1:
{{Command|= Comments
{{Command|Comments=
____________________________________________________________________________________________
____________________________________________________________________________________________


| arma |= Game name
| arma |Game name=


|1.00|= Game version
|1.00|Game version=
____________________________________________________________________________________________
____________________________________________________________________________________________


| Suspend execution of [[function]] or [[SQF_syntax|SQF]] based [[Script|script]] until condition is satisfied. |= Description
| Suspends execution of [[Scheduler | scheduled]] script until the given condition satisfied. This command will loop and call the code inside <tt>{}</tt> ''mostly'' every frame (depends on complexity of condition and overall engine load) until the [[Code|code]] returns [[true]]. The execution of the rest of the script therefore will be suspended until [[waitUntil]] completes. <br><br>
If the very first execution of the code returns [[true]] the command will exit immediately, therefore it will not produce any "Suspending not allowed in this context" error when used inside [[Scheduler#Unscheduled_Environment|non-scheduled]] script. For all other uses it must be executed in environment that allows [[Scheduler#Suspension|suspension]] ([[canSuspend]]), such as [[spawn]]ed or [[execVM]]ed code.
<br><br>
{{Important | '''Since Arma 3 v1.93.145618 returning anything other than [[true]] or [[false]] from condition will result in appropriate type error''' }}
<br>
Use [[getVariable]] with default value:<code>// bad
[[waitUntil]] { bank [[getVariable]] "money" > 0 };
// good
[[waitUntil]] { bank [[getVariable]] ["money", 0] > 0 };</code>
<code>// bad
[[waitUntil]] { isready };
// good
[[waitUntil]] { [[missionNamespace]] [[getVariable]] ["isready", [[false]]] };</code>
Always return [[Boolean]]:<code>// bad
[[waitUntil]] { [[if]] (![[alive]] [[player]]) [[exitWith]] {}; _time <nowiki>=</nowiki> _time + 1 };
// good
[[waitUntil]] { [[if]] (![[alive]] [[player]]) [[exitWith]] { [[true]] }; _time <nowiki>=</nowiki> _time + 1; [[false]] };</code><br>
 
{{Informative | For some unknown reason if you have [[waitUntil]] loop active and game is '''saved/loaded''', some variables in the expression may appear undefined for a short time. As a workaround, assign expression to a variable and make sure it is defined before [[waitUntil]] checks it:
[[waitUntil]]
{
  [[private]] _expression <nowiki>=</nowiki> var1 && (var2 > 10);
  ![[isNil]] "_expression" && { _expression }
};
}}
|DESCRIPTION=
 
____________________________________________________________________________________________
____________________________________________________________________________________________


| '''waitUntil''' condition |= Syntax
| '''waitUntil''' condition |SYNTAX=


|p1= condition: [[Code]] |= Parameter 1
|p1= condition: [[Code]] - the expression that <u>must evaluate to [[true]] or [[false]]</u>, [[true]] to finish waiting or [[false]] to continue waiting |PARAMETER1=


| [[Nothing]] |= Return value
| [[Anything]] - the value the condition evaluates to when the wait is over (normally [[true]]) |RETURNVALUE=
____________________________________________________________________________________________
____________________________________________________________________________________________
   
   
|x1= <code>'''waitUntil''' {not [[alive]] [[player]]}</code> |= Example 1
|x1= <code>[[waitUntil]] { [[not]] [[alive]] [[player]] };</code> |EXAMPLE1=
|x2= <code>_i <nowiki>=</nowiki> 0; '''waitUntil''' {_i <nowiki>=</nowiki> _i + 1; _i ><nowiki>=</nowiki> 100} </code> |=Example 2
 
|x2= <code>_i = 0; [[waitUntil]] { _i = _i + 1; _i >= 100 }; </code> |EXAMPLE2=
 
|x3= <code>[[waitUntil]] {[[sleep]] 0.1; [[not]] [[alive]] [[player]] };</code> |EXAMPLE3=
 
|x4= An on-the-fly custom ''[[Arma_3:_Event_Handlers|event handler]]'':
<code>_myEH = ["ZoomIn"] [[spawn]] {
    [[while]] { [[true]] } [[do]] {
        [[waitUntil]] {
            [[inputAction]] ([[_this]] [[select]] 0) == 1;
        };
        [[diag_log]] [[format]] ["%1 @ %2", [[_this]] [[select]] 0, [[diag_tickTime]]<nowiki>]</nowiki>;
    };
};</code>
Although perhaps better to use [[BIS_fnc_addStackedEventHandler|onEachFrame]], depending on the application. |EXAMPLE4=
____________________________________________________________________________________________
____________________________________________________________________________________________


| [[Control Structures]] |= See also
| [[sleep]], [[uiSleep]], [[canSuspend]], [[spawn]], [[execVM]], [[while]], [[Control Structures]]|SEEALSO=


}}
}}
Line 28: Line 68:
<dl class="command_description">
<dl class="command_description">
<!-- Note Section BEGIN -->
<!-- Note Section BEGIN -->
<dd class="notedate">Posted on December 20, 2006 - 19:55</dd>
 
<dt class="note">'''[[User:CrashDome|CrashDome]]'''</dt><dd class="note">waitUntil suspends both SQF functions and SQF scripts. In functions, the calling script is still in suspension due to waiting for a return from the [[call]] command. The game engine will continue, however. See [[Function]] for more detail.</dd>
<dd class="notedate">Posted on September 20, 2013
<dd class="notedate">Posted on April 2, 2010 - 17:10</dd>
<dt class="note">'''[[User:Killzone_Kid|Killzone_Kid]]'''
<dt class="note">'''[[User:Roehre|Roehre]]'''</dt><dd class="note">If WaitUntil uses an undefined [[call body]] code, WaitUntil won't release, even when this code is separated from other conditions through [[or]].</dd>
<dd class="note">In case you have more complex code inside [[waitUntil]] loop, to be on the safe side '''always''' return boolean at the end of the scope:
 
<code>[[player]] [[addEventHandler]] ["Fired", {
_null = (_this [[select]] 6) [[spawn]] {
_p = [0,0,0];
[[waitUntil]] {
if ([[isNull]] _this) [[exitWith]] {[[true]]};
_p = [[getPos]] _this;
[[false]] //<-- boolean at the end of the scope NOW REQUIRED
};
[[hint]] [[str]] _p;
};
}];</code>
 
<dd class="notedate">Posted on December 20, 2006 - 19:55
<dt class="note">'''[[User:CrashDome|CrashDome]]'''
<dd class="note">
waitUntil suspends both SQF functions and SQF scripts. In functions, the calling script is still in suspension due to waiting for a return from the [[call]] command. The game engine will continue, however. See [[Function]] for more detail.
 
 
<dd class="notedate">Posted on April 2, 2010 - 17:10
<dt class="note">'''[[User:Roehre|Roehre]]'''
<dd class="note">
Prior to Arma 3 v1.92.145618 if WaitUntil uses an undefined [[call]] code, WaitUntil won't release, even when this code is separated from other conditions through [[or]]. Be warned that this won't cause an error message.
 
 
<dd class="notedate">Posted on Jan 07, 2011
<dt class="note">'''[[User:kju|kju]]'''
<dd class="note">
By default the cycle time for the condition check is per frame. Look at the example 3, how to set it at a lower rate yourself.
Often times one does not need per frame checking. Saves a lot CPU checks; especially when the condition is complex to compute.
 
 
<!-- Note Section END -->
<!-- Note Section END -->
</dl>
</dl>
Line 40: Line 112:
[[Category:Scripting Commands ArmA|WAITUNTIL]]
[[Category:Scripting Commands ArmA|WAITUNTIL]]
[[Category:Scripting Commands ArmA2|{{uc:{{PAGENAME}}}}]]
[[Category:Scripting Commands ArmA2|{{uc:{{PAGENAME}}}}]]
[[Category:Scripting Commands VBS2|{{uc:{{PAGENAME}}}}]]
[[Category:Scripting Commands Arma 3|{{uc:{{PAGENAME}}}}]]
[[Category:Scripting_Commands_Take_On_Helicopters|{{uc:{{PAGENAME}}}}]]
 
<!-- CONTINUE Notes -->
<dl class="command_description">
<dd class="notedate">Posted on December 13, 2014 - 23:25 (UTC)</dd>
<dt class="note">[[User:Commy2|Commy2]]</dt>
<dd class="note">
If you want to use waitUntil together with exitWith, remember that the loop only exits if the code block returns true.<br>
<br>
It should look like this:
<code>
waitUntil {
  // exit loop if the unit gets deleted
  if (isNull _unit) exitWith {true};  // has to return true to continue
 
  !alive _unit;
};
</code>
 
</dd>
</dl>
<!-- DISCONTINUE Notes -->

Revision as of 13:30, 2 September 2019

-wrong parameter ("Arma") defined!-1.00
Hover & click on the images for description

Description

Description:
Suspends execution of scheduled script until the given condition satisfied. This command will loop and call the code inside {} mostly every frame (depends on complexity of condition and overall engine load) until the code returns true. The execution of the rest of the script therefore will be suspended until waitUntil completes.

If the very first execution of the code returns true the command will exit immediately, therefore it will not produce any "Suspending not allowed in this context" error when used inside non-scheduled script. For all other uses it must be executed in environment that allows suspension (canSuspend), such as spawned or execVMed code.

Since Arma 3 v1.93.145618 returning anything other than true or false from condition will result in appropriate type error


Use getVariable with default value:// bad waitUntil { bank getVariable "money" > 0 }; // good waitUntil { bank getVariable ["money", 0] > 0 }; // bad waitUntil { isready }; // good waitUntil { missionNamespace getVariable ["isready", false] }; Always return Boolean:// bad waitUntil { if (!alive player) exitWith {}; _time = _time + 1 }; // good waitUntil { if (!alive player) exitWith { true }; _time = _time + 1; false };

For some unknown reason if you have waitUntil loop active and game is saved/loaded, some variables in the expression may appear undefined for a short time. As a workaround, assign expression to a variable and make sure it is defined before waitUntil checks it:
waitUntil 
{
  private _expression = var1 && (var2 > 10);
  !isNil "_expression" && { _expression }
};
Groups:
Uncategorised

Syntax

Syntax:
waitUntil condition
Parameters:
condition: Code - the expression that must evaluate to true or false, true to finish waiting or false to continue waiting
Return Value:
Anything - the value the condition evaluates to when the wait is over (normally true)

Examples

Example 1:
waitUntil { not alive player };
Example 2:
_i = 0; waitUntil { _i = _i + 1; _i >= 100 };
Example 3:
waitUntil {sleep 0.1; not alive player };
Example 4:
An on-the-fly custom event handler: _myEH = ["ZoomIn"] spawn { while { true } do { waitUntil { inputAction (_this select 0) == 1; }; diag_log format ["%1 @ %2", _this select 0, diag_tickTime]; }; }; Although perhaps better to use onEachFrame, depending on the application.

Additional Information

See also:
sleepuiSleepcanSuspendspawnexecVMwhileControl Structures

Notes

Report bugs on the Feedback Tracker and/or discuss them on the Arma Discord or on the Forums.
Only post proven facts here! Add Note

Notes

Posted on September 20, 2013
Killzone_Kid
In case you have more complex code inside waitUntil loop, to be on the safe side always return boolean at the end of the scope: player addEventHandler ["Fired", { _null = (_this select 6) spawn { _p = [0,0,0]; waitUntil { if (isNull _this) exitWith {true}; _p = getPos _this; false //<-- boolean at the end of the scope NOW REQUIRED }; hint str _p; }; }];
Posted on December 20, 2006 - 19:55
CrashDome
waitUntil suspends both SQF functions and SQF scripts. In functions, the calling script is still in suspension due to waiting for a return from the call command. The game engine will continue, however. See Function for more detail.
Posted on April 2, 2010 - 17:10
Roehre
Prior to Arma 3 v1.92.145618 if WaitUntil uses an undefined call code, WaitUntil won't release, even when this code is separated from other conditions through or. Be warned that this won't cause an error message.
Posted on Jan 07, 2011
kju
By default the cycle time for the condition check is per frame. Look at the example 3, how to set it at a lower rate yourself. Often times one does not need per frame checking. Saves a lot CPU checks; especially when the condition is complex to compute.

Bottom Section

Posted on December 13, 2014 - 23:25 (UTC)
Commy2
If you want to use waitUntil together with exitWith, remember that the loop only exits if the code block returns true.

It should look like this: waitUntil { // exit loop if the unit gets deleted if (isNull _unit) exitWith {true}; // has to return true to continue !alive _unit; };