Variables: Difference between revisions

From Bohemia Interactive Community
Jump to navigation Jump to search
(Fix variables scopes (very old discussion about this) with current standard: private, local, global variables)
Line 36: Line 36:
This effectively destroys a variable as if it had never existed.
This effectively destroys a variable as if it had never existed.


== Namespace ==
== Scopes ==


Variables are only visible in certain areas (namespaces) of the game. This prevents name conflicts between different variables in different [[Script (File)|scripts]].
Variables are only visible in certain scopes of the game. This prevents name conflicts between different variables in different [[Script (File)|scripts]].


There are three namespaces:
There are three scopes:
 
; private
: A variable is only visible in the [[Script (File)|script]], or [[function]], or [[Control Structures]] in which it was defined.


; local
; local
: A variable is only visible in the [[Script (File)|script]] in which it was defined.
: A variable is visible on the whole computer where it was defined.


; global
; global
: A variable is visible on the whole computer where it is defined.
; public
: A variable is broadcasted over the network and visible on all computers connected to the network.
: A variable is broadcasted over the network and visible on all computers connected to the network.


=== Local Variables ===
=== Private Variables ===


Local variables are only visible in a specific [[Script (File)|script]]. The whole code in this script has access to the variable, that includes also [[Function|functions]] called within the script.
Private variables are only visible in a specific [[Script (File)|script]], or [[function]], or [[Control Structures]].  


The [[identifier]] of variables local to a [[Script (File)|script]] always has to start with an underscore.  
The [[identifier]] of private variables in a [[Script (File)|script]] always has to started with an underscore.  


  _myLocalVariable = 0;
  _myPrivateVariable = 0;


In functions you should additionally mark variables as local using the command [[private]]. Otherwise you may modify local variables of the calling script that are visible in the function.
In functions you should additionally mark variables as private using the command [[private]]. Otherwise you may modify private variables of the calling script that are visible in the function.


  private "_myLocalVariable";
  private "_myPrivateVariable";
  _myLocalVariable = 0;
  _myPrivateVariable = 0;


You may also pass more [[Identifier|identifiers]] to the private command using an [[Array]].
You may also pass more [[Identifier|identifiers]] to the private command using an [[Array]].
Line 68: Line 68:
  private ["_myLocalVariable1", "_myLocalVariable2", ...];
  private ["_myLocalVariable1", "_myLocalVariable2", ...];


=== Global Variables ===
=== Local Variables ===
 
Local variables are visible on the whole computer where they are defined. Names given to units in the [[Mission Editor]] are also local variables pointing to those units, which may not be redefined or modified.


Global variables are visible on the whole computer where they are defined. Names given to units in the [[Mission Editor]] are also global variables pointing to those units, which may not be redefined or modified.
[[Identifier]]s of local variables ''must not'' start with underscore. Otherwise there are the same rules as for all [[Identifier|identifiers]].


[[Identifier]]s of global variables ''must not'' start with underscore. Otherwise there are the same rules as for all [[Identifier|identifiers]].
myLocalVariable = 0;


myGlobalVariable = 0;
=== Global Variables ===


=== Public Variables ===
Global variables are local variables, visible on all computers in the network. You can never have true global variables, but you can emulate their behaviour.


Public variables are global variables that are visible on all computers in the network. You can never have true public variables, but you can emulate their behaviour.
The value of a local variable gets broadcasted over the network using [[publicVariable]]. After the call of this command the variable will have the same value on all [[Client|clients]]. Once you modify the variable though you have to broadcast it manually ''again'' with [[publicVariable]].


The value of a global variable gets broadcasted over the network using [[publicVariable]]. After the call of this command the variable will have the same value on all [[Client|clients]]. Once you modify the variable though you have to broadcast it manually ''again'' with [[publicVariable]].
== More informations relative to private variable ==
If a private variable is initialized within a [[Control Structures]] (i.e. [[if]], [[for]], [[switch]], [[while]]) its scope will stay ''within'' this structure (i.e. outside of the structure it will still be seen as undefined).


== Scope ==
<code>if (alive player) then {private _living=true}; hint format["%1",_living];</code>
If a local variable is initialized within a [[Control Structures]] (i.e. [[if]], [[for]], [[switch]], [[while]]) its scope will stay ''within'' this structure (i.e. outside of the structure it will still be seen as undefined). This does not apply to global or public variables.
Returns "scalar bool array string 0xe0ffffef", since the private variable was not initialized ''before'' being used within a control structure.
<code>if (alive player) then {_living=true}; hint format["%1",_living];</code>
Returns "scalar bool array string 0xe0ffffef", since the local variable was not initialized ''before'' being used within a control structure.


<code>_dead=true; if (alive player) then {_dead=false}; hint format["%1",_dead];
<code>private _dead=true; if (alive player) then {_dead=false}; hint format["%1",_dead];
</code>
</code>
Returns "false", since the variable was initialized before the if...then.<br>
Returns "false", since the variable was initialized before the if...then.<br>
To initialize local variables, so that they are available throughout the whole script (including any control structures), either initialize it via the [[private]] command (e.g. ''private ["_varname"];''), or by assigning a default value to it (e.g. ''varname=0;'').
To initialize private variables, so that they are available throughout the whole script (including any control structures), either initialize it via the [[private]] command (e.g. ''private ["_varname"];''), or by assigning a default value to it (e.g. ''varname=0;'') at the begining of the script.


== Data Types ==
== Data Types ==
Line 100: Line 101:
== Multiplayer Considerations ==
== Multiplayer Considerations ==


Storing vars and functions into global vars without securing them with [[compileFinal]] (only after Arma-3) is a very bad practice in MP.
Storing vars and functions into local vars without securing them with [[compileFinal]] (only after Arma-3) is a very bad practice in MP.
Basically, if you have a script installed on a server in mission file that uses functions stored in unprotected variables then hackers can overwrite that function attached to a global variable and make it execute code for everyone and do a lot of nasty stuff. So please put all of the code for each function in a SEPARATE file and initialize them like this:
Basically, if you have a script installed on a server in mission file that uses functions stored in unprotected variables then hackers can overwrite that function attached to a global variable and make it execute code for everyone and do a lot of nasty stuff. So please put all of the code for each function in a SEPARATE file and initialize them like this:
<code>myGlobalVarFunction = compileFinal preprocessFileLineNumbers "Dir\where\function\is\fnc_globalVarFunction.sqf";</code>
<code>myGlobalVarFunction = compileFinal preprocessFileLineNumbers "Dir\where\function\is\fnc_globalVarFunction.sqf";</code>

Revision as of 11:48, 7 December 2017

Template:Stub

A variable is a "storage container" or "named placeholder" for data. You can read and modify the data once this container is created.

Requirements

The following links guide to the basics to understand this article:

Initialization

The first thing you have to do is to find a name for your variable. This name is called identifier. Read the article Identifier for more information.

Once you know a name, you have to tell the game engine that you are going to use this identifier. This is called initialization. Then you may do anything with this variable.

Don't worry: This sounds more dramatic than it is. You can initialize any variable by assigning a value to it.

myVariable = 0;

Querying undefined (or uninitialized) variables returns nil (undefined value). When converted to Strings with str, they will always return scalar bool array string 0xe0ffffef (in Armed Assault) or scalar bool array string 0xfcffffef (in Operation Flashpoint).

myString = str(undefinedVar);

myString => "scalar bool array string 0xe0ffffef"

Thus you can't really apply any operations on variables before they are initialized with a start value.

Deletion

Once created, variables will take up space in your computer memory. This is not drastic for small variables, but if you use a big number of very large variables, you should undefine any variables that are not needed anymore. This can be done with the command nil.

hugeVariable = nil;

This effectively destroys a variable as if it had never existed.

Scopes

Variables are only visible in certain scopes of the game. This prevents name conflicts between different variables in different scripts.

There are three scopes:

private
A variable is only visible in the script, or function, or Control Structures in which it was defined.
local
A variable is visible on the whole computer where it was defined.
global
A variable is broadcasted over the network and visible on all computers connected to the network.

Private Variables

Private variables are only visible in a specific script, or function, or Control Structures.

The identifier of private variables in a script always has to started with an underscore.

_myPrivateVariable = 0;

In functions you should additionally mark variables as private using the command private. Otherwise you may modify private variables of the calling script that are visible in the function.

private "_myPrivateVariable";
_myPrivateVariable = 0;

You may also pass more identifiers to the private command using an Array.

private ["_myLocalVariable1", "_myLocalVariable2", ...];

Local Variables

Local variables are visible on the whole computer where they are defined. Names given to units in the Mission Editor are also local variables pointing to those units, which may not be redefined or modified.

Identifiers of local variables must not start with underscore. Otherwise there are the same rules as for all identifiers.

myLocalVariable = 0;

Global Variables

Global variables are local variables, visible on all computers in the network. You can never have true global variables, but you can emulate their behaviour.

The value of a local variable gets broadcasted over the network using publicVariable. After the call of this command the variable will have the same value on all clients. Once you modify the variable though you have to broadcast it manually again with publicVariable.

More informations relative to private variable

If a private variable is initialized within a Control Structures (i.e. if, for, switch, while) its scope will stay within this structure (i.e. outside of the structure it will still be seen as undefined).

if (alive player) then {private _living=true}; hint format["%1",_living]; Returns "scalar bool array string 0xe0ffffef", since the private variable was not initialized before being used within a control structure.

private _dead=true; if (alive player) then {_dead=false}; hint format["%1",_dead]; Returns "false", since the variable was initialized before the if...then.
To initialize private variables, so that they are available throughout the whole script (including any control structures), either initialize it via the private command (e.g. private ["_varname"];), or by assigning a default value to it (e.g. varname=0;) at the begining of the script.

Data Types

Variables may store certain values. The kind of the value specifies the type of the variable. Different operators and commands require variables to be of different types.

Read the article Data Types for more information about variable types.

Multiplayer Considerations

Storing vars and functions into local vars without securing them with compileFinal (only after Arma-3) is a very bad practice in MP. Basically, if you have a script installed on a server in mission file that uses functions stored in unprotected variables then hackers can overwrite that function attached to a global variable and make it execute code for everyone and do a lot of nasty stuff. So please put all of the code for each function in a SEPARATE file and initialize them like this: myGlobalVarFunction = compileFinal preprocessFileLineNumbers "Dir\where\function\is\fnc_globalVarFunction.sqf"; That way, the function can be called and spawned without it being subject to hackers that attempt to overwrite the global variable "myGlobalVarFunction".

Everyone happy :)

See also