Unlike variables, objects always reside on exactly one machine. This can be the server or any connected client, and it can and will change with time (with certain exceptions). The exact rules of locality are outlined here, but as mission makers it isn’t really all that relevant to us. What is important, though, is to know when and where effects are global or local, and what type of arguments a scripting command can take. To test whether an object is local or not, the command local object can be used which will either return true if the object is local to the machine the command is running on, or false if it isn’t. This is a very important command.
For the sake of clarity, when we say object here we refer to a vehicle, a unit, or anything that is of type Object. A common predefined object variable is player, which is a reference to the object that represents the player on the client the script is running on1. On a client, the scripting command local player will always return true2, and consequently, this means that the player variable references a different object on each client (and no object on the dedicated server).
If you look at the BIKI entries for some commands (most notably, those that refer to objects), you will notice some two of four different icons that can appear on top. These are:
- “AL” (argument local): A command that has this icon needs to be run on the machine that the object it operates on is local. That means that if the object is on a different machine, the statement will have either no effect, or a different, undefined effect. setVariable is an example of a command with a local argument; the statement will have no effect if the argument is on a different machine.
- “AG” (argument global): A command with this icon can run on any machine, the argument object does not need to be local (but can be) to the machine running on. An example of this is the local command, which can operate on any object.
AG is mutually exclusive to AL
- “EL” (effect local): A command with local effect will have exactly that – a local effect. The result of this command will be local to the machine it runs on, and its effects will not be visible globally, on different machines. Again, the setVariable command is an example of a command with local effect; unless instructed to do so by the three-element array version, setVariable‘s effect will only be visible locally, and not propagate over the network.
- “EG” (effect global): A command with global effect will have a visible, noticeable effect on all connected machines (clients and server alike). The setDamage command is one such example, even executed on a single machine, setting an objects damage to 1 will kill it and it will appear dead/destroyed on all attached machines.
EG is mutually exclusive to EL.
It is of utmost importance to know what argument type and effect type a command has. Any mistake here has the potential of breaking your mission, so make sure to look up the effects.
Object locality will dictate what kind of scripting commands you can run on an object. If local object returns false, then you will not be able to use a command of the “AL” category. This category of commands must run on the same machine. On the other hand, a command of the “AG” category can disregard the locality of the object, since it will be able to operate on it. However, the effect can still be local only, as is for example the case with addAction. addAction can operate on any type of object, but the effect (the action menu entry for the object) will only be visible on the machine where it was executed. That means you have full control which players get the action, but it also means you need to run the command on every server in order to get the action.
A command with local effect cannot be easily made global. In the case of the setVariable command, there is an easy way to distribute the effect to other machines, but that is not the case for all commands. As an example the addWeaponCargo command, while being able to operate on an object that is stored anywhere, will only add the weapon cargo to the object on the specific machine that the command runs on. So, for example, if you run the command on an ammo box on a dedicated server, the extra weapons you put in are not visible to the clients, and it will appear as a stock ammo box.
Luckily, the addWeaponCargoGlobal command is a version of the command that will do just that, so in this case it is easy to work around this limitation. Other commands might not be so easy to fix, but we will talk about that later in the discussion of the BIS_fnc_MP function.
It is very important to observe that the global effect takes place every time the command is executed. Take the following example of an init.sqf script from a fictitious mission. We will assume there is a car in the mission called “FHQ_playerCar” placed on the map, and you want to fill it up with four MX rifles and 10 magazines.
/* init.sqf */ FHQ_playerCar addWeaponCargoGlobal [“arifle_MX_F”,4]; FHQ_playerCar addMagazineCargoGlobal [“30Rnd_65x39_caseless_mag”, 10];
If you paid attention, you will immediately see what is wrong here. init.sqf is run at startup on all clients and the server. The two lines of code supposedly add 4 MX rifles and 10 magazines. But since the effect is global, something else entirely will happen.
- On a hosted game with only a single player, or single player for the matter, the effect will be as intended – there will be 4 rifles and 10 magazines.
- On a dedicated server with a single player, there will be 8 rifles and 20 magazines. Since the script runs on all machines, and the effect of the command is global, addWeaponCargoGlobal will add four rifles on all machines. In fact, if there are more players than one, the effect will stack.
This is just a very constructed example, but it shows the problem with global effects: Duplication. Not even Bohemia Interactive’s own code is always bulletproof against that. For example, the Supports module that airdrops ammo will duplicate by the number of players in a mission on dedicated servers.
The situation is especially dangerous since the first case (single player on a hosted server) is the default case under which most people test their missions: They just click “Preview” in the editor, playing the mission by themselves.
Similar effects can occur when using triggers. We will talk about trigger locality in more detail below.
Obviously, one of the most serious issues that can occur with local effect commands is that they only have effect on a single machine. createSimpleTask is an example of a command that takes a global argument but only has local effect. While most briefings are added during init.sqf and therefore globally visible, creating tasks dynamically during the mission will fail to show the tasks for everyone unless the command is properly executed on all attached clients.
Likewise, certain commands that seem to be working correctly when you test the mission in single player or on a hosted environment will fail to work on dedicated or with more players. For instance, if you want to override an object’s material, you would use the setObjectMaterial command. Typically, you would be tempted to put this into e.g. a vehicle’s init field. However, the init field is run only where the object is local – if it is an empty vehicle, it would only run on the server, if a player is sitting in it, it would only run on the machine that the driver is using, etc. Since the effect is local, at most one player would see the effect, and everybody else would not see anything.
- Note that there is no player object on a dedicated server, only on clients (or a hosted server), a common pitfall that is responsible for a lot of errors.
- “Always” isn’t quite true, there is a very short period of time at the beginning of the mission when a player is still loading the mission that a player object may be local to the server.