One of the fundamental mission maker tools is a knowledge of locality. In Arma 3, we do not have a strict client-server architecture. Instead, all clients as well as the server itself run code, both mission-specific user code as well as engine-internal AI code. The concept of Locality means nothing else but to determine where an engine object or entity is currently stored, and how this affects the execution of commands. Likewise, it is important to know how and where global variables are stored. We will examine these things in detail below.
The locality mostly concerns objects, but other things need consideration too. For example, Arma differentiates between global and local variables, but the names are a bit misleading. Local variables are local to a certain scope, namely the scope they are defined in. They are invariably named with a leading underscore character. The scripting engine immediately forgets them if they go out of scope, which is a common pitfall if you define them e.g. in the “then” part of an if statement.
What Arma calls global variables are variables that start with something else than an underscore character. However, and this is very important, global variables are global only to the scope of scripts running on the machine they were defined on. What this means is that if my script runs on a client machine and assigns a value to a global variable, that value is only visible on this specific machine. Even worse, a variable with the same name can have a different value on a different client, or the server. Arma does NOT automatically distribute variable values around clients and the server.
In this respect, we refer to “clients” as those machines that run a player’s game, and “server” as the machine that hosts the game. On a hosted game, one client will be identical to the server, but on a dedicated host, this is not the case. When we want to refer to either, we say “machine”.
In order to make sure that a variable has the same value on all clients and the server, it needs to be declared as public using the publicVariable command. In a script this looks something like this:
/* Define a variable to be used on all attached clients */ FHQ_DifficultyLevel = 1; publicVariable “FHQ_DifficultyLevel”;
The above makes sure the variable has the same value on all clients and the server, but this works on a first-come-first-served basis, meaning that running the same command on more than one client with different values might have different outcomes.
It is also worth nothing that although the variable in the above example was declared public, this only applies to the current value of the variable. This does not mean that future changes of the variable will be automatically transmitted as well. Every time you change the variable and want that change to be visible outside of the current machine, you need to run the publicVariable command again.
This type of locality behavior also affects variables set with the setVariable command. This command is usually used on objects or namespace objects, and the default behavior is the same as global variables – content or changes is not propagated to other machines. In order to make this type of variable public in the same sense as above, you need to use the three-element array version:
/* Make an object's variable public */ MyChopper setVariable ["Callsign", "Zulu Victor Niner", true];
The highlighted parameter is a boolean that will determine whether this setVariable command is propagated or not. Obviously, setting it to true will propagate the value, while omitting the parameter or setting it to false will not.