Introduction
This documentation covers how the Small scripting system is implemented in the Eternity
Engine and how it can be used. This is not a general reference or tutorial for the Small
scripting language; see the other documentation on the Eternity Engine webpage for more
information.
Return to Table of Contents
VMs: Gamescript and Levelscript
The Eternity Engine contains two Small virtual machines, known as the Gamescript and
Levelscript. Both of these and the ways in which they can interact are explained in the
subsections below.
Return to Table of Contents
The Gamescript
The Gamescript is an optional set of global scripts which can be invoked at any time during
execution. These scripts are shared between levels, and as such, this VM can act as "glue" to
connect the scripts of individual maps. Levelscripts are not required for a Gamescript to
be loaded.
Return to Table of Contents
Adding a Gamescript
The Gamescript is a normally compiled Small AMX file inserted into the GAMESCR lump in any
wad. Only the last such GAMESCR lump will be loaded, and the functions and variables inside
it will become available. The Gamescript area is initialized at startup, and if it contains
an OnInit() function, that function will be executed once and only once when the
"A_InitGameScript" message appears in the console. The OnInit() function is optional, and
if it does not exist, no error will occur.
Return to Table of Contents
Invoking Gamescripts
Here are the various ways Gamescript public functions (aka scripts) may be invoked:
Using Gamescript Variables
Like any compiled Small program, the Gamescript may contain scalar global variables
declared as "public." These variables, aside from being normally accessable from any
function within the Gamescript, can also be accessed from outside by using the
_GetGameVar and
_SetGameVar functions. Using these functions
in your Levelscripts can allow maps to affect each other, by having one map set a variable
in the Gamescript, and then having another one check it. This is analogous to game and
hub variables in ACS and FraggleScript.
Return to Table of Contents
The Levelscript
The Levelscript is an optional set of map-local scripts which can be invoked only while the
map which owns those scripts is being played. A Gamescript is not required for Levelscripts
to be loaded. Levelscripts cannot access the scripts of other levels, but they can access
public functions and variables of the Gamescript, and the Gamescript can access public
functions and variables of the currently loaded Levelscript.
Return to Table of Contents
Adding a Levelscript
The Levelscript is a normally compiled Small AMX file inserted into any lump. The lump must
be attached to the map using MapInfo. The "levelscript"
value for the map must be set to the name of the lump containing the compiled scripts for
that level. The Levelscript area is initialized during level setup, and if the currently
loaded Levelscript contains an OnInit() function, that function will be executed once and only
once, provided a save game is not being loaded. The OnInit() function is optional, and if it
does not exist, no error will occur.
Return to Table of Contents
Invoking Levelscripts
Here are the various ways Levelscript public functions (aka scripts) may be invoked:
Using Levelscript Variables
Like any compiled Small program, the Levelscript may contain scalar global variables
declared as "public." These variables, aside from being normally accessable from any
function within the Levelscript, can also be accessed from outside by using the
_GetLevelVar and
_SetLevelVar functions. Using these functions
in your Gamescripts can allow the Gamescript to perform similar actions on many
levels. Note that if a variable is not defined in a particular Levelscript, the Gamescript
executing _GetLevelVar or _SetLevelVar will abort with an error message. The variable must be
defined in each Levelscript in which the Gamescript may attempt to access it.
Return to Table of Contents
Savegame Semantics
The following subsections contain information on how the Small system behaves when the
game is saved or loaded.
Return to Table of Contents
The OnInit Function
In the Gamescript, the OnInit function is executed only once at program startup, and therefore
this is not affected by saving or loading games. When a game is loaded, it can be assumed that
the Gamescript OnInit function has already been executed.
In the Levelscript, the OnInit function is executed each time the level is loaded from scratch.
However, if the level is being initialized during savegame loading, the OnInit function will
NOT be executed, as it is expected that the program state created by it was preserved in the
savegame. Executing it again in that case could create duplicate objects, show unnecessary
messages, etc. Be sure that your OnInit function's changes to the map are saveable or are not
necessary to be repeated after loading a saved game.
Return to Table of Contents
Global Variables
Global variables declared in both VMs, public or private, will have their values saved in
save games. This means that when a normal game loading action takes place, the values of
global variables in both VMs will instantly change to reflect the state that was in place at
the time of the save.
Return to Table of Contents
Static Local Variables
Static local variables are variables declared inside functions using the static keyword
as opposed to the new keyword. As mentioned in the Small language documentation, static
local variables, unlike normal local variables, retain their values between calls to the
function in which they are declared. Because static locals are really just limited-scope
globals, they are treated the same way, and their values will be saved in savegames. When a
normal game loading action takes place, the values of all static local variables in both VMs
will instantly change to reflect the state that was in place at the time of the save.
Normal local variables are the only storage class of variable that is not archived in save
games. In addition, the status of the Small stack and heap are also not currently saved, since
Eternity does not allow script execution to be interrupted by a save game under any circumstance.
Return to Table of Contents
Callbacks
Callbacks currently scheduled for either VM will be saved in save games. At the time of a normal
load action, any existing callbacks in either VM will be instantly destroyed and will be replaced
with the callbacks which were scheduled at the time of the save.
Return to Table of Contents
Load Errors
The following fatal errors may occur while loading a savegame which contains script data under
the given circumstances. Eternity will currently exit if these errors occur.
System-Defined Event Handlers
Complete documentation of all system-defined event handlers is below. System-defined event
handlers are optional functions that you can provide in your script that will be started as
callback scripts by the game engine in response to internal events. If the functions do not
exist, no calls will be issued.
Return to Table of Contents
OnInit
Required Prototype: public OnInit();
Can Be Defined In: Gamescript, Levelscript
The OnInit function is called when its corresponding virtual machine is initialized. For the
Gamescript, the OnInit function is executed only once at program startup. In the Levelscript,
the OnInit function is executed each time the level is loaded from scratch, NOT including when
a savegame is being loaded.
Return to Table of Contents
OnHUDStart
Required Prototype: public OnHUDStart();
Can Be Defined In: Gamescript, Levelscript
OnHUDStart will be called first in the Gamescript and then in the Levelscript, if defined in
either or both. It is called whenever a new level is started, or when the player being
displayed by the game engine changes. Because text widgets are cleared by default, you may
want to set new values to them in this function. You may also use it to maintain the internal
state of your scripts with respect to the HUD.
Return to Table of Contents
OnHUDPreDraw
Required Prototype: public OnHUDPreDraw();
Can Be Defined In: Gamescript, Levelscript
OnHUDPreDraw will be called first in the Gamescript and then in the Levelscript, if defined in
either or both. It is called once per frame after HUD widgets from the previous frame have
been erased, but before drawing of widgets for the current frame has begun. This is the safest
time to alter the properties of HUD widgets. Altering properties such as location or graphic
being shown at any other time may result in visual artifacts. Call functions such as
_MoveWidget from this event handler.
Return to Table of Contents
Eternity Small Headers
This section lists the standard headers provided with the Eternity Small compiler
distribution. These headers will be automatically included by the compiler, and so it
is not necessary (although not an error) to include them explicitly.
Reserved Identifiers
The following function, definition, and constant names are explicitly reserved by the Eternity
Engine and should not be used by user script functions or constants. Doing so may cause
your scripts to not compile with future versions of the engine.
Note: The syntax [<character class>]* means zero or more of the characters within the
class indicated inside the brackets. Programmers should recognize this syntax as a regular
expression.