# Table of Contents

1. General
   1. What is This?
   2. Running a Script
   3. Units
   4. Local Player
   5. Loading Collections
   6. Persistence
2. Triggers
3. Using Tables
   1. Custom Fields
   2. Index
4. Tables
   1. Annotations
   2. Cameras
   3. Effects
   4. Endpoints
   5. Game
   6. Items
   7. Level
   8. Lights
   9. Lines
   10. Media
   11. Monsters
   12. Music
   13. Platforms
   14. Players
   15. Polygons
   16. Projectiles
   17. Scenery
   18. Sides
   19. Tags
   20. Terminals
5. Types and Mnemonics
   1. Collections
   2. Completion States
   3. Control Panel Classes
   4. Control Panel Types
   5. Damage
   6. Difficulty
   7. Effects
   8. Faders
   9. Game Types
   10. Items
   11. Light Functions
   12. Light Presets
   13. Light States
   14. Media
   15. Monster Actions
   16. Monster Classes
   17. Monster Modes
   18. Monsters
   19. Overlay Colors
   20. Platform Types
   21. Player and Team Colors
   22. Polygons
   23. Projectiles
   24. Scenery
   25. Scoring Modes
   26. Side Types
   27. Sounds
   28. Texture Types
   29. Transfer Modes
   30. Weapons
6. Example Icon

# 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 three ways to get a script to run - by embedding it in a level, by selecting a solo script in the Environment Preferences, or by selecting a script at the gather network game dialog.

To embed a script in a level, use a tool such as Atque. Use embedded Lua scripts only for map specific features, not for modifying game types. For instance, it may be tempting to embed the latest version of the Lua CTF script in a map designed only for playing CTF; however, this would prevent the user from using a later version of CTF if it were to come out, or from using another net script that works on CTF maps. Some older scenarios use Lua scripts in TEXT resources, but this is no longer recommended since they are not transmitted in net games.

To use a solo script, check the "Use Solo Script" box in Environment Preferences, and choose the script file to use.

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

## 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. :) Lua speeds are expressed in World Units per tick (a tick is 1/30 of a second). Forge claims to use WU per sec, but it actually uses 0.87890625 WU per sec (which equals 30 internal units per tick). The following example illustrates the various conversions:

- Actual: 7.5 World Units per second
- A1 internal: 256 units per tick (7.5 * 1024 / 30)
- Lua: 0.25 WU per tick (7.5 / 30)
- Forge: 8.53 "WU per second" ((7.5 * 1024 / 30) / 30)

## 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 }

## Persistence

Lua scripts are only active during a single level. If the user jumps to a new level, or restores from a saved game, the script is restarted in a clean state.

It is now possible to pass data across level jumps, by using the Game.restore_passed() function. This function will restore any custom fields (see the "Custom Fields" section of "Using Tables" below) in the Players or Game tables that were set immediately prior to the last level jump. Note that in order for data to survive multiple level jumps, Game.restore_passed() must be called after each level jump. Game.restore_passed() will not restore data from saved games.

It is also possible to restore data from saved games. The Game.restore_saved() function will restore all custom fields in use at the time the game was saved.

Only numbers, strings, booleans, and tables (including Aleph One's built-in userdata tables) can be restored.

# Triggers

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.

Triggers
  .init(restoring_game)

    at beginning of level

    - restoring_game: true if restoring from a saved game
  .cleanup()

    at end of the level

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

  .idle()

    at each tick, before physics and such

  .postidle()

    at each tick, after physics and such, but before rendering

  .start_refuel(class, player, side)

    whenever a player starts to use a refuel panel

  .end_refuel(class, player, side)

    whenever a player stops using a refuel panel

  .tag_switch(tag, player)

    whenever a player uses a tag switch

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

  .light_switch(light, player)

    whenever a player uses a light switch

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

  .platform_switch(polygon, player)

    whenever a player uses a platform switch

    - polygon: polygon of the platform being toggled

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

  .terminal_enter(terminal, player)

    whenever a player starts using a terminal

  .terminal_exit(terminal, player)

    whenever a player stops using a terminal

  .pattern_buffer(side, player)

    whenever a player uses a pattern buffer

  .got_item(type, player)

    whenever a player picks up an item

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

  .light_activated(light)

    whenever a light is activated or deactivated

  .platform_activated(polygon)

    whenever a platform is activated or deactivated

  .player_revived(player)

    whenever a player revives (presumably only happens in a netgame)

  .player_killed(player, aggressor_player, action, projectile)

    whenever a player dies

    - aggressor_player: the player who killed player, possibly himself (suicide) (can be nil)
    - action: dying soft, dying hard, or dying flaming
    - projectile: the projectile that delivered the final blow (can be nil)
  .player_damaged(victim, aggressor_player, aggressor_monster, damage_type, damage_amount, 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

    - aggressor_player: player who got the kill (can be nil)
    - aggressor_monster: monster that got the kill (can be nil)
    - damage_type: e.g. "fists"
    - damage_amount: the amount recently subtracted from the player. If "oxygen drain", damage_amount was assessed against player's oxygen; otherwise against player's suit energy
    - projectile: the projectile that delivered the damage (can be nil)
  .monster_damaged(monster, aggressor_monster, damage_type, damage_amount, projectile) 20100118

    whenever a monster is damaged, but before it dies if applicable. The monster's vitality may be negative when this trigger is called. Ther monster's vitality will be tested again after this trigger returns, so a script may prevent a monster's death

    - aggressor_monster: the monster that caused the damage (can be nil)
    - damage_type: e.g. "fists"
    - damage_amount: the amount recently subtracted from the monster's vitality
    - projectile: the projectile that delivered the damage (can be nil)
  .monster_killed(monster, aggressor_player, projectile)

    whenever a monster dies

    - aggressor_player: player who killed it (can be nil)
    - projectile: projectile that delivered the final blow (can be nil)

    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()

  .item_created(item)

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

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

  .projectile_detonated(type, owner, polygon, x, y, z)

    whenever a projectile detonates, after it has done any area of effect damage

# Using Tables

There are numerous tables (technically, userdata) defined in Aleph One which scripts can use to access objects in the game. A complete list is below.

## Custom Fields

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 below. However, by prepending an underscore, custom fields can be indexed. These custom fields will be associated with the object until it is destroyed.

    Players[0]._favorite_flavor = "chocolate"

## Index

Each table has a read-only .index variable, that corresponds to the engine's internal index.

    =Players[0].index
    0

# Tables

### Annotations

  number of map annotations

Annotations()

  iterates through all annotations

Annotations.new(polygon, text [, x] [, y])

  returns a new annotation

Annotations[index]
  .polygon

    polygon this annotation is associated with

    can be nil

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

  .text

    annotation text (64 characters max)

  .x

  .y

### Cameras

  number of cameras

Cameras()

  iterates through all cameras

Cameras.new()

  returns a new uninitialized camera

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

Cameras[index]
  :activate(player)

    activate camera for player

  :clear()

    deletes all path points and angles

  :deactivate()

    deactivates camera

  .path_angles
    :new(yaw, pitch, time)

      adds a path angle

  .path_points
    :new(x, y, z, polygon, time)

      adds a path point

### Effects

  maximum number of map objects

Effects()

  iterates through all valid effects

Effects.new(x, y, height, polygon, type)

  returns a new effect

Effects[index]
  :delete()

    removes effect from map

  .facing

    direction effect is facing

  :play_sound(sound)

    play sound coming from this effect

  .polygon (read-only)

    polygon the effect is in

  :position(x, y, z, polygon) 20090909

    sets position of effect

  .type (read-only)

    type of effect

  .x (read-only)

  .y (read-only)

  .z (read-only)

### Endpoints

  number of endpoints in level

Endpoints()

  iterates through all endpoints in the level

Endpoints[index]
  .x (read-only)

  .y (read-only)

### Game

Game
  .difficulty (read-only)

    the difficulty level

  .global_random(n)

    returns a random number between 0 and n-1 from Aleph One's original random number generator

  .kill_limit (read-only)

    the game kill limit, or 0 if there is none

  .proper_item_accounting 20100118

    When true, the current item counts on the map are updated properly when Lua deletes map items and changes player inventories. This defaults to false to preserve film playback with older scripts. New scripts that manipulate items should always set this to true.

  .time_remaining (read-only)

    the number of ticks until the game ends, or nil if there is no time limit

  .scoring_mode

    the current scoring mode (if the gametype is "custom")

  .over (write-only)

    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.)

  .local_random(n)

    returns a random number between 0 and n-1 from Aleph One's original random number generator

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

  .random(n)

    returns a random number between 0 and n-1 using a good random number generator

  .restore_passed() 20090909

    tries to restore any Player or Game custom fields from before the last level jump; returns true if custom fields were successfully restored

    if successful, overwrites all existing Player or Game custom fields

  .restore_saved() 20090909

    tries to restore any custom fields from the saved game; returns true if custom fields were successfully restored

    if successful, overwrites all existing custom fields

  .save()

    saves the game (as if the user had activated a pattern buffer)

    solo only

  .ticks (read-only)

    ticks since game started

  .type (read-only)

    whether the game is EMFH, KOTH, etc.

  .version (read-only)

    the date version of the local player's engine

    for example, "20071103"

### Items

  maximum number of map objects

Items()

  iterates through all valid items

Items.new(x, y, height, polygon, type)

  returns a new item

Items[index]
  :delete()

    removes item from map

  .facing

    direction item is facing

  :play_sound(sound)

    play sound coming from this item

  .polygon (read-only)

    polygon the item is in

  :position(x, y, z, polygon) 20090909

    sets position of item

  .type (read-only)

    type of item

  .x (read-only)

  .y (read-only)

  .z (read-only)

### Level

Level
  .calculate_completion_state() 20081213

    returns whether level is finished, unfinished, or failed

  .extermination (read-only) 20081213

    whether level has extermination flag set

  .exploration (read-only) 20081213

    whether level has exploration flag set

  .fog
  .underwater_fog
    .active
    .present

      whether fog is present

    .affects_landscapes

      whether fog affects landscapes

    .color

    values range from 0.0 to 1.0

      .b

        blue

      .g

        green

      .r

        red

    .depth

      fog depth in WU

  .low_gravity (read-only)

    whether level is low gravity

  .magnetic (read-only)

    whether level is magnetic

  .name (read-only)

    level name

  .rebellion (read-only)

    whether level is rebellion

  .repair (read-only) 20081213

    whether level has repair flag set

  .rescue (read-only) 20081213

    whether level has rescue flag set

  .retrieval (read-only) 20081213

    whether level has retrieval flag set

  .vacuum (read-only)

    whether level is vacuum

### Lights

  number of lights in level

Lights()

  iterates through all lights in the level

Lights.new( [light_preset])

  returns a new light

Lights[index]
  .active

    whether light is active

  .tag 20100118

    tag of light

  .initial_phase 20100118

    phase the light starts with

  .initially_active 20100118

    whether the light was initially active

  .intensity (read-only) 20100118

    current intensity for this light (range: 0-1)

  .states[light_type]
    .delta_intensity 20100118

      random intensity change for this state

    .delta_period 20100118

      random period change for this state

    .intensity 20100118

      intensity for this state

    .light_function 20100118

      light function for this state

    .period 20100118

      period for this state

### Lines

  number of lines in level

Lines()

  iterates through all lines in the level

Lines[index]
  .clockwise_polygon (read-only)
  .cw_polygon (read-only)

    polygon on clockwise side of line

  .clockwise_side (read-only)
  .cw_side (read-only)

    clockwise side of line

  .counterclockwise_polygon (read-only)
  .ccw_polygon (read-only)

    polygon on counterclockwise side of line

  .counterclockwise_side (read-only)
  .ccw_side (read-only)

    counterclockwise side of line

  .endpoints[n]

    returns line endpoint n

  .has_transparent_side (read-only) 20080707

    whether one of the line's sides has a transparent texture

  .highest_adjacent_floor (read-only) 20080707

    height of higher adjacent polygon floor

  .length (read-only)

    the length of this line

    this might not be accurate, if someone used Chisel's stretch plugin

  .lowest_adjacent_ceiling (read-only) 20080707

    height of lower adjacent polygon ceiling

  .solid (read-only) 20080707

    whether line is solid

### Media

  number of media (liquids) on the level

Media()

  iterates through all media on the level

Media[index]
  .direction 20100118

    direction of media

  .height (read-only) 20100118

    height of media

  .high 20100118

    high tide of media

  .light 20100118

    light that controls this media's tide

  .low 20100118

    low tide of media

  .speed 20100118

    speed of media

  .type (read-only)

    type of media

  .type 20100118

    type of media

### Monsters

  maximum number of monsters

Monsters()

  iterates through all valid monsters (including player monsters)

Monsters.new(x, y, height, polygon, type)

  returns a new monster

Monsters[index]
  :accelerate(direction, velocity, vertical_velocity) 20081213

    accelerates monster

  .action (read-only)

    current AI action of the monster

  .active

    whether monster has been activated

  :attack(target)

    instructs monster to attack target

  :damage(amount [, type])

    damages monster

    if no type is specified, fist damage is dealt

  .external_velocity 20090909

    monster's current external velocity (always in the opposite direction of facing)

  .facing
  .yaw

    direction the monster is facing

  .life
  .vitality

    the monster's vitality

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

  .mode (read-only)

    current AI mode of the monster

  :move_by_path(polygon)

    instructs monster to move to polygon

    monsters get distracted easily en route

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

  .player (read-only)

    if monster is a player monster, the player; otherwise, nil

  :play_sound(sound)

    plays sound coming from this monster

  .polygon (read-only)

    polygon this monster is in

  :position(x, y, z, polygon)

    sets position of monster

  .type (read-only)

    type of monster

  .valid (read-only)

    whether monster is still valid

  .vertical_velocity 20090909

    monster's current vertical external velocity

  .visible

    whether monster is visible (e.g. has teleported in)

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

    only writable before the monster is activated

  .x (read-only)

  .y (read-only)

  .z (read-only)

### Music

Music
  .clear()

    clears the level playlist

  .fade(duration)

    fades out the currently playing track and clears the playlist

  .play(track1 [, track2] [, ...])

    appends all of the specified tracks to the end of the playlist

  .stop()

    stops level music and clears the playlist

  .valid(track1 [, track2] [, ...])

    for every track passed, return true if it exists and is playable and false otherwise

### Platforms

  number of platforms on the level

Platforms()

  iterates through all platforms in the level

Platforms[index]
  .active

    whether platform is currently active

  .ceiling_height

    current ceiling height of platform

  .contracting

    direction platform is moving or will move when active

  .door 20100118

    platform is a door

  .extending

    direction platform is moving or will move when active

  .floor_height

    current floor height of platform

  .locked 20100118

    platform is locked

    this flag doesn't actually do anything

  .monster_controllable

    whether platform can be controlled by monsters

  .player_controllable

    whether platform can be controlled by players

  .polygon (read-only)

    polygon of this platform

  .secret 20100118

    platform is secret

    secret platforms aren't shown on the overhead map

  .speed

    platform speed

  .type 20100118

    type of this platform

    the only thing the engine uses type for is the platform's sound

### Players

  number of players in the game

Players()

  iterates through all players in the game

Players.print(message)

  prints message to all players' screens

Players[index]
  :accelerate(direction, velocity, vertical_velocity)

    accelerates player

  .action_flags

  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

    .action_trigger

      respawns, or activates platforms/doors/control panels

      latched

    .cycle_weapons_backward

      switches to previous weapon

      latched

    .cycle_weapons_forward

      switches to next weapon

      latched

    .left_trigger

      fires primary trigger

    .microphone_button

      activates the net mic

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

    .right_trigger

      fires secondary trigger

    .toggle_map

      toggles the overhead map

      latched

  :activate_terminal(terminal)

    activates terminal

  .color

    color of player (shirt color, if teams are enabled)

  .compass
    :all_off()

      turns all compass quadrants off, disables beacon

    :all_on()

      turns all compass quadrants on, disables beacon

    .beacon

      whether to use the beacon

    .lua

      whether Lua is controlling the compass

    .ne
    .northeast

      whether north east compass quadrant is active

    .nw
    .northwest

      whether north west compass quadrant is active

    .se
    .southeast

      whether south east compass quadrant is active

    .sw
    .southwest

      whether south west compass quadrant is active

    .x

      beacon location

    .y

      beacon location

  .crosshairs
    .active (local player)

      whether crosshairs are visible

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

  :damage(amount [, type])

    inflicts damage on player

    - type: if unspecified, crush damage is delt
  .dead (read-only)

    whether player is dead

  .deaths

    deaths not caused by players

  .direction
  .yaw

    direction player is facing

  .disconnected

    whether player dropped out of the game

  .energy
  .life

    amount of suit energy player has (150 is normal red health)

  .elevation
  .pitch

    angle player is looking up or down

  .external_velocity
    .i
    .x

    .j
    .y

    .k
    .z

  .extravision_duration

    extravision time remaining

  .feet_below_media (read-only)

    whether player is standing in liquid

  :fade_screen(type)

    fades player's screen

  :find_action_key_target()

    if player is in range of a platform or control panel, returns a platform or side; otherwise returns nil

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

  :find_target()

    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

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

  .head_below_media (read-only)

    whether player is completely below liquid

  .infravision_duration

    infravision time remaining

  .internal_velocity
    .forward (read-only)

      player's forward velocity

    .perpendicular (read-only)

      player's perpendicular (sidestep) velocity

  .invincibility_duration

    invincibility time remaining

  .invisibility_duration

    invisibility time remaining

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

  .items[item_type]

    how many of item the player is carrying

  .local_ (read-only)

    true if this player is the local player

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

  .kills[slain_player]

    kill count against slain_player

  .monster (read-only)

    monster that corresponds to player

  .motion_sensor_active (local player)

    whether player can view his motion sensor

    currently, this also controls compass visibility

  .name (read-only)

    player's name

  .oxygen

    amount of oxygen player has (max is 10800)

  .overlays[n]

    there are 6 overlays, numbered 0 through 5

    :clear()

      turns off overlay

    .color (write-only)

      text color

    :fill_icon(color)

      fills icon with solid color

    .icon (write-only)

      icon

    .text (write-only)

      text

  :play_sound(sound, pitch)

    plays sound that only player can hear

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

  .points

    how many points player has

  .polygon (read-only)

    polygon the player is standing on

    if this gives you trouble, try .monster.polygon

  :position(x, y, z, polygon)

    set player position

  :print(message)

    prints message to player's screen

  .team

    player's team (pants color)

  :teleport(polygon)

    teleports player to polygon

  :teleport_to_level(level)

    teleports player to level (of course, all the other players will also go to that level)

  .texture_palette

    displays a texture palette instead of the classic HUD

    .highlight (local player)

      number of slot to highlight

      can be nil

    .size (local player)

      how many slots the palette has

      there is a maximum of 256 slots

      the texture palette is visible whenever the size is greater than 0

      rows/columns may change in the future based on the user's screen layout prefs

    .slots[n]
      :clear()

        makes this slot empty

      .collection (local player)

        collection of this slot

      .texture_index (local player)

        texture index of this slot

      .type (local player) 20090909

        texture type of this slot such as wall or sprite; see "Texture Types"

  :view_player(player) 20080707

    switch to another player's view

  .weapons
    .active 20080707

      when a player's weapons are not active, he does not see weapons in hand, and can not fire

    .current (read-only)

      weapon the player is currently wielding

      can be nil

    .desired (read-only) 20090909

      weapon the player wants to switch to

      can be nil

  .weapons[weapon_type]
    .primary
    .secondary
      .rounds (read-only)

        how many rounds are currently loaded into the weapon

    :select()

      attempts to force player to ready weapon

  .weapons.current (read-only)

    weapon the player is currently wielding

    can be nil

  .x (read-only)

  .y (read-only)

  .z (read-only)

  .zoom_active (local player)

    whether player's sniper zoom is active

### Polygons

  number of polygons in the level

Polygons()

  iterates through all polygons in the level

Polygons[index]
  .adjacent_polygons[n]

    returns adjacent polygon n (across from line n), if one exists, or nil

  :adjacent_polygons()

    iterates through all polygons directly adjacent to this polygon

  .area (read-only)

    the area of this polygon

  .ceiling
  .floor
    .collection

      texture collection

    .height
    .z

      height

    .light

      texture light

    .texture_index

      texture bitmap index

    .texture_x

      texture x offset

    .texture_y

      texture y offset

    .transfer_mode

      texture transfer mode

  :contains(x, y [, z])

    whether the point is in this polygon

  .endpoints[n]

    returns endpoint n

  :endpoints()

    iterates through all of this polygon's endpoints

  :find_line_crossed_leaving(x1, y1, x2, y2) 20080707

    returns the polygon line crossed by line segment (x1, y1) (x2, y2)

    can be nil if the line segment doesn't intersect a polygon line

  .lines[n]

    returns polygon line n

  :lines()

    iterates through all of this polygon's lines

  .media

    polygon media (liquid)

  :monsters()

    iterates through all monsters in this polygon (including player monsters)

  .permutation

    raw permutation index of this polygon

  :play_sound(sound)

    plays sound in center of polygon on floor

  :play_sound(x, y, z, sound [, pitch])

    plays sound at location

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

  .sides[n]

    returns polygon side n if it exists

  :sides()

    iterates through all of this polygon's sides

  .type

    polygon type

  .x (read-only)

    center of polygon

  .y (read-only)

    center of polygon

  .z (read-only)

    shortcut for .floor.height

### Projectiles

  maximum number of projectiles

Projectiles()

  iterates through all valid projectiles

Projectiles.new(x, y, z, polygon, type)

  returns a new projectile

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

Projectiles[index]
  .damage_scale

    amount to scale projectile's normal damage by upon detonating

  .dz

    instantaneous downward velocity

  .elevation
  .pitch

    vertical angle

  .facing
  .yaw

    direction

  :play_sound(sound)

    plays sound coming from this projectile

  :position(x, y, z, polygon)

    sets projectile position

  .owner

    monster that fired projectile, or nil

  .polygon (read-only)

    polygon the projectile is in

  .target

    target of guided projectile, or nil

  .type (read-only)

    type of projectile

  .x (read-only)

  .y (read-only)

  .z (read-only)

### Scenery

  maximum number of map objects

Scenery()

  iterates through all valid scenery

Scenery.new(x, y, height, polygon, type)

  returns a new scenery

Scenery[index]
  :damage()

    damages scenery

  .damaged (read-only)

    whether this scenery has been damaged

  :delete()

    removes scenery from the map

  .facing

    direction scenery is facing

  :play_sound(sound)

    play sound coming from this scenery

  .polygon (read-only)

    polygon the scenery is in

  :position(x, y, z, polygon) 20090909

    sets position of scenery

  .solid

    whether this scenery is solid

  .type (read-only)

    type of scenery

  .x (read-only)

  .y (read-only)

  .z (read-only)

### Sides

  number of sides on the level

Sides()

  iterates through all sides on the level

Sides.new(polygon, line) 20080707

  creates a new side

  side must not already exist

Sides[index]
  .control_panel

  nil if the side is not a control panel

  set to true or false to create/destroy a control panel 20080707

    .can_be_destroyed 20080707

      whether projectiles destroy this switch

    .light_dependent 20080707

      switch can only be activated if light > 75%

    .only_toggled_by_weapons 20080707

      switch can only be toggled by weapons

    .permutation

      permutation of control panel

    .repair 20080707

      switch is a repair switch

    .type 20080707

      type of control panel

    .uses_item 20080707

      i.e. chip insertion

  .primary
  .secondary
  .transparent
    .collection

      texture collection

    .empty

      whether transparent side is empty

      transparent side only

      setting empty to false is a no-op; set collection and texture_index instead

    .light

      texture light

    .texture_index

      texture bitmap index

    .texture_x

      texture x offset

    .texture_y

      texture y offset

    .transfer_mode

      texture transfer mode

  :play_sound(sound [, pitch])

    play sound coming from this side

  .line (read-only)

    line this side is attached to

  .polygon (read-only)

    polygon this side is attached to

  :recalculate_type() 20081213

    correct the side type (Forge can generate incorrect side types)

  .type (read-only) 20080707

    type of side

### Tags

Tags[index]
  .active

    tag is active

### Terminals

  number of terminal texts in the level

Terminals()

  iterates through all terminal texts on the level

Terminals[index]

# Types and Mnemonics

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!

### Collections

Collections()
Collections[collection]
  .bitmap_count

    number of bitmaps in collection

#### Mnemonics

- "interface"
- "weapons in hand"
- "juggernaut"
- "tick"
- "explosions"
- "hunter"
- "player"
- "items"
- "trooper"
- "fighter"
- "defender"
- "yeti"
- "bob"
- "vacbob"
- "enforcer"
- "drone"
- "compiler"
- "water"
- "lava"
- "sewage"
- "jjaro"
- "pfhor"
- "water scenery"
- "lava scenery"
- "sewage scenery"
- "jjaro scenery"
- "pfhor scenery"
- "day"
- "night"
- "moon"
- "space"
- "cyborg"

### Completion States

# CompletionStates
CompletionStates()

#### Mnemonics

- "unfinished"
- "finished"
- "failed"

### Control Panel Classes

# ControlPanelClasses
ControlPanelClasses()

#### Mnemonics

- "oxygen recharger"
- "single shield recharger"
- "double shield recharger"
- "triple shield recharger"
- "light switch"
- "platform switch"
- "tag switch"
- "pattern buffer"
- "terminal"

### Control Panel Types

# ControlPanelTypes
ControlPanelTypes()
ControlPanelTypes[control_panel_type]
  .active_texture_index (read-only) 20080707

    bitmap index when control panel is active

  .class (read-only)

    class of this control panel type

  .collection (read-only) 20080707

    collection this control panel belongs to

  .inactive_texture_index (read-only) 20080707

    bitmap index when control panel is inactive/destroyed

### Damage

# DamageTypes
DamageTypes()

#### Mnemonics

- "explosion"
- "staff"
- "projectile"
- "absorbed"
- "flame"
- "claws"
- "alien weapon"
- "hulk slap"
- "compiler"
- "fusion"
- "hunter"
- "fists"
- "teleporter"
- "defender"
- "yeti claws"
- "yeti projectile"
- "crushing"
- "lava"
- "suffocation"
- "goo"
- "energy drain"
- "oxygen drain"
- "drone"
- "shotgun"

### Difficulty

# DifficultyTypes
DifficultyTypes()

#### Mnemonics

- "kindergarten"
- "easy"
- "normal"
- "major damage"
- "total carnage"

### Effects

# EffectTypes
EffectTypes()

#### Mnemonics

- "rocket explosion"
- "rocket contrail"
- "grenade explosion"
- "grenade contrail"
- "bullet ricochet"
- "alien weapon ricochet"
- "flamethrower burst"
- "fighter blood splash"
- "player blood splash"
- "civilian blood splash"
- "assimilated civilian blood splash"
- "enforcer blood splash"
- "compiler bolt minor detonation"
- "compiler bolt major detonation"
- "compiler bolt major contrail"
- "fighter projectile detonation"
- "fighter melee detonation"
- "hunter projectile detonation"
- "hunter spark"
- "minor fusion detonation"
- "major fusion detonation"
- "major fusion contrail"
- "fist detonation"
- "minor defender detonation"
- "major defender detonation"
- "defender spark"
- "trooper blood splash"
- "water lamp breaking"
- "lava lamp breaking"
- "sewage lamp breaking"
- "alien lamp breaking"
- "metallic clang"
- "teleport object in"
- "teleport object out"
- "small water splash"
- "medium water splash"
- "large water splash"
- "large water emergence"
- "small lava splash"
- "medium lava splash"
- "large lava splash"
- "large lava emergence"
- "small sewage splash"
- "medium sewage splash"
- "large sewage splash"
- "large sewage emergence"
- "small goo splash"
- "medium goo splash"
- "large goo splash"
- "large goo emergence"
- "minor hummer projectile detonation"
- "major hummer projectile detonation"
- "durandal hummer projectile detonation"
- "hummer spark"
- "cyborg projectile detonation"
- "cyborg blood splash"
- "minor fusion dispersal"
- "major fusion dispersal"
- "overloaded fusion dispersal"
- "sewage yeti blood splash"
- "sewage yeti projectile detonation"
- "water yeti blood splash"
- "lava yeti blood splash"
- "lava yeti projectile detonation"
- "yeti melee detonation"
- "juggernaut spark"
- "juggernaut missile contrail"
- "small jjaro splash"
- "medium jjaro splash"
- "large jjaro splash"
- "large jjaro emergence"
- "civilian fusion blood splash"
- "assimilated civilian fusion blood splash"

### Faders

# FadeTypes
FadeTypes()

#### Mnemonics

- "start cinematic fade in"
- "cinematic fade in"
- "long cinematic fade in"
- "cinematic fade out"
- "end cinematic fade out"
- "red"
- "big red"
- "bonus"
- "bright"
- "long bright"
- "yellow"
- "big yellow"
- "purple"
- "cyan"
- "white"
- "big white"
- "orange"
- "long orange"
- "green"
- "long green"
- "static"
- "negative"
- "big negative"
- "flicker negative"
- "dodge purple"
- "burn cyan"
- "dodge yellow"
- "burn green"
- "tint green"
- "tint blue"
- "tint orange"
- "tint gross"
- "tint jjaro"

### Game Types

# GameTypes
GameTypes()

#### Mnemonics

- "kill monsters"
- "cooperative play"
- "capture the flag"
- "king of the hill"
- "kill the man with the ball"
- "defense"
- "rugby"
- "tag"
- "netscript"

### Items

# ItemTypes
ItemTypes()

#### Mnemonics

- "knife"
- "pistol"
- "pistol ammo"
- "fusion pistol"
- "fusion pistol ammo"
- "assault rifle"
- "assault rifle ammo"
- "assault rifle grenades"
- "missile launcher"
- "missile launcher ammo"
- "invisibility"
- "invincibility"
- "infravision"
- "alien weapon"
- "alien weapon ammo"
- "flamethrower"
- "flamethrower ammo"
- "extravision"
- "oxygen"
- "single health"
- "double health"
- "triple health"
- "shotgun"
- "shotgun ammo"
- "key"
- "uplink chip"
- "light blue ball"
- "ball"
- "violet ball"
- "yellow ball"
- "brown ball"
- "orange ball"
- "blue ball"
- "green ball"
- "smg"
- "smg ammo"

### Light Functions

# LightFunctions
LightFunctions()

#### Mnemonics

- "constant"
- "linear"
- "smooth"
- "flicker"

### Light Presets

# LightPresets
LightPresets()

#### Mnemonics

- "normal"
- "strobe"
- "media"

### Light States

# LightStates
LightStates()

#### Mnemonics

- "becoming active"
- "primary active"
- "secondary active"
- "becoming inactive"
- "primary inactive"
- "secondary inactive"

### Media

# MediaTypes
MediaTypes()

#### Mnemonics

- "water"
- "lava"
- "goo"
- "sewage"
- "jjaro"

### Monster Actions

# MonsterActions
MonsterActions()

#### Mnemonics

- "stationary"
- "waiting to attack again"
- "moving"
- "attacking close"
- "attacking far"
- "being hit"
- "dying hard"
- "dying soft"
- "dying flaming"
- "teleporting"
- "teleporting in"
- "teleporting out"

### Monster Classes

# MonsterClasses
MonsterClasses()

#### Mnemonics

- "player"
- "bob"
- "madd"
- "possessed drone"
- "defender"
- "fighter"
- "trooper"
- "hunter"
- "enforcer"
- "juggernaut"
- "drone"
- "compiler"
- "cyborg"
- "explodabob"
- "tick"
- "yeti"

### Monster Modes

# MonsterModes
MonsterModes()

#### Mnemonics

- "locked"
- "losing lock"
- "lost lock"
- "unlocked"
- "running"

### Monsters

# MonsterTypes
MonsterTypes()
MonsterTypes[monster_type]
  .class

    class of monster type

  .enemies[monster_class]

    whether monster class is an enemy

  .friends[monster_class]

    whether monster class is a friend

  .impact_effect (read-only)

    type of effect generated when monster gets hit by a bleeding projectile

  .immunities[damage_type]

    whether monster type is immune to damage type

  .height (read-only)

    height of monster

  .item

    type of item the monster drops when it dies

  .melee_impact_effect (read-only)

    type of effect generated when monster gets hit by a melee projectile

  .radius (read-only)

    radius of monster

  .weaknesses[damage type]

    whether monster type has a weakness to damage type

#### Mnemonics

- "player"
- "minor tick"
- "major tick"
- "kamikaze tick"
- "minor compiler"
- "major compiler"
- "minor invisible compiler"
- "major invisible compiler"
- "minor fighter"
- "major fighter"
- "minor projectile fighter"
- "major projectile fighter"
- "green bob"
- "blue bob"
- "security bob"
- "explodabob"
- "minor drone"
- "major drone"
- "big minor drone"
- "big major drone"
- "possessed drone"
- "minor cyborg"
- "major cyborg"
- "minor flame cyborg"
- "major flame cyborg"
- "minor enforcer"
- "major enforcer"
- "minor hunter"
- "major hunter"
- "minor trooper"
- "major trooper"
- "mother of all cyborgs"
- "mother of all hunters"
- "sewage yeti"
- "water yeti"
- "lava yeti"
- "minor defender"
- "major defender"
- "minor juggernaut"
- "major juggernaut"
- "tiny pfhor"
- "tiny bob"
- "tiny yeti"
- "green vacbob"
- "blue vacbob"
- "security vacbob"
- "explodavacbob"

### Overlay Colors

# OverlayColors
OverlayColors()

#### Mnemonics

- "green"
- "white"
- "red"
- "dark green"
- "cyan"
- "yellow"
- "dark red"
- "blue"

### Platform Types

# PlatformTypes
PlatformTypes()

#### Mnemonics

- "spht door"
- "spht split door"
- "locked spht door"
- "spht platform"
- "noisy spht platform"
- "heavy spht door"
- "pfhor door"
- "heavy spht platform"
- "pfhor platform"

### Player and Team Colors

# PlayerColors
PlayerColors()

#### Mnemonics

- "slate"
- "red"
- "violet"
- "yellow"
- "white"
- "orange"
- "blue"
- "green"

### Polygons

# PolygonTypes
PolygonTypes()

#### Mnemonics

- "normal"
- "item impassable"
- "monster impassable"
- "hill"
- "base"
- "platform"
- "light on trigger"
- "platform on trigger"
- "light off trigger"
- "platform off trigger"
- "teleporter"
- "zone border"
- "goal"
- "visible monster trigger"
- "invisible monster trigger"
- "dual monster trigger"
- "item trigger"
- "must be explored"
- "automatic exit"
- "minor ouch"
- "major ouch"
- "glue"
- "glue trigger"
- "superglue"

### Projectiles

# ProjectileTypes
ProjectileTypes()

#### Mnemonics

- "missile"
- "grenade"
- "pistol bullet"
- "rifle bullet"
- "shotgun bullet"
- "staff"
- "staff bolt"
- "flamethrower burst"
- "compiler bolt minor"
- "compiler bolt major"
- "alien weapon"
- "fusion bolt minor"
- "fusion bolt major"
- "hunter"
- "fist"
- "armageddon sphere"
- "armageddon electricity"
- "juggernaut rocket"
- "trooper bullet"
- "trooper grenade"
- "minor defender"
- "major defender"
- "juggernaut missile"
- "minor energy drain"
- "major energy drain"
- "oxygen drain"
- "minor hummer"
- "major hummer"
- "durandal hummer"
- "minor cyborg ball"
- "major cyborg ball"
- "ball"
- "minor fusion dispersal"
- "major fusion dispersal"
- "overloaded fusion dispersal"
- "yeti"
- "sewage yeti"
- "lava yeti"
- "smg bullet"

### Scenery

# SceneryTypes
SceneryTypes()

#### Mnemonics

- "light dirt"
- "dark dirt"
- "lava bones"
- "lava bone"
- "ribs"
- "skull"
- "hanging light 1"
- "hanging light 2"
- "small cylinder"
- "large cylinder"
- "block 1"
- "block 2"
- "block 3"
- "pistol clip"
- "water short light"
- "water long light"
- "siren"
- "rocks"
- "blood drops"
- "water thing"
- "gun"
- "bob remains"
- "puddles"
- "big puddles"
- "security monitor"
- "water alien supply can"
- "machine"
- "staff"
- "sewage short light"
- "sewage long light"
- "junk"
- "antenna"
- "big antenna"
- "sewage alien supply can"
- "sewage bones"
- "sewage big bones"
- "pfhor pieces"
- "bob pieces"
- "bob blood"
- "alien short light"
- "alien long light"
- "alien ceiling rod light"
- "bulbous yellow alien object"
- "square gray organic object"
- "pfhor skeleton"
- "pfhor mask"
- "green stuff"
- "hunter shield"
- "alien bones"
- "alien sludge"
- "jjaro short light"
- "jjaro long light"
- "weird rod"
- "pfhor ship"
- "sun"
- "large glass container"
- "nub 1"
- "nub 2"
- "lh'owon"
- "floor whip antenna"
- "ceiling whip antenna"

### Scoring Modes

# ScoringModes
ScoringModes()

#### Mnemonics

- "most points"
- "most time"
- "least points"
- "least time"

### Side Types

# SideTypes
SideTypes()

#### Mnemonics

- "full"
- "high"
- "low"
- "split"

### Sounds

Sounds()

#### Mnemonics

- "startup"
- "teleport in"
- "teleport out"
- "crushed"
- "nuclear hard death"
- "absorbed"
- "breathing"
- "oxygen warning"
- "suffocation"
- "energy refuel"
- "oxygen refuel"
- "cant toggle switch"
- "switch on"
- "switch off"
- "puzzle switch"
- "chip insertion"
- "pattern buffer"
- "destroy control panel"
- "adjust volume"
- "got powerup"
- "get item"
- "bullet ricochet"
- "metallic ricochet"
- "empty gun"
- "spht door opening"
- "spht door closing"
- "spht door obstructed"
- "spht platform starting"
- "spht platform stopping"
- "loon"
- "smg firing"
- "smg reloading"
- "heavy spht platform starting"
- "heavy spht platform stopping"
- "fist hitting"
- "pistol firing"
- "pistol reloading"
- "assault rifle firing"
- "grenade launcher firing"
- "grenade expolding"
- "grenade flyby"
- "fusion firing"
- "fusion exploding"
- "fusion flyby"
- "fusion charging"
- "rocket exploding"
- "rocket flyby"
- "rocket firing"
- "flamethrower"
- "body falling"
- "body exploding"
- "bullet hit flesh"
- "fighter activate"
- "fighter wail"
- "fighter scream"
- "fighter chatter"
- "fighter attack"
- "fighter projectile hit"
- "fighter projectile flyby"
- "spht attack"
- "spht death"
- "spht hit"
- "spht projectile flyby"
- "spht projectile hit"
- "cyborg moving"
- "cyborg attack"
- "cyborg hit"
- "cyborg death"
- "cyborg projectile bounce"
- "cyborg projectile hit"
- "cyborg projectile flyby"
- "drone activate"
- "drone start attack"
- "drone attack"
- "drone dying"
- "drone death"
- "drone projectile hit"
- "drone projectile flyby"
- "bob wail"
- "bob scream"
- "bob hit"
- "bob chatter"
- "assimilated bob chatter"
- "bob trash talk"
- "bob apology"
- "bob activation"
- "bob clear"
- "bob angry"
- "bob secure"
- "bob kill the player"
- "water"
- "sewage"
- "lava"
- "goo"
- "underwater"
- "wind"
- "waterfall"
- "siren"
- "fan"
- "spht door"
- "spht platform"
- "alien harmonics"
- "heavy spht platform"
- "light machinery"
- "heavy machinery"
- "transformer"
- "sparking transformer"
- "water drip"
- "walking in water"
- "exiting water"
- "entering water"
- "small water splash"
- "medium water splash"
- "large water splash"
- "walking in lava"
- "entering lava"
- "exiting lava"
- "small lava splash"
- "medium lava splash"
- "large lava splash"
- "walking in sewage"
- "exiting sewage"
- "entering sewage"
- "small sewage splash"
- "medium sewage splash"
- "large sewage splash"
- "walking in goo"
- "exiting goo"
- "entering goo"
- "small goo splash"
- "medium goo splash"
- "large goo splash"
- "major fusion firing"
- "major fusion charged"
- "assault rifle reloading"
- "assault rifle shell casings"
- "shotgun firing"
- "shotgun reloading"
- "ball bounce"
- "you are it"
- "got ball"
- "computer login"
- "computer logout"
- "computer page"
- "heavy spht door"
- "heavy spht door opening"
- "heavy spht door closing"
- "heavy spht door open"
- "heavy spht door closed"
- "heavy spht door obstructed"
- "hunter activate"
- "hunter attack"
- "hunter dying"
- "hunter landing"
- "hunter exploding"
- "hunter projectile hit"
- "hunter projectile flyby"
- "enforcer activate"
- "enforcer attack"
- "enforcer projectile hit"
- "enforcer projectile flyby"
- "flickta melee attack"
- "flickta melee hit"
- "flickta projectile attack"
- "flickta projectile sewage hit"
- "flickta projectile sewage flyby"
- "flickta projectile lava hit"
- "flickta projectile lava flyby"
- "flickta dying"
- "machine binder"
- "machine bookpress"
- "machine puncher"
- "electric hum"
- "alarm"
- "night wind"
- "surface explosion"
- "underground explosion"
- "sphtkr attack"
- "sphtkr projectile hit"
- "sphtkr projectile flyby"
- "sphtkr hit"
- "sphtkr exploding"
- "tick chatter"
- "tick falling"
- "tick flapping"
- "tick exploding"
- "ceiling lamp exploding"
- "pfhor platform starting"
- "pfhor platform stopping"
- "pfhor platform"
- "pfhor door opening"
- "pfhor door closing"
- "pfhor door obstructed"
- "pfhor door"
- "pfhor switch off"
- "pfhor switch on"
- "juggernaut firing"
- "juggernaut warning"
- "juggernaut exploding"
- "juggernaut start attack"
- "enforcer exploding"
- "alien noise 1"
- "alien noise 2"
- "vacbob wail"
- "vacbob scream"
- "vacbob hit"
- "vacbob chatter"
- "assimilated vacbob chatter"
- "vacbob trash talk"
- "vacbob apology"
- "vacbob activation"
- "vacbob clear"
- "vacbob angry"
- "vacbob secure"
- "vacbob kill the player"

### Texture Types

# TextureTypes
TextureTypes()

#### Mnemonics

- "wall"
- "landscape"
- "sprite"
- "weapon in hand"
- "interface"

### Transfer Modes

# TransferModes
TransferModes()

#### Mnemonics

- "normal"
- "pulsate"
- "wobble"
- "fast wobble"
- "landscape"
- "horizontal slide"
- "fast horizontal slide"
- "vertical slide"
- "fast vertical slide"
- "wander"
- "fast wander"

### Weapons

# WeaponTypes
WeaponTypes()

#### Mnemonics

- "fist"
- "pistol"
- "fusion pistol"
- "assault rifle"
- "missile launcher"
- "flamethrower"
- "alien weapon"
- "shotgun"
- "ball"
- "smg"

# 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.
    ]]