Creating a Single Player Mission

Variables (5.7)

Integers

In general, variables are very useful. They let you store information or the state of the game in various ways. Most often though, you'll simply use them for communicating information between teams. There are three kinds of variables to use: Integers, floats, and strings. Let's start off with the simplest: integers. To create an integer variable, use an action statement with this command:

  Action()
  {
    CreateVarInteger("@.[var name]", [initial value], [lower bounds], [upper bounds]);
  }

This will create an integer variable. Integers store a whole number, either positive or negative. These can be used to count things, but more often then not you will be using them as a "pseudo-boolean" when nothing else will fit the situation.

A variable created this way will have two parts to its reference name. The first part is simply the name of the team that created it; That is, the team running the objective. "[var name]" is the second half of the name. So for example, the team "Team3" would create a var named "@Team3.counter". Variables can only have TWO periods in the name, no more (i.e. @.ab.bc-cd will work, but @.ab.bc.cd will not).

The "[initial value]" is the value the variable starts at. For integers, this is 0 by default. "[lower bounds]" and "[upper bounds]" are the lowest and highest values a variable can reach via operation. Integers are stored internally as a signed 32-bit value: In layman's terms, that means the default upper and lower bounds are 2,147,483,647 and -2,147,483,648 respectively, much more than you should ever need to work with.

So for example, if you wanted an integer that starts at 5 and is clamped to the values -5 to 20, you would use a command like this:

  Action()
  {
    CreateVarInteger("@.counter", 5, -5, 20);
  }

The initial value and both bounds can be omitted as well, so in this example:

  Action()
  {
    CreateVarInteger("@.myvar");
  }

You would create a integer called "myvar" which starts out as 0, and can increase or decrease as much as needed.

Floats

Floats, like Integers, store a number. They have a decimal component, and are most often used for timers. To create a float, you would use the following command:

  Action()
  {
    CreateVarFloat("@.[var name]", [initial value], [lower bounds], [upper bounds]);
  }

Like with integers, when creating a float you may choose to exclude an intial value and/or bounds.

Strings

While integers and floats deal with numbers, a string variable will store a string of characters. That is, it will store a line of text. Strings are almost exclusively used to deal with interface elements; Their most common use case is to associate a game message with them. This will make a game messages that prints the content of the string, which can be updated according to the game state. Creating a string uses the following command:

  Action()
  {
    CreateVarString("@.[var name]", "[initial value]");
  }

Unlike the previous two variables, strings do not have a default value, and also do not have upper or lower bounds. Also, unlike integers and floats, a string's value MUST always be enclosed by "" quotation marks.

Performing Arithmetic

When you create a var, it will stay at it's default value forever until you perform an operation on it. To do this, you will use the Op() command.

  Action()
  {
    Op("@.[var name]", "[operation]", [new value]);
  }

"[var name]" is the name of the var you are changing. The "[operation]" in the middle is the mathematical operation you want to perform. And the "[new value]" is the second term of your equation.

There are several different operations to perform on variables.

OperationCode Symbol
Assignment=
Addition+
Subtraction-
Multiplication*
Division/
Modulus%
Bitwise OR|
Bitwise AND&
Bitwise Exclusive OR^

Let's take a look at some examples. The first operation "Assignment" is fairly straight forward. It will take the variable you specify, then assign its value to the "[new value]", regardless of whatever the variable's previous value was.

  Action()
  {
    Op("@.numunits", "=", 20);
  }

So in this case, we set the variable "@.numunits" to be 20.

The next few operations are pretty self explanatory in what they do. Addition and subtraction can increment and decrement variables by a given amount, and multiplication and division do their respective thing. So another exmaple:

  Action()
  {
    Op("@.score", "*", 2);
  }

Here, we take the variable "@.score" and multiply it by 2, doubling it.

Arithmetic can also be performed on float variables. They use the same syntax, and support decimals too. This example will increment the "@.floatvar" var by 7.25.

  Action()
  {
    Op("@.floatvar", "+", 7.25);
  }

Note that string variables do not support arithmetic. Only the assignment operation can be performed on them. Also, you must enclose the "[new value]" in "" quotation marks.

  Action()
  {
    Op("@.locname", "=", "Location A");
  }

Lastly, you can substitute the "[new value]" with the name of another variable. You can use this to add two variables together, or dynamically change a multiplier for example.

  Action()
  {
    Op("@.var1", "+", "@.var2");
  }

This will add the amount of "@.var2" to "@.var1". Don't forget that this will change the value of @.var1, meaning performing this operation a second time will yield a different result!

Using Variables

Once you've created a variable, there are several ways to utilize them. The most common way you'll be using is as a conditional.

CreateObjectType("[objective name]"), "Objective")
{
  Condition("If", "@.[var name]", "[operator]", [value]);
  Action()
  {
    [action];
  }
}

The "If" condition is a versatile method of testing variables, and is structured very similarly to the Op() command. It will perform a comparison between a given variable and a value depending on its operator. The "[var name]" is the variable you are testing. It can be any variable, including strings. The "[operator]" in the middle is the relational operator you want to use, and the "[value]" is the value you want to test the variable against.

A list of operators can bee seen here.

OperatorCode Symbol
Greater than>
Less than<
Equal to==
NOT Equal to!=
Greater than OR Equal to>=
Less than OR Equal to<=

CreateObjectType("[objective name]"), "Objective")
{
  Condition("If", "@.kills", ">", 99);
  Action()
  {
    [action];
  }
}

In this example, we grab the variable named "@.kills" and test whether it is greater than 99. If it is, then the condition becomes true and the Action() statement is executed. Remember, if the condition is not true, then it will remain dormant until it does become true.

You can also compare a variables to another variable. So in this example:

CreateObjectType("[objective name]"), "Objective")
{
  Condition("If", "@.kills", "<", "@.loses");
  Action()
  {
    [action];
  }
}

We test if the "@.kills" variable becomes less than the value of the "@.loses" variable.

Floats and strings can also be compared to each other in this way. However, different variable types cannot be compared to each other, so for example you can't test an integer against a float, or vice versa. Also, string variables only support "Equal to" and "NOT Equal to" comparisons.

There is also a way to tie a float variable to a timer. When using a "Timer" condition, you can specify the name of a float to use:

CreateObjectType("objective_countdown", "Objective")
{
  Condition("Timer")
  {
    Time(300);
    Var("@.timeleft");
  }

  Action()
  {
    [action];
  }
}

In this example, the Timer will begin at 300 seconds (five minutes) and while counting down, and will keep the variable named "@.timeleft" updated to the current time left. Doing this, you can then create objectives that will become true once the timer reaches a specific value. So for example, this objective will become true once the timer from objective_countdown reaches 150 seconds (two and a half minutes) or below:

CreateObjectType("objective_halftime"), "Objective")
{
  Condition("If", "@.timeleft", "<=", 150);
  Action()
  {
    [action];
  }
}

Also, by tying a timer condition to a variable, you can then display that variable on screen. This will let you show the player how much time remains for the timer in real time. Note that tying a variable to a timer condition alone is not enough to get a timer to display onscreen. For that, you'll need to define the interface element. See Section 7.1: Mods and Rulesets - Getting Started for more information.

There is one more way to test a variable with an objective. When using an "If" condition, the objective remains dormant until the condition becomes true or is abandoned. That, and every command in the action statement is executed. One way to get around this is to have a timer objective that chains into several if objectives. Alternatively, you can use a simple If() statement in the action statement itself.

CreateObjectType("[objective name]", "Objective")
{
  Condition("Timer")
  {
    Time(15);
  }

  Action()
  {
    If("@.tankilled", ">", 5)
    {
      [action];
    }
    Else()
    {
      [action];
    }
  }
}

Just like with the conditional method, this will test a variable. Here, we are testing if the @.tankilled variable is greater than 5. If it is, we execute the actions under the If statement's brackets. Otherwise, execute the actions under the Else() statement. This method is helpful for directly branching your objectives without having to chain multiple objectives together to utilize different conditions. In the example, the integer is tested after 15 seconds have passed, and this will happen only once and only requires a single objective!