Constants are named values just like variables, except constants never change while the engine is running (hence the name). Constants provide a way to give any value a human readable label without using memory to store it as a variable. They are highly valuable for lists of static values, and as a tool for making code easier to read.
OpenBOR relies heavily on constants. Nearly every list of items, properties, or values is comprised of named constants. OpenBOR script also enables creators to define their own constants.
Predefined
There are innumerable predefined constants used by the OpenBOR engine. Constants exposed for script use are accessible with the openborconstant(char <name>)
function. Constant names are strings, so enclose them in quotes.
Get the ANI_IDLE constant value:
int i = openborconstant("ANI_IDLE");
Optimizing
It is very important to use openborconstant()
as documented. This is because openborconstant()
is an expensive function requiring a lengthy internal string search. However, if written correctly OpenBOR can completely eliminate the in game CPU load by pre-processing openborconstant()
calls. See the following examples:
Incorrect
char animation_name = "ANI_IDLE"
int i = openborconstant(animation_name);
Correct
int i = openborconstant("ANI_IDLE");
In most other functions, the incorrect example is best practice. But openborconstant()
is unique. Assuming you provide the name argument directly as in correct example, the openborconstant()
function is processed as the module loads. It essentially becomes a “free” function that costs no memory or CPU time at all. In the incorrect example, the engine has no way to know what the constant argument is until the parent function runs. Consider the following practical example, performing an animation switch:
Function
void do_something_cool(char animation_name, int special_number)
{
...do some other stuff...
// Change animation.
performattack(entity, openborconstant(animation_name + special_number), 1);
}
Model text
@cmd do_something_cool "ANI_FREESPECIAL" 1
The above code is a common misuse of openborconstant()
. It will work, but it is unnecessarily expensive. There is a pointless string concatenation and the engine is unable to process openborconstant()
until the moment it runs. Try a more optimal approach like this:
Function
void do_something_cool(int animation_id)
{
...do some other stuff...
// Change animation.
performattack(entity, animation_id, 1);
}
Model text
@cmd do_something_cool openborconstant("ANI_FREESPECIAL")
This code eliminates the string concatenation and allows OpenBOR to process openborconstant()
into the actual constant value during engine start up. When the animation function runs, it simply receives an animation ID and acts on it without wasting any resources on extra calculations.
User Defined
OpenBOR script supports the #define directive, enabling user defined macros and constants. A define comprises three parts:
- Definition: Always “#define”.
- Identification: This is the name of your macro (in this case, the constant).
- Token: The value. This is what the computer will interpret whenever the constant is encountered in code.
#define SOME_IDENTIFICATION somevalue
Once defined, the constant is available through the entirety of the script’s scope. In the case of animation scripts, the constant becomes available within the model’s text for use with @script and @cmd. You do not need a function to access a user defined constant. On startup, OpenBOR replaces all instance of the constant’s identifier with its defined value.
#define SOME_IDENTIFICATION somevalue