.;oOXNWWXOd;
    .:x0000KXNWWWWWXx;
  .oK000OOOO0XXWWNNWNXKl
 ;O000O.        ..,xWNNNX;                                                 TM
cXXNXKX.   ,ddd,    xNWMWN,     xxx:   :xxx.                     xxxxxdl'
XWNNNNW.   'ddo,   .kXNWKkl'   .MMNW. .WXNM.   .,,.      ',,.   .MM;'.,dMx
WWWWWWW.         .cO0K0. ;lkMd .MMlM0 xM;KM. :NKll0Wo  xWkcoXX; .MM.    OM;
KNWWWWW.   :Oo.   'KNNl .ccl0K..MM.OMxWO KM..WX    XM'cMO   .MW..MM.    0M,
:WWWNNX.   cXXK'   .kNx .l:;x: .MM.'MMM' KM. kMd..oMK .XN:.'xMd .MMc;;:kMl
 ;XNXXKc:::xNWWNl;;,,xOd,'do;   ll  ;l:  :l   'cddl,    ,ldoc.   lllllc;.
  .lKWWNNWWWWWNXKK0OOOx;
     ;d0WWMMWWNXK00xc'
        ,d0NNNXKxc'

This documentation was written by GhostlyDeath (ghostlydeath@gmail.com).
ReMooD (C) 2006-2008 GhostlyDeath, 2006-2008 ReMooD Team. The ReMooD Name and Logo are trademarks of GhostlyDeath (ghostlydeath@gmail.com).

Table of Contents

Legacy Script

About

NOTE: Some of this documentation refers to a future version of ReMooD which will be version 0.8a.
Legacy Script is a scripting language for Doom that allows users to define custom actions when players cross lines. It is available for ReMooD, Legacy, Old Versions of Eternity and SMMU. FraggleScript was renamed to Legacy Script because this scripting language emphasizes Legacy more than Eternity since it was removed and also since SMMU is out of date and not much maps were made for it. There are also modifications to the language which are unique to ReMooD.

Legacy Script In ReMooD

ReMooD supports Legacy Legacy Script completely. However there are some differences of the script in this port than in the parent port Legacy. One of those differences that instead of being interpreted on the go, the scripts are all compiled into byte code and executed within the ReMooD Virtual Machine. Existing scripts should still be compatible completely except for a few things.

Compatibility

There have been changes in Legacy Script that may affect scripts.

  • The function runcommand() no longer has the ability to execute any console command. However, an emulation layer is provided for the following commands, anything that isn't on this list will do nothing. Any emulation is virtualized as in they don't really call the real console commands.
    • echo - Prints a line a text.
    • color - Changes the color of the first local player.
    • color2 - Changes the color of the second local player.
    • originalweaponswitch - Changes the weapon preference to classic (ex: EXE).
    • viewheight - Changes the viewheight of the player.
    • turbo - Percent change in speed (200 = 200% speed).
    • respawnitem - Sets whether items respawn or not.
    • respawnitemtime - Sets the amount of time before items respawn.
    • respawnmonsters - Sets whether monsters respawn or not.
    • respawnmonsterstime - Sets the amount of time before items respawn.
    • fastmonsters - Sets the speed of monsters.
    • predictingmonsters - Sets whether monsters will aim ahead of their targets or not.
    • exitlevel - Leaves the current level then goes to the next level.
    • restartlevel - Restarts the current level.
    • chasecam - Sets whether the chasecam is on or off.
    • cam_height - Sets the height of the camera.
    • cam_dist - Sets the distance of the camera.
    • cam_speed - Sets the speed of the camera.
    • skin - Changes the skin of the first local player.
    • skin2 - Changes the skin of the second local player.
    • teamplay - Sets whether teamplay is enabled by color or skin.
    • teamdamage - Sets whether players on the same team can hurt each other.
    • gravity - Sets the amount of gravity in a level.
    • allowjump - Sets whether players can jump or not.
    • allowrocketjump - Sets whether players will gain extra vertical boost from explosions or not.
    • allowautoaim - Sets whether players can autoaim at targets or not.
    • allowturbo - Sets whether players can use turbo or not.
    • allowexitlevel - Sets whether players can exit the level via exit triggers.
    • allowmlook - Sets whether players can look up/down or not.
    • fragsweaponfalling - Sets whether players will drop weapons when they die or not.
    • fraglimit - Sets the amount of frags until the game is won.
    • timelimit - Sets the amount of time before the game ends.
    • say - Says a line (Will be prefixed by "<SCRIPT>").
    • sayto - Says a line to a certain player (Will be prefixed by "<SCRIPT>").
    • sayteam - Says a line to your team (Will be prefixed by "<SCRIPT>").
    • map - Changes the current map.
    • solidcorpse - Sets whether corpses are solid or not.
    • bloodtime - Sets the amount of time blood will last.
    • deathmatch - Sets the current game mode (0 = Cooperative, 1 = DM, 2 = Alt DM and 3 = New DM)
  • The function runcommand() also has these emulated for ReMooD 0.7a and ReMooD 0.7b support.
    • cl1_skin - Alias for skin.
    • cl2_skin - Alias for skin2.
    • cl3_skin - Changes the skin of the third local player.
    • cl4_skin - Changes the skin of the fourth local player.
    • cl1_color - Alias for color.
    • cl2_color - Alias for color2.
    • cl3_color - Changes the color of the third local player.
    • cl4_color - Changes the color of the fourth local player.
    • classicmeleerange - Sets whether monsters will be able to use a melee attack at any vertical distance or not.
    • classicblood - Sets whether blood will act like it does in Vanilla Doom or not.
    • classicmonsterlogic - Sets whether monsters will act like they do in Vanilla Doom or not.
    • spawnmonsters - Sets whether monsters will spawn or not.
  • The functions break(), continue(), return() and goto() are no longer real functions, they are special functions used by the compiler.
  • There is a new type function which points to a function (example: If print() was not constant, it could be reassigned to something else). It is not recommended to attempt to reassign built-in functions or to call symbols that are not functions. It can also contain new code.
  • ReMooD supports parenthetical statements however Doom Legacy may have supported them but were undocumented.

Utilizing Legacy Scripts

Before using Legacy Scripts in your code, you first need to write it then insert it into a level. Once writing is completed, any written scripts are stored in the map header (ex: MAP01, E2M1, etc.. Scripts are placed after [scripts] blocks, anything outside will not be considered a script.

Types

int, hub and const

A standard integer ranging from -2,147,483,648 to 2,147,483,647. If a const is declared, the value cannot be changed and must be initialized. if a hub is declared, the value will be available across levels.

  • Conversion:
    • To fixed - If the value is less than -32,768 then this will be the new value, if the value is greater than 32,767 then this will be the new value. Otherwise, the value will remain the same.
    • To string - The value will be converted to a string format.
    • To mobj - A search will be done for all map objects for a matching id number (ex: 4002 is a Zombieman) and the first match will be returned.
    • To function (ReMooD Only) - A reference lookup will be done, if such a reference is found then it will be mapped to the function. Otherwise, the function will be a NULL function which when executed will stop the script.
Sample Code:
int foo = 100;

fixed

A standard fixed point number ranging from -32,768.65535 to 32,767.65535.

  • Conversion:
    • To int - Anything after the decimal point will be truncated, 5.1 becomes 5, 7.9 becomes 7.
    • To string - The value will be converted to a string format.
    • To mobj - After conversion to an int, a search will be done for all map objects for a matching id number (ex: 4002 is a Zombieman) and the first match will be returned.
    • To function (ReMooD Only) - After conversion to an int, a reference lookup will be done, if such a reference is found then it will be mapped to the function. Otherwise, the function will be a NULL function which when executed will stop the script.
Sample Code:
fixed foo = 10.5;

string

A string of characters terminated by a NULL character.

  • Conversion:
    • To int - The string value will be transformed to an int, if conversion fails the result will be 0.
    • To fixed - The string value will be transformed to a fixed, if conversion fails the result will be 0.
    • To mobj - The string value will be transformed to an int, if conversion fails the result will be 0. Once conversion is done, the rules for int to mobj will be done.
    • To function - A symbolic name lookup will be done, if the symbol name matches a function then it will reference that.
Sample Code:
string foo = "Hello World";

mobj

A reference to an object on the map.

  • Conversion:
    • To int - The reference will be lost and the int will equal -1.
    • To fixed - The reference will be lost and the fixed will equal -1.
    • To string - The string will become "map object".
    • To function (ReMooD Only) - The function will transform into a NULL function, if called the script will stop.
Sample Code:
mobj foo = playerobj(0);

function

A function that executes a set of code. This type is unique to ReMooD and will break compatibility if used in other source ports.

  • Conversion:
    • To int (ReMooD Only) - The function's reference to the virtual machine will be returned (built-in functions will result in negative values.
    • To fixed (ReMooD Only) - The function's reference to the virtual machine will be returned (built-in functions will result in negative values.
    • To mobj (ReMooD Only) - function to int to mobj rules will be used.
    • To string (ReMooD Only) - The function's symbolic name will be converted to a string.
Sample Code:
function foo(mobj theobject)
{
    damageobj(theobject, 5000);
    objmomz(theobject, 2000.0);
}

Expressions

Everything from adding and multiplying numbers to calling functions is considered and expression. Please not that Legacy Script does not follow natural mathematical order of operations nor any standard programming languages. Legacy Script uses a semi-reversed order, so 2 + 3 - 4 is equivalent to 2 + (3 - 4) which will result in 1.

Operators and Their Orders

All expressions will follow this order.
Operators
Description
( and ) Parenthesis: Anything placed within parenthesis will be evaluated first. For example: 2 + 3 * 4 is really 2 + (3 * 4) which results in 14. However, the order can be changed using parenthesis such as (2 + 3) * 4 which will result in 20.
. Member: This operator "gives Legacy Script a comfortable object-oriented appearance" (fsbasic.html). However all it does is move the first parameter of a function outside of the parenthesis. The second operator must be a function that takes at least one parameter. You can only use identifiers as the first parameter because the compiler will treat 0.print() as a decimal number. Example: a mobj obelisk can be killed by using obelisk.kill() which is the same as kill(obelisk).
-- Decrement: Decreases a value by one. If the operator is prefixed (--i) then the value is decreased by one then the resulting value is used. If the operator is suffixed (i--) then the value is returned then it is decremented. If a non-int type is used, it will be converted to one then converted back to the original type.
++ Increment: Increases a value by one. If the operator is prefixed (++i) then the value is increased by one then the resulting value is used. If the operator is suffixed (i++) then the value is returned then it is incremented. If a non-int type is used, it will be converted to one then converted back to the original type.
! Logical NOT: This will turn a non-zero value into zero, and a zero value to 1. If a non-int type is used, it will be converted to one then converted back to the original type.
~ Binary NOT: Flips every bit, ON bits become OFF and OFF bits become ON. If a non-int type is used, it will be converted to one then converted back to the original type.
% Modulus: Returns the remainder of one number divided by the other. The second operand must not be zero. Example: 5 % 2 will result in 1
/ Division: Returns the fractional value of the first number over the second number. The second operand must not be zero. Example: 4 / 2 will result in 2
* Multiplication: Returns the product of the first number times the second number. Example: 5 * 4 is equivalent to 5 + 5 + 5 + 5 which results in 20
- Subtraction: Returns the difference of the first operand and the second operand. Example: 4 - 2 will result in 2.
Unary Plus: If the first operand is an operator then, the value of the second operand will have it's sign flipped.
+ Addition: Returns the sum of the first operand and the second operand. Example: 2 + 2 will result in 4.
>= Greater Than or Equal To: Compares both operands, if the first operand is greater than the second operand or equal to it, then 1 is returned otherwise 0 is. Example: 3 >= 2 will result in 1; 2 >= 2 will result in 1; and 1 >= 2 will result in 0.
<= Less Than or Equal To: Compares both operands, if the first operand is less than the second operand or equal to it, then 1 is returned otherwise 0 is. Example: 3 <= 2 will result in 0; 2 <= 2 will result in 1; and 1 <= 2 will result in 1.
> Greater Than: Compares both operands, if the first operand is greater than the second operand, then 1 is returned, otherwise 0 is. Example: 3 > 2 will result in 1; 2 > 2 will result in 0; and 1 > 2 will result in 0.
< Less Than: Compares both operands, if the first operand is less than the second operand, then 1 is returned, otherwise 0 is. Example: 3 < 2 will result in 0; 2 < 2 will result in 0; and 1 < 2 will result in 1.
!= Not Equal To: Compares both operands, if their value is not the same then 1 is returned, otherwise 0 is. Example: 3 != 3 will result in 0; and 3 != 2 will result in 1.
== Equal To: Compares both operands, if their value is the same then 1 is returned, otherwise 0 is. Example: 3 == 3 will result in 1; and 3 == 2 will result in 0.
& Binary AND: This operand returns a set of bits specified in the second operand that exist in the first operand. 1010 AND 0011 results in 0010.
| Binary OR: This operand returns a set of bits that exist in at least one of the operands. 1010 OR 0011 results in 1011.
&& Logical AND: If both operands are non-zero, this will result in 1, otherwise it will be 0. If the first operand is zero then testing will be short-circuited and the second operand will not be tested.
|| Logical OR: If one operands is non-zero, this will result in 1, otherwise it will be 0. If the first operand is non-zero then testing will be short-circuited and the second operand will not be tested.
= Assignment: Sets the value of the first operand to the second operand on the right. The first operand must be a variable. Example: foo = 2 will set the value of foo to 2.

Operatior Tricks

XOR (Exclusive OR)

A Binary XOR operator does not exist in Legacy Script. This code will simulate that operator and switch the bits around if it were ever needed.
Sample Code:
// Simulated Binary XOR
script 0
{
    int num = 123456;
    int xor = 654321;
    int out = 0;
    int b = 1;
    int i;
    int t;
    
    for (i = 0, i < 32, i++)
    {
        if (xor & b) // Check to see if we are XORing this bit
        {
            if (num & b)
            { // If the bit is 1, we turn it into 0
                t = ~b;
                out = out & b;
            }
            else
            { // If the bit is 0, we turn it into 1
                out = out | b;
            }
        }
        else
        {
// Otherwise, we do not touch this bit
            t = num & b;
            out = out | t;
        }
        
        b = b * 2;
    }
}
If you need to use it multiple times you can also do the following:
Sample Code:
int xor_a = 0; // Value to be XORed
int xor_b = 0; // Value to XOR it by
int xor_c = 0; // Output Value

// Simulated Binary XOR inside of it's own script
script 200
{
    int b = 1;
    int i;
    int t;
    
    xor_c = 0; // Erase old value
    
    for (i = 0, i < 32, i++)
    {
        if (xor_b & b) // Check to see if we are XORing this bit
        {
            if (xor_a & b)
            { // If the bit is 1, we turn it into 0
                t = ~b;
                xor_c = xor_c & b;
            }
            else
            { // If the bit is 0, we turn it into 1
                xor_c = xor_c | b;
            }
        }
        else
        {
// Otherwise, we do not touch this bit
            t = xor_a & b;
            xor_c = xor_c | t;
        }
        
        b = b * 2;
    }
}

// Small script that calls the XOR script
script 0
{
    xor_a = 123456;
    xor_b = 654321;
    
    startscript(200);
    
    print(xor_a, " XOR ", xor_b " is ", xor_c, ".");
}

Functions

void print(...)

Available in: Doom Legacy 1.30+ and ReMooD 0.7a+
Description: Prints a line of text to the console.
Parameters:

  • ... - Variable, can take up to 128 paramaters of any type. Non-string types will automatically be converted into strings.
Return Value: None
Sample Code:
// This code will print "My favorite number is 12."
script 0
{
    int number = 12;
    print("My favorite number is ", number, ".");
}

void runcommand(...)

Available in: Doom Legacy 1.30+ and ReMooD 0.7a+
Description: Executes passed commands in the console.
Parameters:

  • ... - Variable, can take up to 128 paramaters of any type. Non-string types will automatically be converted into strings.
Compatibility:
  • ReMooD 0.7a to ReMooD 0.7c: if scr_allowcommandexec is set, this function will not execute any commands.
  • ReMooD 0.8a+: Not all console commands are supported, check the compatibility section for more details on what commands will work.
Security Warning: In Doom Legacy 1.30+, ReMooD 0.7a and ReMooD 0.7b, this function has the ability to execute any console command.
Return Value: None
Sample Code:
// This code will make the player say "Hello."
script 0
{
    runcommand("say Hello.");
}

ReMooD Assembly

About

ReMooD Assembly provides lower level access to the ReMooD Virtual Machine.

Memory Access

Access to variables and memory is provided using 32-bit unsigned addresses. The memory address 0x00000000 to 0x7FFFFFFF is where standard byte code is stored, it is variable in size and changes depending on the scripts compiled. Access to this area is like normal memory in programming, and everything is represented as bytes. However, everything on and after 0x80000000 are special locations that represent different areas. They are not like standard memory and act as pointers to other locations.
Location
Description
0x00000000 to 0x7FFFFFFF
Byte Code
Size: 2,147,483,647 bytes
Contains all compiled bytecode, not all addresses may be available.
0x80000000 to 0x87FFFFFF
Global Symbol Mapping Space
Size: 134,217,727 bytes
Contains all non-hub variables, constants and functions. This area is a reference area which means that only single values point to objects in memory. 0x80000000 may contain a variable that is 4 bytes in size but the reference is only a single byte. All user created objects are stored here, including objects inside scopes. Due to the size limitation, there is a theoretical maximum of 134,217,727 variables. Built-in symbols and functions are placed in reversed order from the end (example: 0x87FFFFFF may be the built-in constant PORTNAMESTRING, but a symbol lookup should be done to make sure that is is).
0x88000000 to 0x8BFFFFFF
Local Symbol Mapping Space
Size: 67,108,863 bytes
Similar to to the global variable space except that these point to variable pointers in the global variable space. This area is further split into subsections depending on the value of MAXDEEPCALLS. When local variables are created inside of functions, global variables are added then the subsections of this group are mapped to the correct global value. In 0.8a, this value is 10 which limits local variables to 67,108,863 per recursive function.
0x8C000000 to 0x8FFFFFFF
Hub Symbol Mapping Space
Size: 67,108,863 bytes
These are variables, constants and functions that are available in all scripts across all domains. There is a limit of 67,108,863 objects, there are no built-in mappings to these.
0x90000000 to 0x9FFFFFFF
Virtual Data Map
Size: 4,096 sections of 65,536 bytes
This area can be mapped to variable data for direct access. There are 4,096 objects that can be mapped here. 0x9sssDDDD where s is sections for access and D is the data available to access.
0xA0000000 to 0xAFFFFFFF
High Virtual Data Map
Size: 268,435,456 bytes
This area can be mapped to a single variable for direct access. Similar to the Virtual Data Map but allows access to more data but in only a single section.
0xB0000000 to 0xBFFFFFFF
Register Map
Size: 268,435,456 bytes
This area is made up of virtual registers, the maximum allowed is MAXREGISTERS, in 0.8a this is 100.
0xC0000000 to 0xCFFFFFFF
User Zone
Size: 268,435,456 bytes
Contains all allocated by user memory, not all addresses may be available.
0xFFFFFFFF
Invalid
Size: 1 bytes
Invalid memory, any reading or writing to this value will stop the script.

Instructions

NULL ()

Available in: ReMooD 0.7b+
Description: NULL Instruction, this does nothing.

ADD (u:dest, i:add)

Available in: ReMooD 0.7b+
Description: Adds the value in add to the value in dest.
Parameters:

  • u:dest - Memory location to be modified.
  • i:add - Value to add.

SUBTRACT (u:dest, i:sub)

Available in: ReMooD 0.7b+
Description: Subtracts the value in sub to the value in dest.
Parameters:

  • u:dest - Memory location to be modified.
  • i:add - Value to subtract.

Comparison of Scripting Languages

This comparison chart is based on features and limitations.
Feature/Limitation ReMooD Script ReMooD Assembly Legacy Script ACS Small
Exists in ports ReMooD ReMooD ReMooD, Legacy and SMMU Hexen and ZDoom Eternity
Year script released 2008+ (TBD) 2008+ (TBD) 2000? 1995 2008?
Documentation This File This File This File ZDoom Site ?
Base Language Pascal Assembly C C ?
Storage Method Plain Text Plain Text Plain Text Bytecode (Binary) Bytecode (Binary)
Execution Method Byte Code Execution Byte Code Execution Interpreted (Byte Code Execution in ReMooD) Byte Code Execution Byte Code Execution
Compiler Location Internal Internal None (Internal in ReMooD) External External
Allows custom functions Yes Yes No No ?
Allows modification of byte code on the fly No Yes (But is not recommended) - No No
Allows inline assembly Yes - - No No
Allows flow control Loops & Labels Loops, Jumps and Calls Loops & Labels Loops ?
Allows lines to call scripts Yes Yes (via callbacks) Yes Yes Yes
Allows sectors to call scripts Yes (via callbacks) Yes (via callbacks) No Yes ?
Allows things to call scripts (ex: when it dies) Yes (via callbacks) Yes (via callbacks) No ? ?
Allows custom parameters sent to scripts No No No Yes (Hexen only) ?
Maximum number of scripts permitted 65,536 65,536 256 (65,536 in ReMooD) 256 ?
Feature/Limitation ReMooD Script ReMooD Assembly Legacy Script ACS Small