-
Notifications
You must be signed in to change notification settings - Fork 0
Control Flow
ffredyk edited this page Jul 23, 2026
·
1 revision
SQ# provides standard control flow constructs. Unlike SQF, then is optional after if.
// Basic if
if (_hp <= 0) {
handleDeath();
};
// if-else
if (_alive) {
attack();
} else {
retreat();
};
// if-else if-else chain
if (_score > 100) {
rank = "A";
} else {
if (_score > 50) {
rank = "B";
} else {
rank = "C";
};
};
// then is optional (both work)
if (_cond) then { action(); };
if (_cond) { action(); };
// Ternary-like (returns value)
_result = if (_cond) then { "yes" } else { "no" };// Basic while loop
_i = 0;
while { _i < 10 } do {
print f"Index: {_i}";
_i = _i + 1;
};
// Infinite loop with exit
while { true } do {
if (_done) exitWith {};
sleep 0.1;
};
// Condition re-evaluated each iteration
while { count _queue > 0 } do {
processItem(_queue deleteAt 0);
};The condition must be wrapped in {} — it's a code block that is re-evaluated every iteration.
// for-from-to
for "_i" from 0 to 9 do {
print f"Index: {_i}";
};
// for-from-to-step
for "_i" from 0 to 100 step 10 do {
print f"Step: {_i}"; // 0, 10, 20, ..., 100
};
// Reverse (step negative)
for "_i" from 10 to 0 step -1 do {
print f"Countdown: {_i}";
};
// Iterate array
for "_i" from 0 to (count _arr - 1) do {
_elem = _arr select _i;
process(_elem);
};Iterate array elements. Magic variables inside the block:
-
_x— current element -
_forEachIndex— zero-based index -
_this—[element, index, array](SQF compat)
[1, 2, 3] forEach {
print f"Element {_forEachIndex}: {_x}";
};
// Early exit with exitWith
_arr forEach {
if (_x == "target") exitWith {
print "Found!";
};
};switch (_state) do {
case "idle": {
playIdle();
};
case "patrol": {
startPatrol();
};
case "combat": {
engage();
};
default {
print "Unknown state";
};
};
// Multiple cases
switch (_key) do {
case "w";
case "W": {
moveForward();
};
case "s";
case "S": {
moveBackward();
};
};Exits the current scope (loop or code block):
// Exit loop
while { true } do {
_item = getNext();
if (isNil "_item") exitWith {};
process(_item);
};
// Exit forEach
_arr forEach {
if (_x == target) exitWith {
_found = _x;
};
};Structured error handling:
try {
if (_hp <= 0) then { throw "Unit is dead"; };
doWork();
} catch {
print f"Error: {_exception}";
};
// _exception contains the thrown value
// It is an SqError with: .message, .file, .line, .colReturns a value from a function/code block:
_calc = {
params ["_a", "_b"];
if (_b == 0) exitWith { return 0; }; // early return
_a / _b
};
_result = [10, 2] call _calc; // 5sleep, await, and suspending commands only work in scheduled code (spawned fibers):
// Check if suspension is allowed:
if (canSuspend nil) then {
sleep 1; // OK — in spawned code
};
// call-executed code CANNOT suspend:
call {
sleep 1; // ERROR!
};| Context | canSuspend | sleep/await |
|---|---|---|
spawn { ... } |
true | ✅ |
execVM "file.sqf" |
true | ✅ |
call { ... } from spawned |
true | ✅ |
call { ... } from unscheduled |
false | ❌ |
callUnscheduled { ... } |
false | ❌ |
- Functions & Code — call/spawn/execVM/compile
- Language Guide — syntax and operators
- throw — throw errors
- try/catch — error handling construct
- canSuspend — check suspension context
- sleep — fiber suspension
- Getting Started
- Language Guide
- Type System
- Control Flow
- Functions & Code
- Strings & Text
- Arrays & Collections
- Concurrency
- Promise System
- Thread Safety
- Host API & Embedding
- CLI Tool
- Bytecode Reference
- Multiplayer
- Syntax Sugar
- Optimization Guide
- Benchmarks
- count
- select
- pushBack
- append
- deleteAt
- deleteRange
- resize
- reverse
- sort
- find
- in
- forEach
- freeze
- thaw
- isFrozen
- currentScheduler
- clientOwner
- allSchedulers
- schedulerName
- schedulerExists
- schedulerBudget
- setSchedulerBudget
- fiberCount
- readyFiberCount
- waitingFiberCount
- schedulerLoad
- sendTo