Variables and Arrays

Variables store numbers. The engine uses predefined variables that can be set by functions to change global parameters, such as the background color; you'll find a list of these predefined variables in this manual. For defining your own variables and giving them initial values, use the following declaration:

var name;	// uninitialized variable
var name = number; // initialized variable

This declaration creates a variable of type var with the given name. The name can contain up to 30 characters, and must begin with A..Z, a..z, or an underscore _ . Like all other objects, variables must never have names that are already used otherwise, like red, green, blue, x, y, z, pan, tilt, roll and so on. Example:

var test; //  declare variable "test"
var enemy = 5; // declare  variable "enemy" and assign the value 5 

 LC  In lite-C, also also constant expressions and defines can be assigned to variables. Example:

#define SIZE 100
...
var smaller_size = SIZE/2; // assign the value 50 

 !!  Be careful when assigning constant expressions to variables. If the constant expression only contains integers (numbers without decimals), the result is also rounded down to an integer. For instance, the constant (99/2) is 49, but (99.0/2.0) is 49.5. Likewise, the constant 1.0/2 is 0.5, but 1/2 is 0!

Variables can be redefined at any place within the script. Only the last definition is used, for instance:

var v1 = 7;
... 
var v1 = 13;
creates the variable v1 with an initial value of 13. However, variables can not be redefined to a different type, or a different array length; and in lite-C engine variables can not be redefined.

In C-Script, all uninitialized variables are automatically initialized to 0. This comes at a performance penalty for local variables,  LC  so in lite-C autoinitialization of local variables is optional and can be switched on with the PRAGMA_ZERO definition:

#define PRAGMA_ZERO   // initialize variables

If this line is added at the beginning of the script, all uninitialized local variables are automatically initialized to zero. Function calls are a little slower then.

Variable types

Computers always perform their calculations with finite accuracy, so all normal variable types are limited in precision and range. The "workhorse"of the lite-C language is the general purpose var variable that can store numbers, pointers, or handles. Numbers are stored in fixed point format in the range of -999999.999..+999999.999 with a minimum of 0.001. Unlike floating point variables, which have low precision with bigger numbers, var variables keep their precision over their whole range and thus are better suited for coordinates in a virtual world. Therefore they are used for 3D coordinates, angles, and all other properties of engine objects. You can also realize counters and boolean operations with var variables, which would not be possible with floating point variables.

 !!  All var advantages come at a price however: due to their minimum step width of 0.001, be careful when calculating very large or very small values with them. For instance, a multiplication by 100 has an inaccuracy of 0.001/100 = 0.001%, while the result of a division by 0.01 - mathematically the same - is inaccurate by 0.001/0.01 = 10%!

 LC  lite-C additionally supports standard C/C++ integer or floating point variables for cases where you need a higher range with less precision, or higher precision with small numbers:

Type Size Range Minimum Precision*
var, fixed 4 bytes -1048577.999 to 1048576.999** 0.001 ~9
int, long 4 bytes -2147483648 to 2147483647 1 ~10
short 2 bytes 0 to 65535 1 ~4
char 1 byte 0 to 255 1 ~2
float 4 bytes -3.4·1038 to 3.4·1038 1.2·10-38 ~6
double 8 bytes -1.8·10308 to 1.8·10308 2.2·10-308 ~14

*  in decimal digits.
** also often referred to in this manual as -999999.999 to +999999.999, which is easier to memorize.

Integer constants in the program - such as character constants ('A'), integer numeric constants (12345) or hexadecimal constants (0xabcd) are treated as int. Constants containing a decimal point (123.456) are treated as float. Therefore, when you directly enter numbers in the script, they have a precision of only about 6 decimal digits even when you assign them to double variable.

Cast operators

Variables are normally automatically converted to another type. So you can assign float or int variables to var parameters or vice versa without having to care about type conversion. However, sometimes you'll need to convert expressions or variables when the conversion is not obvious - for instance when calling an overloaded function that accepts several variable types. In this case you can enforce a type conversion with a cast operator. A cast (or typecast) operator is the target variable type in parentheses placed before the expression or variable to be converted. Example:
float fx = 123.456;
printf("The value of fx is: %.3f",(double)fx); // &f expects the "double" variable type 

Global, local, and static variables

Normally, variables are defined outside functions. They are called global variablesand are accessible by all functions. Alternatively, var definitions can also be placed inside functions. This creates a local variable. Local variables are only valid within the scope of the function - they are unknown outside. If a global variable with the same name as a local variable exists, the local variable has priority inseide it's function. Example:
function  beep_seven_times()
{
  var i = 0; // define and  initialize a local variable
  while (i  < 7)
  {
    i += 1;
    beep();
    wait(1); //  local variables keep their value during wait()
  }
}                                                                                  

If many instances of the same function are running, which is normally the case with entity actions, each instance uses its own independent set of local variables. We recommend to define local variables at the beginning of the function.

 LC  In lite-C a local variable can be declared as static. It is then treated as a global variable even if it is declared within a function, and keeps its content when the function terminates or when another instance of the function is called. This means that it is initialized only the first time the function is called. Example:

function foo() 
{
  static var initialized = 0;
  if (!initialized) { initialize(); } // initialize only once
  initialized = 1;
  ...
}

 !!  Be careful when calling other functions and passing non-static local variables as arguments. Because local variables only exist within the scope of the calling function, the arguments become invalid as soon as the calling function terminates by return or wait().

In C-Script, local variables caused a performance penalty and could not be used for particle functions. This restriction does not apply for lite-C (but local variables are not preserved between frames in a particle function).

Arrays

If you group several variables together, you have an array:
var name[n]; // uninitialized array
var name[n] = { value_1, value_2, ... value_n }// initialized global array
This creates a variable that contains n numbers, and optionally gives them default values as in the second line. Note the winged brackets { } that must surround the set of default values in lite-C, C, or C++ (but not in C-Script). Such a multi-number variable is called an array. The number n is called the length or the dimension of the array. Example:
var my_array[5] = { 0, 10, 20, 30, 40 }; 

This creates an array of 5 numbers that can be accessed in expressions through my_array[0]...my_array[4]. In the expression the number in the [ ] brackets - the index - tells which one of the 5 numbers of the array is meant. Note that there is no my_array[5], as the index starts with 0. The advantage of using an array, compared to defining single variables, is that any numeric expression also can be given as index. Example:

var i;
for (i=0; i<5; i++) 
{
   my_array[i] = i; // sets the array to 0,1,2,3,... etc.
}

Care must be taken that the index never exceeds its maximum value, 4 in this example. Otherwise an error message will be issued or an engine crash can happen.

In C-Script, arrays can also be defined locally like local variables, but only with the dimension 3. Local arrays and variables can not be passed as a '&' vector parameter to other functions, except for engine functions. There is no such limitation in lite-C.

 !!  Array initialization in the array definition has several restrictions: It is not supported for structs, for arrays that contain something other than numbers, and for several arrays defined together in a single logical line. Initializing local arrays makes them static (see above), meaning that they keep their previous values when the function is called the next time. For initializing them every time the function is called, explicitely set them to their initial values, like this:

function foo()
{
  var my_vector[3];
  my_vector[0] = 10;
  my_vector[1] = 20;
  my_vector[2] = 30;
  ...
  static var my_static[3] = { 1, 2, 3 }; // lite-C: initializing local arrays makes them static 
  ...
} 

An array of length 3 is often used for vectors, positions, angles, or colors (see below). Arrays may have any length, but a maximum of 500 initial values can be given in a C-Script file. If you need more, have the values in a separate text file which you use to fill the array through file_.. instructions. There is no limit of initial values in lite-C.

 !!  Be careful when defining huge local arrays. All local variables are stored on a special memory area called the stack. This area has a limited size that depends on where your function is running and whether it's called by other functions. Exceeding the stack size causes any program to crash . Thus, when you need huge local arrays of ten thousands of variables, or when you want to determine the array size dynamically, use the sys_malloc / sys_free method.

Multidimensional arrays can be defined by multiplying the index by the array width. Suppose you need an array in two dimensions, like a 10*20 grid of height values. It is defined this way:

var heightmap[200]; // 200 =  10*20

The array value at position (j,i) can then be accessed through:

heightmap[j*20 + i] = 10; // j = 0..9, i = 0..19

 LC  In lite-C, you can alternatively define (uninitialized) and address multidimensional arrays by using several indices:

var heightmap[10][20];
...
heightmap[j][i] = 10; // j = 0..9, i = 0..19
C-Script supports arrays for variables as well as for STRING pointers within a TEXT object. lite-C supports arrays for any type of variables or pointers.

typedef

 LC  In lite-C you can define your own variable types with typedef statements. Example;
typedef long DWORD;
typedef char byte;

...

DWORD dwFlags;
byte mypixel; 
typedef can be used to redefine variables and structs; it can not be used for arrays and predefined engine objects.

Saving and loading variables

With special variable definitions the variable behavior on saving or loading a game can be determined:
var_info name; // C-Script: define var_info 
var name_i;    // lite-C: append _i to the variable name

Creates a variable or an array that is saved when SV_INFO is set for a game_save instruction. Info variables are suited for user-settings like volume or screen resolution that are supposed to be loaded at game start, and must not change when loading a previously saved game.

var_nsave name; // C-Script: define var_nsave 
var name_n;     // lite-C: append _n to the variable name

This variable is never saved. Use this type of variables, for instance, to store DLL handles and sound handles that must not be overwritten by a game_load instruction.

Coordinate system

Predefined vectors are used for coordinates, angles, or colors. In the virtual world we have a right-handed XYZ coordinate system with the Z-axis standing upright. In the 2-D case, for positioning something on the screen or within a bitmap, we use a XY coordinate system in pixel units, with the Y-axis pointing downwards and the origin in the upper left corner.

Space and time units of the virtual world are the quant and the tick. One quant is one unit in WED and MED coordinates, and therefore one texture pixel at a 1.0 scale. How much inches a quant shall be depends on the relative size of the models. We recommend one inch per quant for person based games (shooters or adventures), and 4 inches per quant for vehicle based games (war games or flight simulators). This way with the same level size you get much bigger worlds. One tick is equivalent to 1/16 second - the average time between two frame cycles on a very low-end PC.

Angles are given in degrees (0 to 360) and counted counter-clockwise. For rotations in three dimensions the so-called Euler angles are used: pan is the horizontal angle (0..360) about the upright Z axis, tilt is the vertical angle (-90..+90) about the rotated Y axis, and roll is the angle (0..360) about the rotated and tilted X axis. For a pan angle, 0 degrees is equivalent to the positive direction of the X-axis coordinate, which points to the east of the map. 90 degrees is north, 180 degrees west, and 270 degrees south.

Colors are given as blue, green, red component values between 0 and 255. All component values set to 0 gives black; all set to 255 gives white. The maximum color value of 255 must not be exceeded. The color order in a color vector is blue-green-red.

See also:

Strings, pointers, structs, functions

 

► latest version online