# General

## What is This?

This is a reference for writing Lua scripts to work in Aleph One. It lists every trigger and table available to Lua scripts. It is expected that Lua functionality will grow in Aleph One, and as it does, so will this document. Not everything here is completely documented, and any help fixing that would be appreciated.

This is not a reference for Lua itself - see lua.org for that.

## Running a Script

There are two ways to get a script to run - level specific MML, and selecting a script at the gather network game dialog. To use level specific MML, put the script in a TEXT resource in the map file. Then put in TEXT resource 128 MML telling A1 where to find the script, which in its most basic form is this:

      <marathon_levels>
        <level index="0">
          <lua resource="1000"/>
        </level>
      </marathon_levels>

By convention we use TEXT resource 1000+x to hold the script for level x, so the first level in the map file (which has level index 0) gets its script in TEXT resource 1000.

This works fine for single player games. It will also work for multiplayer games, but only if every player has a copy of the map file and selects it in enviroment prefs.

To use a script via the network game dialog, put then script in a text file. Then, at the gather network game dialog, select "use script", then select your script file.

When playing network games, even if you are not gathering, it's important not to have a map file with level specific MML selected in your environment prefs, unless it's the map file for the map you are playing. A1 will run the script for that map file, your game will go out of sync, and you'll be unhappy.

## Units

The unit for distance we use is World Units (WU) These are the same values you'd see in Forge or with F10 location display, and 1/1024 of what A1 uses internally and what you'd see in Pfhorte.

Units for speed are . . . well let's say they're messy. :)

## Local Player

A few variables are marked "local player." These variables will always do the right thing when written to, but when reading, will only return a useful result if the player they belong to is "local." In net games, there is a separate copy of each Lua script running on each player's computer, and the player is "local" only to his copy of the script.

So, the only local player variables the script running on player 4's machine will be able to read from are the ones in Players[4]. For his script, the value of Players[1].zoom_active, for example, will return nil. If this confuses you, it might be better to avoid reading from any variable marked "local player."

## Loading Collections

A Lua script can ask for the engine to load collections it might otherwise not load; for instance, in order to be able to spawn defenders and compilers on a map that might not have them otherwise, add the indices for those collections to the global table CollectionsUsed:

    CollectionsUsed = { 10, 16 }

These are functions scripts can define which Aleph One will call at specific times or events. For example, to regenerate health:

    Triggers = {}
    function Triggers.idle()
      for p in Players() do
        if p.life < 150 and not p.dead then
          p.life = p.life + 1
        end
      end
    end

Calling Triggers = {} at the beginning of the script removes the compatibility triggers installed for old Lua scripts, speeding up execution of new scripts.
at beginning of level
true if restoring from a saved game
boolean
at end of the level

primarily this is intended as a last chance for changing netgame scores before the postgame carnage report.

at each tick, before physics and such
at each tick, after physics and such, but before rendering
whenever a player starts to use a refuel panel
control_panel_class
player
side
whenever a player stops using a refuel panel
control_panel_class
player
side
whenever a player uses a tag switch
tag
player

not called when a projectile (e.g., fists) toggles a tag switch

whenever a player uses a light switch
light
player

not called when a projectile (e.g., fists) toggles a light switch

whenever a player uses a platform switch
polygon polygon of the platform being toggled
player

not called when a projectile (e.g., fists) toggles a platform switch

whenever a player starts using a terminal
terminal
player
whenever a player stops using a terminal
terminal
player
whenever a player uses a pattern buffer
side
player
whenever a player picks up an item
item_type
player

also whenever a player gets an item when a script calls .items.add()

whenever a light is activated or deactivated
light
whenever a platform is activated or deactivated
polygon
whenever a player revives (presumably only happens in a netgame)
player
whenever a player dies
player
the player who killed player, possibly himself (suicide) (can be nil)
player
dying soft, dying hard, or dying flaming
monster_action
the projectile that delivered the final blow (can be nil)
projectile
whenever a player has taken damage, but before he dies if applicable. The player's suit energy or oxygen may be negative when this trigger is called; if it still is when the trigger returns, it will be set to 0. The player's suit energy is tested again after this trigger returns, so a script may prevent a player's death
player
player who got the kill (can be nil)
player
monster that got the kill (can be nil)
monster
e.g. "fists"
damage_type
the amount recently subtracted from the player. If "oxygen drain", damage_amount was assessed against player's oxygen; otherwise against player's suit energy
number
the projectile that delivered the damage (can be nil)
projectile
whenever a monster dies
monster
player who killed it (can be nil)
player
projectile that delivered the final blow (can be nil)
projectile

called after a monster has taken lethal damage, but before it's removed from the monster list

you can use this to find out when a monster created with new_monster dies, but a monster discovered by Polygons.monsters() may have already taken lethal damage, so you may need to check for that case when using Polygons.monsters()

whenever an item is created and placed on the ground (or floating) somewhere
item

does not trigger on initial item placement because the initial item placement is done before Lua becomes initialised.

whenever a projectile detonates, after it has done any area of effect damage
projectile_type
monster
polygon
WU
WU
WU
These are tables (technically, userdata) defined in Aleph One which scripts can use to access objects in the game.
There is one important difference: in a real Lua table, you can set any field you want. In order to help troubleshooting, Aleph One's userdata tables will only accept the fields listed in the documentation. However, by prepending an underscore, custom fields can be indexed. These custom fields will be associated with the object until it is destroyed.
Each table also has a read-only .index variable that corresponds to the engine's index

polygon this annotation is associated with
polygon

can be nil

an annotation is only shown when its polygon is visible on the overhead map

annotation text (64 characters max)
string
WU
WU

activate camera for player
player
deletes all path points and angles
deactivates camera
adds a path angle
angle
pitch
time
adds a path point
WU
WU
WU
polygon
time

removes effect from map
direction effect is facing
degrees
play sound coming from this effect
sound
polygon the effect is in
polygon
type of effect
effect_type
WU
WU
WU

the difficulty level
difficulty_type
returns a random number between 0 and n-1 from Aleph One's original random number generator
number
number
the game kill limit, or 0 if there is none
number
the number of ticks until the game ends, or nil if there is no time limit
number
the current scoring mode (if the gametype is "custom")
scoring_mode_type
Use this variable to override the game's default scoring behavior. If set to false, the game will not end due to a score limit. If set to true, the game ends immediately. If left unset or if set to nil, the game will end if a score limit is reached. (Note that you cannot prevent the game from ending due to a time limit.)
boolean
returns a random number between 0 and n-1 from Aleph One's original random number generator
number
number

this is a good way to put net games out of sync

returns a random number between 0 and n-1 using a good random number generator
number
number
ticks since game started
time
whether the game is EMFH, KOTH, etc.
game_type

removes item from map
direction item is facing
degrees
play sound coming from this item
sound
polygon the item is in
polygon
type of item
item_type
WU
WU
WU

underwater_fog
present
whether fog is present
boolean
whether fog affects landscapes
boolean

values range from 0.0 to 1.0

red
number
green
number
blue
number
fog depth in WU
number
whether level is low gravity
boolean
whether level is magnetic
string
level name
string
whether level is rebellion
boolean
whether level is vacuum
boolean

whether light is active
boolean

cw_polygon
polygon on clockwise side of line
polygon
cw_side
clockwise side of line
side
ccw_polygon
polygon on counterclockwise side of line
polygon
ccw_side
counterclockwise side of line
side

type of media
media_type

current AI action of the monster
number
whether monster has been activated
boolean
instructs monster to attack target
monster
damages monster
number
damage_type

if no type is specified, fist damage is dealt

yaw
direction the monster is facing
degrees
vitality
the monster's vitality
number

monsters that haven't spawned or teleported in yet don't have vitality

current AI mode of the monster
number
instructs monster to move to polygon
polygon

monsters get distracted easily en route

once it gets there, it probably won't choose to stay

if monster is a player monster, the player; otherwise, nil
player
plays sound coming from this monster
sound
sets position of monster
WU
WU
WU
polygon
type of monster
monster_type
whether monster is still valid
boolean
whether monster is visible (e.g. has teleported in)
boolean

this has nothing to do with whether monsters are cloaked (like invisible S'pht) or not

only writable before the monster is activated

WU
WU
WU

clears the level playlist
fades out the currently playing track and clears the playlist
seconds
appends all of the specified tracks to the end of the playlist
string
string
string
stops level music and clears the playlist
for every track passed, return true if it exists and is playable and false otherwise
string
string
string

whether platform is currently active
boolean
current ceiling height of platform
WU
direction platform is moving or will move when active
boolean
direction platform is moving or will move when active
boolean
current floor height of platform
WU
whether platform can be controlled by monsters
boolean
whether platform can be controlled by players
boolean
polygon of this platform
polygon
platform speed
speed

accelerates player
angle
speed
speed

only valid when read/written in idle()

disabled when the player is viewing a terminal

latched action flags are only true the first tick the key is held down

respawns, or activates platforms/doors/control panels
boolean

latched

switches to next weapon
boolean

latched

switches to previous weapon
boolean

latched

fires primary trigger
boolean
activates the net mic
boolean

can not be set to true; can be set to false

fires secondary trigger
boolean
toggles the overhead map
boolean

latched

activates terminal
terminal
color of player (shirt color, if teams are enabled)
number
turns all compass quadrants off, disables beacon
turns all compass quadrants on, disables beacon
whether to use the beacon
boolean
whether Lua is controlling the compass
boolean
northeast
whether north east compass quadrant is active
boolean
northwest
whether north west compass quadrant is active
boolean
southeast
whether south east compass quadrant is active
boolean
southwest
whether south west compass quadrant is active
boolean
beacon location
WU
beacon location
WU
whether crosshairs are visible
boolean

if you wish to stop the user from toggling the crosshairs, you must set the state every tick

inflicts damage on player
number
if unspecified, crush damage is delt
damage_type
whether player is dead
boolean
deaths not caused by players
number
yaw
direction player is facing
angle
life
amount of suit energy player has (150 is normal red health)
number
pitch
angle player is looking up or down
angle
x
speed
y
speed
z
speed
extravision time remaining
time
whether player is standing in liquid
boolean
fades player's screen
fade_type
if player is in range of a platform or control panel, returns a platform or side; otherwise returns nil
variant

you can check the type of the return with is_polygon() and is_side()

returns t, x, y, z, polygon, where t is the side, polygon_floor, polygon_ceiling, monster, scenery, or polygon (if the target is the surface of a liquid) the player is looking at; and x, y, z, and polygon are the point the player is looking at
variant
WU
WU
WU
polygon

you can check the type of t with is_side(), is_polygon_floor(), is_polygon_ceiling(), is_monster(), is_scenery(), and is_polygon()

whether player is completely below liquid
boolean
infravision time remaining
time
player's forward velocity
number
player's perpendicular (sidestep) velocity
number
invincibility time remaining
time
invisibility time remaining
time

player will become subtly invisible if this is set higher than the standard invisibility duration (70 seconds)

how many of item the player is carrying
item_type
number
true if this player is the local player
boolean

normally, you shouldn't need this--you'll just make the game go out of sync

kill count against slain_player
player
number
monster that corresponds to player
monster
whether player can view his motion sensor
boolean

currently, this also controls compass visibility

player's name
string
amount of oxygen player has (max is 10800)
number
there are 6 overlays, numbered 0 through 5
turns off overlay
text color
number
fills icon with solid color
number
icon
icon
text
string
plays sound that only player can hear
sound
scale

if you want all players to hear the sound as if it is coming from this player, use .monster:play_sound() instead

how many points player has
number
polygon the player is standing on
polygon

if this gives you trouble, try .monster.polygon

set player position
WU
WU
WU
polygon
prints message to player's screen
string
player's team (pants color)
number
teleports player to polygon
WU
teleports player to level (of course, all the other players will also go to that level)
number
secondary
how many rounds are currently loaded into the weapon
number
attempts to force player to ready weapon
weapon the player is currently wielding
player_weapon

can be nil

WU
WU
WU
whether player's sniper zoom is active
boolean

returns adjacent polygon n (across from line n), if one exists, or nil
iterates through all polygons directly adjacent to this polygon
z
ceiling height
WU
whether the point is in this polygon
WU
WU
WU
z
floor height
WU
polygon media (liquid)
media
iterates through all monsters in this polygon (including player monsters)
raw permutation index of this polygon
number
plays sound in center of polygon on floor
sound
plays sound at location
WU
WU
WU
sound
number

if you want to play a sound at an object location, use that object's play_sound function instead

polygon type
polygon_type
center of polygon
WU
center of polygon
WU
shortcut for .floor.height
WU

amount to scale projectile's normal damage by upon detonating
scale
instantaneous downward velocity
speed
pitch
vertical angle
angle
yaw
direction
angle
plays sound coming from this projectile
sound
sets projectile position
WU
WU
WU
polygon
monster that fired projectile, or nil
monster
polygon the projectile is in
polygon
type of projectile
projectile_type
WU
WU
WU

damages scenery
whether this scenery has been damaged
boolean
removes scenery from the map
direction scenery is facing
angle
play sound coming from this scenery
sound
polygon the scenery is in
polygon
whether this scenery is solid
boolean
type of scenery
scenery_type
WU
WU
WU

type of control panel
control_panel_type
permutation of control panel
number

nil if the side is not a control panel

play sound coming from this side
sound
number
line this side is attached to
line
polygon this side is attached to
polygon

tag is active
boolean

number of map annotations
iterates through all annotations
returns a new annotation
polygon
string
WU
WU
number of cameras
iterates through all cameras
returns a new uninitialized camera

make sure to add path points and angles before activating the camera

maximum number of map objects
iterates through all valid effects
returns a new effect
WU
WU
WU
polygon
effect_type
effect
maximum number of map objects
iterates through all valid items
returns a new item
WU
WU
WU
polygon
item_type
item
number of lines in level
iterates through all lines in the level
number of lights in level
iterates through all lights in the level
number of media (liquids) on the level
iterates through all media on the level
maximum number of monsters
iterates through all valid monsters (including player monsters)
returns a new monster
WU
WU
WU
polygon
monster_type
monster
number of platforms on the level
iterates through all platforms in the level
number of players in the game
iterates through all players in the game
prints message to all players' screens
string
number of polygons in the level
iterates through all polygons in the level
maximum number of projectiles
iterates through all valid projectiles
returns a new projectile
WU
WU
WU
polygon
projectile_type

remember to set the projectile's elevation, facing and owner immediately after you've created it

maximum number of map objects
iterates through all valid scenery
returns a new scenery
WU
WU
WU
polygon
scenery_type
scenery
number of sides on the level
iterates through all sides on the level
number of terminal texts in the level
iterates through all terminal texts on the level
class of this control panel type
control_panel_class
class of monster type
monster_class
whether monster class is an emeny
monster_class
boolean
whether monster class is a friend
monster_class
boolean
type of effect generated when monster gets hit by a bleeding projectile
effect_type
whether monster type is immune to damage type
damage_type
boolean
height of monster
WU
type of item the monster drops when it dies
item_type
type of effect generated when monster gets hit by a melee projectile
effect_type
radius of monster
WU
whether monster type has a weakness to damage type
damage_type
boolean
The string mnemonics listed below can be used for assignment and as arguments to functions. Additionally, Aleph One's Lua interpreter has been modified so that equality comparisons between userdata types and strings are possible.
For example, this script would move all players on the blue team to the red team:

    for p in Players() do
      if p.team == "blue" then
        p.team = "red"
      end
    end

And this one would damage all major compilers with 10 points of fusion damage:

    for m in Monsters() do
      if m.type == "major compiler" then
        m:damage(10, "fusion")
      end
    end

Each type has a read-only .index field, which represents the game's internal index:

    > =ItemTypes["pistol"].index
    1

Each type also has a .mnemonic field, which is handy for finding the mnemonic of a given type:

    > =MonsterTypes["major compiler"].class.mnemonic
    compiler

You can even use the mnemonic field to customize the mnemonics for your scenario. Note that you can only have one string mnemonic per type index:

    > WeaponTypes["fist"].mnemonic = "puncher"
    > =WeaponTypes["puncher"].index
    0
    > =WeaponTypes["fist"]
    nil

If you do this, you should customize them all at the beginning of the script. Changing mnemonics mid-game will confuse anyone who tries to read your script, and probably yourself as well!

# Example Icon

    --[[
    This is  an example  of an  icon  in  the format  used by  Aleph One's  overlay
    functions.
    The first characters  are a digit string  describing the number of  colors. (in
    this example, it's 7.
    The first character that  is not a digit is ignored,  as are all the characters
    following it  that are the same  character. (i.e. I  could use a q instead of a
    newline here.
    Then,  for  every color,  it reads  a character,  followed by  a six-digit  hex
    string,  which is the  HTML-style color corresponding  to that character in the
    image.  After reading this string,  it ignores the next character,  whatever it
    is.
    Once it has  read every color,  it reads all the following characters,  and for
    every character it reads for which a color has defined, it puts that color into
    the icon as the next pixel. Other characters are ignored. (see below.)
    Icons are always 16x16.
    ]]

    [[
    7
     0000FF
    #000000
    .FFFFFF
    $7FAE20
    %EBD52A
    ,45983C
    *5B4714
    *************# The fact
    *************# that it
    *$$$#*********# ignores
    $$$$$#********# characters
    $$$$$#$$******# that
    $$##$##$$*****# are
    $$$$##.#$$#**# not colors
    $%%$$#.,#$#**# can be
    %%%%%%##,#$$# exploited to interesting
    %%%%%%%##$$# effect by a sufficiently
    #%%%%%%%$$$$# resourceful and obnoxious
    *##%%%%%%$$$$###
    #**#%%#%%%###**#
    *#*##%%#%%$$$$# person
    **#  #%%##%$$# such as
    **#   #%%%#%$# myself :)
    Additionally, once it has read 256 valid characters, it ignores the rest of the
    string.
    ]]