Instead of regular JavaScript variables and properties (not to be confused with buildings), Commander Wars uses what are known as Script Variables to store data that can then be accessed across multiple functions.

For example, let's say you want to make a CO that keeps track of the number of attacks made during a turn. While normal JavaScript variables and properties might suffice, they come with a couple issues:

  • They are not stored in game saves. This means if you save, restart the game and reload, the game won't remember whatever values were stored.
  • They are shared across all instances of the same CO, meaning if two players play the same CO in the same match, they'll both share the same values stored in those properties.

How to use Script Variables

Many objects in Commander Wars support Script Variables, including COs, units, buildings, map scripts, campaign scripts, weather scripts, players, and many more.

For simplicity, this tutorial will use a CO for its examples, but Script Variables work the same way for everything else (like units). You can also write or read data stored in a unit's Script Variables from a CO's code, and vice versa.

Getting started

Most cases of Script Variable usage start with the following two lines of code, or something similar (variable names may vary):

var variables = co.getVariables();
var exampleSVar = variables.createVariable("Test");

In the first line, a reference to the CO's Script Variables is assigned to the variable variables. To better explain this, the function getVariables() returns the reference (and in this case, a reference to Script Variables belonging to co, which is the CO).

The following line then uses the reference to access a specific Script Variable named "Test". If a Script Variable named "Test" doesn't already exist for the CO, createVariable() will create it. Otherwise, it'll return the existing Script Variable.

You can also use getVariable() instead of createVariable() if you can be sure that the Script Variable definitely already exists. getVariable() is a bit faster than createVariable(), but it can lead to errors if the Script Variable doesn't already exist. (Do not confuse getVariable() with getVariables(), which is an entirely different function that we just went over.)

With that out of the way, what follows those two lines of code depends on whether you want to access data stored in the Script Variables, or write data to them.

Accessing data stored in Script Variables

To access data that may be stored in a Script Variable, the third line would look like this:

var value = exampleSVar.readDataInt32();

This line of code reads the Script Variable and assigns its data to the normal variable value. The readDataInt32() function is one of several readData functions that you can use (see below for a list) to access data in a Script Variable. In general, you want to use the function that reads the correct data type of whatever was stored in the Script Variable.

Writing data to a Script Variable

If you are writing data to a Script Variable, your third line would instead look like this:

exampleSVar.writeDataInt32(5);

In this example, we wrote the number 5 as an integer to the Script Variable. Just like the readData functions, there is a corresponding writeData function (also listed below) for every data type. Every time you write data to a Script Variable, it overwrites whatever was previously stored in it, regardless if it was a different data type.

Full examples

Now, we will demonstrate using Script Variables in a CO script. Be sure to read every example carefully!

Example 1: Writing data to the Script Variable

this.startOfTurn = function(co, map)
{
    var variables = co.getVariables(); // Assigns a reference to "variables"
    var exampleSVar = variables.createVariable("Test"); // Accesses the Script Variable named "Test" via the reference
    exampleSVar.writeDataInt32(5); // Writes 5 to the Script Variable    
};

In this example, we use the CO's startOfTurn function to write the number 5 to our Script Variable. This means the moment the CO's turn starts, they'll have the number 5 stored in the Script Variable named "Test".


Example 2: Accessing data in the Script Variable and applying bonus firepower accordingly

this.getOffensiveBonus = function(co, attacker, atkPosX, atkPosY,
    defender, defPosX, defPosY, isDefender, action, luckMode, map)
{
    var variables = co.getVariables(); // Assigns a reference to "variables"
    var exampleSVar = variables.createVariable("Test"); // Accesses the Script Variable named "Test" via the reference
    var value = exampleSVar.readDataInt32(); // Reads and assigns the stored value to the variable "value"
    
    if (value < 5) // If "value" is less than 5
    {
        return 30; // Return 30% bonus firepower
    }
    return 0; // Otherwise, return 0% bonus firepower by default.
};

Here, we access the data in our Script Variable from the CO's getOffensiveBonus function. We then assign that data to the variable value, and use it in an if condition to apply firepower accordingly.

But now that we've shown you the basic setup of Script Variables, you might have noticed something... the utter pointlessness of our example. You see, in our example, at the start of every turn, the CO will always assign the number 5 to the Script Variable "Test". Since we have the firepower bonus apply only if that value is less than 5, it means our CO never gets that 30% firepower boost. Which leads us to the next example...

Example 3: Increments; accessing the Script Variable and writing to it

this.startOfTurn = function(co, map)
{
    var variables = co.getVariables(); // Assigns a reference to "variables"
    var exampleSVar = variables.createVariable("Test"); // Accesses the Script Variable named "Test" via the reference
    var value = exampleSVar.readDataInt32(); // Reads and assigns the stored value to the variable "value"

    value = value + 1; // Increases value by 1
    exampleSVar.writeDataInt32(value); // Writes the new value to the Script Variable   
};

Instead of applying a static value to the Script Variable every turn like in Example 1, we can do this to gradually increase the value at the start of each turn. Now, our CO will get their 30% firepower boost every turn until the 5th turn.

createVariable() vs getVariable()

As already mentioned above, getVariable() is faster performance-wise, but it doesn't account for Script Variables that may not have already been created yet.

Take a look at Example 1 once again. It might seem pointless, but it's worth mentioning that our CO can indeed get that 30% firepower boost even if we never made the changes demonstrated in Example 3.

In our example, our CO will assign a value to that Script Variable only at the start of their turn. If they happen to not be player 1 and has a unit attacked before their first turn, then yes, they'll counter-attack with 30% more firepower. This is because in our CO's getOffensiveBonus function as demonstrated in Example 2, we used createVariable() instead of getVariable(). The former creates a Script Variable if it didn't already exist, and in doing so, assigns a default value to it. Since we are accessing our Script Variable with readDataInt32(), the default value will be 0, and 0 is less than 5. Had we used getVariable() instead, we would have gotten an error unless the Script Variable already exists.

List of writeData/readData functions

The following is a list of functions you can use to read from or write data to Script Variables.

  • writeDataInt32() / readDataInt32() - Signed 32-bit integer. Default value is 0.
  • writeDataUint32() / readDataUint32() - Unsigned 32-bit integer. Default value is 0.
  • writeDataString() / readDataString() - A text string. Default value is an empty string ("").
  • writeDataFloat() / readDataFloat() - Floating point number. Default value is 0.
  • writeDataBool() / readDataBool() - A boolean. Default value is false.
  • writeDataListInt32() / readDataListInt32() - An array/list containing only signed 32-bit integers. Default value is an empty array ([]).
  • writeDataListString() / readDataListString() - An array/list containing only strings. Default value is an empty array ([]).