Loop is a piece of code that repeats over and over. There will be times when you need to do this and there are few ways you can do it. I give you an example. Lets say you need to add 3 identical items into inventory. You can just go add item, add item, add item 3 times. But what if you need it 20 times, what better than making the same code run in a loop 20 times? Quick and neat.

The for loops. These loops allow to execute a portion of code {} set amount of times. The syntax allows you to set up the counter in 2 ways. Although similar, there is however a difference in performance depending on which syntax you choose. I’ve made both loops perform 100000 iterations and one loop finished 2.5 times faster.

for "_i" from 5 to 93 step 7 do {hint str _i}; //hint is 96

This is the faster loop. This syntax reads like this: Create private variable _i then assign 5 to it, check if it is now equal or more than 93, if yes quit the loop, if not hint _i value then add 7 to it, check if it is now equal or more than 93,  if yes quit the loop, if not hint _i value then add 7 to it… and so forth until the condition is met and it quits. If you omit step it will increment _i by 1 by default. Notice how the result overshot the “to” limit of 93 we set. It is because the check condition in this syntax is if _i >= 93 then quit. Also the to value is checked only once at the beginning of the loop so you can use for example ceil (random 10) to generate random number of iterations, it will only be compiled once. Another peculiar feature of this construct is that _i has private scope within the loop, meaning that if there is var _i that exists elsewhere outside this loop, it will not be affected by changes in our _i. You can make infinite loop by setting step at 0.

for "_i" from 0 to 1 step 0 do {}; //will run infinitely

If you’ve done some coding in other languages you might be more comfortable with an alternative syntax for the for loop. This is the slower loop.

for [{_i=5},{_i<=93},{_i=_i+7}] do {hint str _i}; //hint is 89

This syntax reads like this: Assign 5 to variable _i, check if it is less than or equal to 93, if not quit the loop, if yes hint _i value then add 7 to it, check if it is less than or equal to 93, if not quit the loop, if yes hint _i value then add 7 to it…  and so forth until the condition is not true any more and it quits. Contrary to the 1st example, _i is never more than set limit. This is because the check condition for it is while _i <= 93 do repeat. Also _i is not private unless you explicitly make it private.

_i = 101; for [{private "_i"; _i=5},{_i<=93},{_i=_i+7}] do {}; hint str _i; //hint is 101

Unlike the first for loop, this loop checks condition of its completion every single iteration, this is why it is slower I guess. You can dynamically alter the number of iteration it performs.

k = 3; a = {k = k + 0.5; k}; for [{_i=0},{_i<(call a)},{_i=_i+1}] do { diag_log format ["_i:%1/k:%2", _i, k]; }; //.rpt file //"_i:0/k:3.5" //"_i:1/k:4" //"_i:2/k:4.5" //"_i:3/k:5" //"_i:4/k:5.5" //"_i:5/k:6" //"_i:6/k:6.5"

This loop can also be made infinite intentionally or by mistake. All you need to do is make check condition produce true all the time.

for [{_i=0},{true},{_i=_i+1}] do {}; //will run infinitely

You might say, wait, why all this hassle? You can just make a while true loop and be done with it. Well not really or at least not all the time. Lets have a look at while loops.

_i=5; while {_i<=93} do {hint str _i; _i=_i+7}; //hint is 89 _i=5; while {_i<=93} do {_i=_i+7}; hint str _i; //hint is 96

As you can see we can achieve either of the for loops result with while loop. However it is also very easy to create a runaway train by mistake. This is why there is a limit set in place for while loops by the engine. The while loop that is called will run for a maximum of 10000 iterations then it will quit. Put the following in init field of a unit in editor and hit preview.

i=0; while {true} do {i=i+1}; hint str i; //hint is 10000

The limit is set in place for when the script is called by the engine and it has to wait for call to return before it can do other things. This happens when you call the infinite while loop from either event handler, FSM script or init line. If your script is executed using spawn or execVM, you can make while loop run forever. Also the aforementioned examples of infinite for loop construct is entirely free of this limitation. By the way init.sqf file is not called so the while true loop in it will run forever. To summarize…

spawn {while {true} do {}} //infinite always call {while {true} do {}} //10000 if called from FSM / event handler / init field call {while {true} do {}} //infinite if called from init.sqf / execVMed script spawn {call {while {true} do {}}} //infinite always

Many people use while true loops to check on things and it is especially popular when people share their code since it is the easiest way to hook up a bunch of code on top of existing code. This is pretty bad practice and you don’t really want millions of loops clogging your CPU degrading performance. Instead learn about event handlers. There are many event handlers of all kinds in ArmA, which will fire your code when event condition is met.

Let’s say you want to know when player gets in or out of a vehicle. You can do it with while true loop like a beginner or use GetIn and GetOut event handlers like a pro.

//good _veh addEventHandler ["GetIn",{_this call isIn}]; _veh addEventHandler ["GetOut",{_this call isOut}]; //not very good lastVehicle = objNull; lastSeat = ""; null = [] spawn { private ["_veh","_roles","_seat"]; while {true} do { _veh = vehicle player; if (_veh != player) then { _roles = assignedVehicleRole player; _seat = if (count _roles > 0) then [{_roles select 0},{""}]; if (_veh != lastVehicle || _seat != lastSeat) then { lastVehicle = _veh; lastSeat = _seat; [_veh, _seat, player] call isIn; }; } else { if (!isNull lastVehicle) then { [lastVehicle, lastSeat, player] call isOut; }; }; sleep 0.1; }; };

If you want a better response time in while example you will need to reduce sleep value, which will lead to more repetitions, more wasted CPU power. With event handler it will trigger your script ASAP every time.

Next Page …

Pages: 1 2