SQF Syntax: Difference between revisions
Lou Montana (talk | contribs) m (Text replacement - "{{HashLink" to "{{Link") |
Lou Montana (talk | contribs) m (Fix example) |
||
(4 intermediate revisions by the same user not shown) | |||
Line 4: | Line 4: | ||
<small> | <small> | ||
* "Status Quo" was a code name for {{ | * "Status Quo" was a code name for {{Link|https://en.wikipedia.org/wiki/Operation_Flashpoint|Operation Flashpoint}} | ||
* "Combined Arms" was a code name for {{ | * "Combined Arms" was a code name for {{Link|https://en.wikipedia.org/wiki/ARMA_(series)|{{arma}}}} | ||
* "Futura" was a code name for {{ | * "Futura" was a code name for {{Link|https://en.wikipedia.org/wiki/ARMA_3|{{arma3}}}}. | ||
</small> | </small> | ||
Line 13: | Line 13: | ||
In fact: there are barely any actual language structures at all. | In fact: there are barely any actual language structures at all. | ||
The functionality is provided via so called ''[[:Category: | The functionality is provided via so called ''[[:Category:Arma 3: Scripting Commands|operators]]'' (or more commonly known [[:Category:Arma 3: Scripting Commands|scripting commands]]). | ||
Those [[:Category:Scripting Commands Arma 3|operators]] are one of the following types: [[#Nular Operators|Nular]]{{sic}}, [[#Unary Operators|Unary]], or [[#Binary Operators|Binary]]. | Those [[:Category:Scripting Commands Arma 3|operators]] are one of the following types: [[#Nular Operators|Nular]]{{sic}}, [[#Unary Operators|Unary]], or [[#Binary Operators|Binary]]. | ||
Line 73: | Line 73: | ||
<sqf>1 + /* some random comment in an expression */ 1</sqf> | <sqf>1 + /* some random comment in an expression */ 1</sqf> | ||
It should be mentioned that there is a [[comment]] unary [[:Category: | It should be mentioned that there is a [[comment]] unary [[:Category:Arma 3: Scripting Commands|operator]] that should not be used as it will actually be executed (thus taking time to execute) but does nothing besides consuming a [[String|string]]. | ||
There is no benefit in using it and the reason it exists is solely for backward compatibility. | There is no benefit in using it and the reason it exists is solely for backward compatibility. | ||
Another way to make a ''comment'' that way, is to just place a [[String|string]]: <sqf inline>/* some code */ | Another way to make a ''comment'' that way, is to just place a [[String|string]]: <sqf inline>/* some code */ "I can be considered as a comment but should not be used"; /* some other code */</sqf> | ||
''Comments are removed during the [[PreProcessor_Commands|preprocessing]] phase.'' This is important to know as that prevents usage in e.g a [[String|string]] that gets compiled using the [[compile]] unary [[:Category:Scripting Commands|operator]] or when only using [[loadFile]]. | ''Comments are removed during the [[PreProcessor_Commands|preprocessing]] phase.'' This is important to know as that prevents usage in e.g a [[String|string]] that gets compiled using the [[compile]] unary [[:Category:Scripting Commands|operator]] or when only using [[loadFile]]. | ||
Line 82: | Line 82: | ||
== Nular Operators == | == Nular Operators == | ||
A {{sic|nular}} operator is more or less a computed [[Variables|variable]]. Each time accessed, it will return the current state of something. | A {{sic|nular|nullar}} operator is more or less a computed [[Variables|variable]]. Each time accessed, it will return the current state of something. | ||
It is tempting to think of a nular{{sic}} [[:Category: | It is tempting to think of a nular{{sic}} [[:Category:Arma 3: Scripting Commands|operator]] as nothing more but a magic [[Variables|global variable]], but it is important to differentiate! | ||
Consider following example in a mission with e.g. 5 units: | Consider following example in a mission with e.g. 5 units: | ||
Line 94: | Line 94: | ||
// create a new unit in the player group | // create a new unit in the player group | ||
group player createUnit ["B_RangeMaster_F", getPosATL player, [], 0, " | group player createUnit ["B_RangeMaster_F", getPosATL player, [], 0, "NONE"]; | ||
// output the Array size again | // output the Array size again | ||
Line 115: | Line 115: | ||
== Unary Operators == | == Unary Operators == | ||
The unary [[:Category: | The unary [[:Category:Arma 3: Scripting Commands|operators]] are operators that expect an argument on their right side ({{hl|unary <argument>}}). They always will take the first argument that occurs. | ||
A common mistake would be the following: | A common mistake would be the following: | ||
Line 131: | Line 131: | ||
<sqf>(count _arr) select 2; // error</sqf> | <sqf>(count _arr) select 2; // error</sqf> | ||
Due to the nature of unary [[:Category: | Due to the nature of unary [[:Category:Arma 3: Scripting Commands|operators]], count instantly consumes our [[Variables|variable]] ''_arr'' and returns the number ''3''. | ||
The ''3'' then is passed to [[select]] which does not knows what to do with a number as left argument and thus errors out. | The ''3'' then is passed to [[select]] which does not knows what to do with a number as left argument and thus errors out. | ||
Line 147: | Line 147: | ||
== Binary Operators == | == Binary Operators == | ||
Binary [[:Category: | Binary [[:Category:Arma 3: Scripting Commands|operators]] expect two arguments ({{hl|<1st argument> binary <2nd argument>}}) and are executed according to their {{Link|#precedence}}. If their precedence is equal, they are executed left to right. | ||
As example, we will look into the following expression: | As example, we will look into the following expression: | ||
Line 171: | Line 171: | ||
<sqf>((((_arr select 0) select (1 - 1)) select ((15 / 3) - 5)) select 0) select (((10 * 10) + (4 * 0)) - 100)</sqf> | <sqf>((((_arr select 0) select (1 - 1)) select ((15 / 3) - 5)) select 0) select (((10 * 10) + (4 * 0)) - 100)</sqf> | ||
As you can see the | As you can see the <sqf inline>*</sqf> and <sqf inline>/</sqf> are executed first which matches their [[Order of Precedence|precedence]]. | ||
Afterward, the | Afterward, the <sqf inline>+</sqf> and <sqf inline>-</sqf> [[:Category:Scripting Commands|operators]] will get executed followed by our [[select]] operator, which are executed from the left to the right. | ||
[[Category: Syntax]] | [[Category: Syntax]] |
Latest revision as of 16:51, 24 April 2024
SQF stands for Status Quo Function - a successor of Status Quo Script, which is deprecated since Armed Assault but could still be used in Arma 3. SQF was first introduced in Operation Flashpoint: Resistance together with the call operator in update 1.85.
- "Status Quo" was a code name for Operation Flashpoint
- "Combined Arms" was a code name for Arma
- "Futura" was a code name for Arma 3.
The SQF Language is fairly simple in how it is built.
In fact: there are barely any actual language structures at all.
The functionality is provided via so called operators (or more commonly known scripting commands). Those operators are one of the following types: Nularsic, Unary, or Binary.
Terminating an expression
An SQF expression has to be terminated via either ; (preferred by convention!) or ,.
In the above example, there are three expressions:
- _num = 10
- _num = _num + 20
- systemChat str _num
All are separated by ; and not the line return - they could all be inlined and it would not impact the code.
Brackets
- () - Round brackets are used to override the default Order of Precedence or improve legibility.
- [] - Square brackets define Arrays.
- {} - Curly brackets enclose instances of the Code Data Type. They are also used in Control Structures.
Whitespaces
Whitespace consists of tabs and/or space characters.
For the purposes of the engine The 'line' begins at the first non whitespace character.
Similarly, trailing whitespace at the end of a line or statement is also ignored.
Blank Lines
Blank lines are lines containing nothing but whitespace and are therefore ignored by the engine.
Comments
A comment is additional text that gets ignored when a script is parsed. They serve as future reference and are often used to explain a specific part of the code.
In SQF, there are two kind of comments:
A comment can occur anywhere but inside a string. For example, the following would be valid:
It should be mentioned that there is a comment unary operator that should not be used as it will actually be executed (thus taking time to execute) but does nothing besides consuming a string. There is no benefit in using it and the reason it exists is solely for backward compatibility. Another way to make a comment that way, is to just place a string: /* some code */ "I can be considered as a comment but should not be used"; /* some other code */
Comments are removed during the preprocessing phase. This is important to know as that prevents usage in e.g a string that gets compiled using the compile unary operator or when only using loadFile.
Nular Operators
A nularsic operator is more or less a computed variable. Each time accessed, it will return the current state of something. It is tempting to think of a nularsic operator as nothing more but a magic global variable, but it is important to differentiate!
Consider following example in a mission with e.g. 5 units:
Now, what would the output of this look like?
System: 5 System: 5 System: 6
As you can see, _unitsArray was not automatically updated as it would have been if it was not generated each time. If allUnits was just a global variable with a reference to some internal managed array, our private variable should have had reflected the change as value types are passed by reference. The reason for this is because allUnits and other nularsic operators just return the current state of something and do not return a reference to eg. an array containing all units. It is generated each time, which is why some of theese operators are more expensive to run then just using a variable.
Unary Operators
The unary operators are operators that expect an argument on their right side (unary <argument>). They always will take the first argument that occurs.
A common mistake would be the following:
Now, what went wrong?
Let's put some brackets in the right places to make the mistake understandable:
Due to the nature of unary operators, count instantly consumes our variable _arr and returns the number 3. The 3 then is passed to select which does not knows what to do with a number as left argument and thus errors out.
To do it correctly, one would have to put the _arr select 2 in brackets. The correct code thus would be:
Binary Operators
Binary operators expect two arguments (<1st argument> binary <2nd argument>) and are executed according to their precedence. If their precedence is equal, they are executed left to right.
As example, we will look into the following expression:
Now, let us analyze why this is happening for the first few expressions:
- _arr is loaded
- 0 is loaded
- select is executed with the result of 1. & 2.
- 1 is loaded
- 1 is loaded
- - is executed with the result of 4. & 5.
- select is executed with the result of 3. & 6.
- ...
If we now would put brackets at the correct spots, the expression will get clearer:
As you can see the * and / are executed first which matches their precedence. Afterward, the + and - operators will get executed followed by our select operator, which are executed from the left to the right.