Totem Script
Totem Script is a shell-like scripting language used in FUEL. Most of the textual game files are Totem Script scripts. Two of the extensions used for Totem Script are .tsc
(Totem Script) and .pc
in the trtext
directory. In addition to being used in game files, the language is used in the in-game console and programmatically throughout the game executable. Each line of a Totem Script file is executed sequentially. If a line fails to execute then it is ignored and execution continues with the next line. Whitespace is ignored.
Command arguments have two types. The first type is a numeric argument. Numeric arguments are backed by a float value but in practice they are used as integers, booleans, and floats. The second type is a string argument. String arguments are unsurprisingly backed by a C-string value.
Text Editor Extensions
Command Names
All command names are case insensitive. Only the first 15
capital letters and numbers in each command name are required, this is called the “short form command name” and it is also case insensitive. However, I recommend using the full command name in scripts for readability.
See the Commands documentation entry for a list of commands available in FUEL.
Directives
Directives are like commands built into the script evaluator instead of registered by the game. All directives are case insensitive. Directives are only available when executing a script file, so they cannot be used from the in-game console.
#set name
Sets a variable.
#define name
Alias for #set
.
#unset name
Unsets a variable.
#if expression
If the expression evaluates as true then this block is executed. Otherwise, it is skipped.
An expression is a sequence of one or more variable names separated by the conditional operators ||
(Binary OR) and &&
(Binary AND). If a variable name is set then it evaluates as true. Otherwise, it evaluates as false. Note that the expression is not escaped or quoted in any way. For example, #if CD_MAKE_BF || CD_VERSION
will be satisfied when either CD_MAKE_BF
, CD_VERSION
, or both are set. But it will not be satisfied if neither are set.
Rather than having operator prescience, the expression is evaluated left to right with no operator prescience. For example, while you might expect the expression name1 || name2 && name3 || name4
to be evaluated as ((name1 || name2) && (name3 || name4))
it is actually evaluated as (((name1 || name2) && name3) || name4)
. Note that parentheses are not supported in expressions, they are only used here to illustrate the order of operations. Also, the conditional expressions do not have short circuit evaluation, not that this matters since there are no side effects.
#ifdef expression
Alias for #if
.
#ifnot expression
Equivalent to #if
except that it is satisfied when the expression evaluates as false.
#ifndef expression
Alias for #ifnot
.
#else
If the matching #if
, #ifdef
, #ifnot
, or #ifndef
was unsatisfied, then this block is executed. Otherwise, it is skipped.
#endif
Close the matching #if
, #ifdef
, #ifnot
, #ifndef
, or #else
block and resume unconditional execution.
Constants
All constants are case insensitive. While these constants change the numeric value, the string value will remain unchanged. Some commands will check for string values of “OFF” or “ON” independently of the command evaluator. In this case the argument must match exactly since the string value is being checked and not the numeric value.
true
Evaluates to a numeric argument of value 1.
false
Evaluates to a numeric argument of value 0.
on
Evaluates to a numeric argument of value 1.
off
Evaluates to a numeric argument of value 0.
Numeric Values
Integer, boolean, and float values can be used as arguments to commands. Integer and float values must be expressed in base 10 since there is no special handling for other bases. Boolean values can be expressed using the constants or numerically. A value of 0
represents false while any non-zero value represents true.
String Values
For basic strings with no whitespace, quotes, or backslashes, the string can be given as an argument verbatim, unquoted. For complex strings, a C-style string literal can be supplied as an argument to commands. A string literal is a sequence of characters enclosed by two "
s. To escape a "
in a string literal use \"
. Likewise, a \
can be escaped by using \\
. Rather than splitting on the spaces, the entire string will be given as one argument. This is useful when you want to pass a command an argument with spaces in it.
Arguments
%index
When a script file is invoked with the BSource
command, tokens of the form %index
will be replaced with the argument to BSource
at index index
. For example if the command-line BSource UserGame.tsc Story Story
was run, %0
would be replaced with the name of the script (UserGame.tsc
) and %1
would be replace with the first argument to BSource
following the script name (Story
), and so on. Nested calls to BSource
are handled appropriately using a stack.
Limitations
The number of usable characters in a buffer is 1
less than the length of the buffer to leave room for the null terminator. The buffer length for each line is 2048 characters. The buffer length for the command name is 1024 characters. The buffer length for the short form command name is 16 characters. Registered commands are stored in a linked list and thus there is no limitation on the number of registered commands. The buffer length for each argument is 1024 characters. The buffer length for variable names is 32 characters. There can be at most 32 variables set at any one time. A command can have at most 32 arguments including the name. Since integer and float arguments are backed by 32-bit floating point values they are subject to the limitations imposed the underlying data type.
Additionally, an eagle eyed reader will have noticed that Totem Script only supports sequential and conditional execution, and not iterative execution. This means that there are no loops, so if you want to run a command multiple times then you need to copy and paste it that many times or fall back to a higher level environment and execute the commands from there. You will almost never need to do this so it is an excusable omission from the language.
Comments
Totem Script supports C-style comments
//
Single line comment. Ignore all characters until the end of the line.
/*
Begin multi-line comment. Ignore all characters until the end multi-line comment sequence.
*/
End multi-line comment.