SQX API Reference

Get Started With Some Examples

Follow these steps to create a mission and a TypeSqf project with some pre written SQX files.

  1. Create a mission in the Arma 3 Eden editor (a mission.sqm file).
  2. Start TypeSqf and open the mission ('File->Open mission...' and select the mission.sqm file).
  3. Download CPacks with SQX content (using the CPack Console) to see some examples. Here are some:
  4. Compile the project ('Build->Compile project').
  5. Run the mission in the Arma 3 Eden editor.

#region New in 0.45

The #region command is used together with the #endregion to create a custom folding region in the editor. It is used as a preprocessor command (without semicolon), it does not affect the TypeSqf analyzer, and it does not have any compiler output.

#region [RegionName]

Some code ...

#endregion

Custom regions are also possible to use in SQF files. However, since SQF is not compiled by TypeSqf you need to write them in a line komment:

// #region [RegionName]

Some code ...

// #endregion

Example: A folding region around some variable initialization:
#region Global Mission Variables

Abc_EnemyCount = 10;
Abc_AlwaysRespawnAtBase = true;
Abc_UseRevive = true;

#endregion
Example: A folding region in SQF:
// #region Global Mission Variables

Abc_EnemyCount = 10;
Abc_AlwaysRespawnAtBase = true;
Abc_UseRevive = true;

// #endregion

_self

The variable _self is a local variable that is declared automatically in all methods (and the constructor), and it is used to reference members of the current instance of the class.

_self.[PropertyName] = [Value];      // Setting a property value
[Variable] = _self.[PropertyName];   // Using a property value
[Arguments] call _self.[MethodName]; // Calling a method

Example: Initializing a class in the constructor:
public class Tower {
    public constructor {
        call _self.InitializeHeight; // Using self to call method
    };

    private method InitializeHeight {
        // Using self to set property value
        _self.Height = 100;

        // Sending current instance as parameter to a global function
        [_self] call somePublicFunction; 
    };

    public property Scalar Height { get; private set; };
};

as

The as keyword is used to explicitly determine the type of a variable or an expression, and it may be used in a number of ways.

1. It may be used to set a variable's type in a declaration:

private "_var" as Group;

When a variable is declared in this way the TypeSqf analyzer will not allow it to be assigned a value of any other type than Group or 'Any'. The latter is a data type that is used when the actual type is unspecified or unknown.

2. It may be used to cast a value type, e.g. in an assignment. A variable assigned like below is allowed to be used as a 'Building' (if its type is not explicitly set). The 'as' keyword here tells the TypeSqf analyzer that _anotherVar actually is of type Building, in case its type is unknown.

_myVar = _anotherVar as Building;

3. Is may be used in a forEach declaration to state the type of the iteration variable _x. If the "as" is left out in this example, the analyzer do not know how that _x is of type House, and it will not approve the reference to the method NoOfDoors that is being used.

{
    hint str _x.NoOfDoors;
} forEach _myArray as House

Example: All forms of declarations with explicit type set:
public class Vehicle {};
public class Civilian {
    public constructor { _self.IsAlive = true; };
    public property Boolean IsAlive { get; set; };
};

civs = [new Civilian, new Civilian, new Civilian];

// A single variable of type Civilian
private "_civilian" as Civilian;

// An array declaration
private ["_age" as Scalar, "_name" as String];

// It may also be used in the parameter declaration of 'params':
params ["_vehicle" as Vehicle];

// Or a params parameter with default value:
params [["_vehicle" as Vehicle, classNull]];

// Or as a type specifyer in a count statement:
myCount = { _x.IsAlive } count civs as Civilian;

// Or as a type specifyer in a forEach statement:
{
    if (_x.IsAlive) then {
        hint "he is alive!";
    };
} forEach civs as Civilian;

class

The class keyword is used to define a class (an object).

A class may contain one constructor, fields, properties and methods. The outline of a class looks like this:

public class [Name] [: Interfaces ] {
    [private fields [ ... ]; ]
    [public constructor[(Parameters)] { ... }; ]
    [public property [Type] [Name] { get; [private] set; }; ]
    [[public|private] method [Type] [Name][(Parameters)] { ... }; ]
};

A class can implement one or more interfaces.

A class may only be public.

Example: Minimum required syntax to define a class:
public class TinyClass {};
Example: Working class with all inner symbols represented:
public class Person {
    private fields ["_mName" as String];

    public constructor("_name" as String, "_age" as Scalar)
    {
        _mName = _name;
        _self.Age = _age;
    };

    public property Scalar Age { get; private set; };

    public method IncreaseAge("_ageDiff" as Scalar)
    {
        _self.Age = _self.Age + _ageDiff;
    };
};
Example: Using the class Person:
private ["_person" as Person, "_name" as String, "_age" as Scalar];

_person = ["David", 25] new Person; // Create new instance
[10] call _person.IncreaseAge;      // Increase age by 10
_age = _person.Age;                 // Get age from person

classNull

The classNull keyword is used to give a variable a null value. The value can then be tested with the 'isNull' command.

Example:
public class Person {};

private ["_person" as Person];

// Before this line, _person is undefined
_person = classNull;

if (isNull _person) then {
    hint "This person is null!";
};

constructor

The constructor keyword is used to define a constructor in a class. A class may have zero or one constructor defined.

public constructor[(Parameters)] { ...; };

The purpose of a constructor is to initialize a class instance upon create, i.e. when the 'new' statement is executed. It must not have a return value, since the return value of the 'new' statement is the new instance of the class. That means, always terminate the last statement in a constructor with a semicolon.

A constructor may only be public.

Constructor Parameters New in 0.64

The classic way to specify the constructor's parameter (prior to TypeSqf 0.64) is to use the "params" script command on the first line of the constructor, like this:

public constructor
{
    params ["_name" as String, ["_yearsInBusiness" as Scalar, 0]];
    ...
};
In the example, the first parameter "_name" is required, and the second "_yearsInBusiness" is optional, see the official Arma 3 params documentation.

Since TypeSqf 0.64, however, the params variable content can instead be moved to the header (similar to other languages). The syntax for the parameters in the header is exactly like the syntax in the params list.:

public constructor("_name" as String, ["_yearsInBusiness" as Scalar, 0])
{
    ...
};

Example: Defining and instantiating a class with a constructor:

public class Vehicle {
    public constructor {
        hint "New vehicle created!";
    };
};

pubVar = new Vehicle; // "New vehicle created!" shown on screen.

Example: Defining and instantiating a class with constructor parameters:

public class Vehicle {
    public constructor("_className" as String) {
        hint "A new vehicle of type " + _className + " created!";
    };
};

pubVar = ["B_Quadbike_01_F"] new Vehicle; // "New vehicle created!"


enum New in 0.54

The enum keyword is used to define an enum type. An enum (i.e. enumeration) is a collection of enumerated values.

public enum [Name] { [Value1 [ = x]][, Value2 [= y]] ... };

The purpose of an enum is to translate enumerable constants to understandable concepts for the developer. It can in many ways be compared to a constant. Imagine you want to use the arrow keys in a mission, but instead of remembering some imagined and distinctive number value for them, you create the following enum:

public enum Keys {
    Left,
    Up,
    Right,
    Down
};

Now you will only need to remember the name of the enum, and the enum also defines all possible and impossible values.

As an alternative syntax, and if you want to translate the enum value to a specific value, you may declare the type and give the values a number. Say you also somewhere need the ASCII values for the arrow keys:

public enum Keys {
    Left = 37,
    Up = 38,
    Right = 39,
    Down = 40
};

Note that the latter version with explicitly set values will also let you use the enum values in SQF contexts. The usages of an enum type compiles directly to its scalar value. If not set explicitly, the values will be an enumeration starting from 1.

Example: Defining a class with a constructor:
namespace MyMission
{
    public enum VehicleType
    {
        Land,
        Air,
        Sea
    };

    public class Vehicle
    {
        public constructor("_type" as VehicleType) {
            _self.Type = _type;
        };

        public property VehicleType Type { get; set; };
    };

    private ["_vehicle" as Vehicle];
    _vehicle = [VehicleType.Land] new Vehicle;
    
    if (_vehicle.Type == VehicleType.Air) then { // Will be false
        hint "This is an air vehicle.";
    };
};

fields

The fields keyword is used to define private fields in a class. A 'field' (or a class variable) is a private variable that can be accessed by all members (the constructor and all methods) of a class.

private fields ["[Name]" [as [Type]], ... ];

The requirement for naming of a field is the same as for naming a local variable. However, it may be good practice to name them so that they never interfere with local variables in the constructor or in the methods. The suggestion is to add an 'm' (as in member) to name the variables. E.g. the local variable

_myVar
would form the corresponding private field
_mMyVar

A field may only be private. If you need a public field, use a property.

Example: Defining a class with private fields that are initialized in the constructor:
public class Person {
    private fields ["_mName", "_mAge"];

    public constructor("_name", "_age")
    {
        _mName = _name;
        _mAge = _age;
    };
};

// Creating an instance of class person
person = ["John", 30] new Person;

interface (new in 0.52)

Interface management in SQX is used to template different aspects (or views) of class objects. It can be seen as a way to declare different behaviors of objects. Classes implementing interfaces are then fully compatible with methods and functions that manages these behaviours.

The behaviour of interfaces are much similar to interfaces as we know them from languages such as Java and C#.

An interface declaration is similar to a class declaration, but much simpler. It may only contain properties and methods, and it only provides declarative headers and no bodies. All members are regarded as public. Thus the keywords public and private need not be used (and are not allowed). The outline of an interface looks like this:

public interface [Name] {
    [property [Type] [Name] { get; [set;] }; ]
    [method [Type] [Name](Parameters); ]
};

While the name of an object (a class) should be a noun, the name of an interface should be an adjective. Furthermore, the name of an interface is also suggested to start with a capital 'I', to clearly distinguish them from classes.

Parameters New in 0.64

Unlike methods, the parameter list of an interface method is not optional (since TypeSqf 0.64). The syntax of the parameter list is the exact same as for the script command params.

Performance Considerations

While a call to a method of a class known by the editor is compiled to an ordinary global function call, that is not the case with calls to methods of unknown classes (interfaces). Since the exact global function name is unknown to the editor in the case of interfaces, the calls are being compiled with help of meta data in runtime. So if high performance is needed due to frequent function calls, you do better perform the method call to the actual class rather than to an interface.

Example: A function that performs a teleport. It can take any object that implements the ITeleportable interface as an argument:
namespace Units
{
    public interface ITeleportable
    {
        method TeleportToPos("_pos" as Array);
    };

    public class Soldier : ITeleportable
    {
        public property Object UnitObj { get; set; };

        public method TeleportToPos("_pos" as Array)
        {
            _self.UnitObj setPos _pos;
        };
    };
	
    // If you want to use this function and send in your own class,
    // then have the class implement the ITeleportable interface.
    fnc_PerformTeleport = {
        params ["_object" as ITeleportable, "_pos" as Array];
        [_pos] call _object.TeleportToPos;
    };
};

is (new in 0.52)

The is operator performs a runtime check on whether a variable is of a certain type or not. The return type of the is operator is Boolean.

[Variable|Literal] is [Type]

The "is" keyword can be used to test classes, interfaces and native types.

public interface IDemolishable { ... };
public class Tower : IDemolishable { ... };
...
if (_myTower is Tower) then {};         // true if _myTower is not null
if (_myTower is IDemolishable) then {}; // true if _myTower is not null
if (_height is Scalar) then {};         // true if _height is a Scalar.

If a class variable is set to null (classNull) the is operator always returns false, even if the variable's type is set explicitly in declaration.

_myTower = classNull;
_result = (_myTower is Tower); // false.

Note that only variables and literals can be checked. Not expressions.

Example: A function that takes a parameter of unknown type, tests the type and takes action:
namespace Vehicles {
    public class Car {
        public property Scalar Passengers { get; set; };
    };
	
    public class Truck {
        public property String Cargo { get; set; };
    };

    globalFnc = {
        params ["_vehicle"];

        if (_vehicle is Car) then {
            hint str (_vehicle as Car).Passengers;
        }
        else {
            hint (_vehicle as Truck).Cargo;
        };
    };
};

method

A method is a function that belongs to a class. It executes just as an ordinary function, but it also has access to the fields of the class.

[public|private] method [Type] [Name][(Parameters)] { ... };

A method may be public or private. If it is private, only methods within the class have access to it, and if it is public it may be accessed from outside of the class.

If the return type is left out, the method's return value type will be 'Any'. However, this may be subject for changes in the future due to ongoing discussions.

Method Parameters New in 0.64

The classic way to specify the method's parameter (prior to TypeSqf 0.64) is to use the "params" script command on the first line of the method body, like this:

public method Scalar RateEmployee
{
    params ["_name" as String, ["_yearsInBusiness" as Scalar, 0]];
    ...
};
In the example, the first parameter "_name" is required, and the second "_yearsInBusiness" is optional, see the official Arma 3 params documentation.

Since TypeSqf 0.64, however, the params variable content can instead be moved to the header (similar to other languages). The syntax for the parameters in the header is exactly like the syntax in the params list.:

public method Scalar RateEmployee("_name" as String, ["_yearsInBusiness" as Scalar, 0])
{
    ...
};

Example: Defining a class with methods, and calling them correctly and incorrectly:
public class Signal
{
    public constructor
    {
        call _self.SoundBeep;              // OK!
        ["TUUUT!"] call _self.SoundCustom; // OK!
    };

    public method SoundBeep
    {
        hint "BEEP!";
    };

    private method SoundCustom("_sound" as String)
    { 
        hint _sound;
    };
};

private "_signal" as Signal;
_signal = new Signal;
call _signal.SoundBeep;              // OK!
["TOOOT!"] call _signal.SoundCustom; // Not OK - method is private!

namespace (new in 0.40)

A namespace is used to keep class names unique. A common problem for developers is that objects and function names collide with other developer's work. A common and primitive form of namespace is to add a personal prefix to function names. In SQX this can better be solved with namespaces. A namespace is declared like this:

namespace [Name] { ... };

Consider the example class Helicopter below:

namespace LordPhilip.Vehicles
{
    public class Helicopter {
        public method LandAtBase { ... };
    };
};

The Helicopter class above can be referenced in three ways.

1. The usual scenario would be to add a using directive at the beginning of the file. This tells the TypeSqf analyzer that all classes in the specified namespace can be used without specifying the namespace path on each occurrence.

using LordPhilip.Vehicles;
myChopper = new Helicopter;

2. Within the same namespace (or a namespace with the same name), only the class name needs to be specified (unless there is no conflict with a class in another used namespace.).

namespace LordPhilip.Vehicles
{
    myChopper = new Helicopter;
};

3. The class can always and in any context be referenced by specifying the full namespace path and class name. This is useful if there are conflicting class names in other used namespaces.

myChopper = new LordPhilip.Vehicles.Helicopter;

The namespace declarations do not need to be unique. If you want to add a class to an existing namespace, simply surround the class with a namespace declaration that has the desired name.

Order Of Execution

All classes and namespaces that are included in the project are considered known to the TypeSqf Editor. Note that there is no question about which files that are included by files. TypeSqf assumes that all classes that can be found in the project tree is possible to use anywhere. That might not be the case. The user needs to manage so that all classes have been included and executed before being referenced.

Namespaces vs. File Structure

Namespaces are independent of file structures. However, it is recommended to have the namespace names organized as the folders and files in the project. E.g. the content in the file MyRevive/Start/ReviveOptions.sqx would be written in a namespace named MyRevive.Start.

NOTE: The only code affected by namespace is SQX classes, and not public variables and functions. In future releases also public variables and functions may be affected.

Example: The file LordPhilip/Vehicles/Helicopter.sqx in the mission project:
namespace LordPhilip.Vehicles
{
    public class Helicopter {
        public method LandAtBase {
            hint "Landing at base.";
        };
    };

    public class PieceOfFreight {};
};
Example: The file Scissorman/Air/Helicopter.sqx in the mission project:
namespace Scissorman.Air
{
    public class Helicopter {
        public method AttackPosition("_position" as Array)
        {
            hint "Attacking position " + str _position;
        };
    };
};
Example: The file init.sqx that are using the classes above:
call compile preprocessFile "LordPhilip/Vehicles/Helicopter.sqx";
call compile preprocessFile "Scissorman/Air/Helicopter.sqx";

using LordPhilip.Vehicles;
using Scissorman.Air;

namespace TheMission
{
    // The PieceOfFreight class is known because of the "using" above.
    private "_freight" as PieceOfFreight;

    // The two helicopters' names are conflicting, so here we need 
    // to specify the full namespace path for each.
    private "_freightChopper" as LordPhilip.Vehicles.Helicopter;
    private "_attackChopper" as Scissorman.Air.Helicopter;

    _freightChopper = new LordPhilip.Vehicles.Helicopter;
    _attackChopper = new Scissorman.Air.Helicopter;

    call _freightChopper.LandAtBase;
    [getMarkerPos "attackMarker"] call _attackChopper.AttackPosition;
};

property

The property is essentially a public variable, but it may have getters and setters of different kinds of access (public/private).

public property [Type] [Name] { get; [private] set; };

The purpose of a property, in addition to storing a variable value, is to make class variables available from contexts outside of the class. In addition, it makes the syntax easier and more convenient than get and set methods.

A property may only be public, but its setter may be public (set;) or private (private set;).

If the return type is left out, the property's value type will be 'Any'. However, this may be subject for changes in the future due to ongoing discussions.

Example: Defining a class with properties, and referencing them correctly and incorrectly:
public class Dictionary {
    public constructor {
        _self.Name = ""; // OK!
        _self.Count = 0; // OK!
    };

    public property String Name { get; set; };
    public property Scalar Count { get; private set; };
};

myDictionary = new Dictionary;
myDictionary.Name = "From A to Z"; // OK!
myDictionary.Count = 10;           // Not OK - property has a private setter!

static (new in 0.53)

The keyword "static" is used to create static fields, properties or methods in classes. A static member does not belong to a certain instance, but should be thought of as a member shared across all instances, or rather, a single instance declared directly on the class definition. A static method does not use any non static members (like instance fields, instance properties and instance methods) of the class, and can therefore be called without having to instantiate the class first.

[public|private] static method [Type] [Name] { ... };

A static method can be called from .SQF context by replacing the dots in its full name with underscores (see example).

Why not a usual global function?

A static method is just like an ordinary global function, but with one important difference - it belongs to a class. Technically a global function is just as good as a method, but with the object oriented approach you would want all methods to belong to an object, and in that way add context and meaning to the method name.

For example, a Math class may be used to bundle up methods that do different types of calculations, but these methods do not have anything in common except for that. And you do not want to write a lot of code to instantiate the class before use:

private ["_math" as Math];
_math = new Math;
_roundedValue = [_value] call _math.Round;

So if the methods are static you can simply use them with a call like the following:

_roundedValue = [_value] call Math.Round;

Example: A Tank object with a static method that blows up any provided tank:
namespace Mission
{
    public class Tank {
        // Static method that blows up the provided tank.
        public static method BlowUpTank("_tank" as Tank)
        {
            hint "BOOM!";
        };
    };

    myTank = new Tank;
    
    // Blow up tank from insie the namespace
    [myTank] call Tank.BlowUpTank;
};
                
// Blow up tank from outside the namespace
[myTank] call Mission.Tank.BlowUpTank;
Example: Blowing up the tank from an editor trigger (or from any SQF context):
[myTank] call Mission_Tank_BlowUpTank;

using (new in 0.40)

The using keyword is used to specify the use of a bundle of classes, so that they can be referenced without the developer having to specify the full namespace path on every time.

using [Namespace];

The using directive is usually written at the top of a file, but beneath eventual includes. It is allowed to write them further down in the file, and in that case the using will not be valid above the using statement. However, a using directive is always valid for the rest of the file, and cannot be removed.

Example: The file Scissorman/Air/Helicopter.sqx in the mission project:
namespace Scissorman.Air
{
    public class Helicopter {
        public method AttackPosition("_position" as Array)
        {
            hint "Attacking position " + str _position;
        };
    };
};
Example: The file init.sqx in the mission project:
call compile preprocessFile "Scissorman/Air/Helicopter.sqx";

using Scissorman.Air;

// The Helicopter's full class name is "Scissorman.Air.Helicopter".
// Since the using above, simply "Helicopter" will be enough.
private ["_chopper" as Helicopter];

_chopper = new Helicopter;
call _chopper.LandAtBase;