Phaser AE

Sector map

Pro packv3.0.0-0LogicNew

The levels of a 2.5D shooter, as JSON a person or an editor can write: polygons with heights, and a handful of settings for doors, lifts, slime and triggers. Snap rooms together like a kit, or paint them as characters.

This is a Pro pack. Upgrade to Phaser Pro to use it in your games.See Phaser Pro →

Released October 24, 2026

Sector map: a screenshot of its demo
A note about these graphics

Expansion packs don't come with graphics. This screenshot is one way of drawing what the pack does, made for its demo: none of the sprites, tiles or backgrounds in it are in the pack.

That's by design. A pack is a game's logic, mechanics and effects, and it works with whatever art you give it. Some packs draw effects, backdrops or 3D scenes of their own, but none carries a game's sprites.

So the look is yours. Make the art on phaser.io, bring your own, or let your agent draw it in code: the same pack can look like anything.

The pack

sectorMap

function sectorMap(): Pack<{ sectorMap: typeof kit; }>

Compose the sector map, its format, kit-bash assembly and mesh builder under game.sectorMap.

Helpers

area

const area = (p: readonly Point[]): number=> …

Area.

assembleMap

function assembleMap(layout: MapLayout, kit: Record<string, KitPiece> = {}): SectorMapData

Put a map together from pieces. Each placement copies a piece in, turned, mirrored, moved and raised; its ids get the placement's id in front (room1.floor), except tags written with a leading @, which stay shared across the whole map. A join snaps a socket onto an earlier piece's socket, at any angle. Where pieces' edges touch they open onto each other, as in any sector map. Fixtures, signs, screens and flyers turn and move with their piece. Throws on an unknown piece or socket, a join that cannot be met, or sockets of different widths.

buildMeshes

function buildMeshes(map: SectorMap, opts: MeshOptions = {}): SectorMeshes

Build the meshes of a sector map.

centroid

function centroid(p: readonly Point[]): Point

The centroid of a polygon's area.

checkMap

function checkMap(data: SectorMapData): string[]

Check a map without building it: every problem found, as sentences an editor can show. Empty when the map is sound. createSectorMap throws on the first few.

createSectorMap

function createSectorMap(data: SectorMapData): SectorMap

Build a sector map from its data. Throws, naming the problems, on a map checkMap finds fault with.

fill

function fill(rings: readonly (readonly Point[])[]): { points: Point[]; tris: number[] }

Triangles filling the area inside an odd number of rings (even–odd): a floor outline with the shapes drawn inside it cut out, however those shapes touch one another. A sweep across z in slabs between corner heights, each slab split into trapezoids between pairs of crossing edges. More triangles than ear clipping, and never confused.

gridMap

function gridMap(g: GridMap): SectorMapData

A sector map from a grid of characters: each run of one character becomes as few rectangular sectors as it takes, with that character's settings, so a person (or a tile-painting editor) draws heights, doors, lifts, slime and secrets as easily as walls. Things come from the legend or by cell; so do windows, hinged doors and cabinets. Signs, screens and flyers are placed by cell (a screen's camera too).

inside

function inside(p: readonly Point[], x: number, z: number): boolean

Whether a point is strictly inside a polygon (even–odd), points on the edge counting as outside.

pieces

const pieces: { room(w: number, d: number, o?: PieceLook & { sockets?: Partial<Record<Facing, number>>; pool?: { w: number; d: number; depth: number; damage?: number; texture?: string; light?: number; }; dais?: { ...; }; pillars?: { ...; }; width?: number; }): KitPiece; ... 15 more ...; liftLedge(w: number, d: number, o?: PieceLo... …

Pieces made to measure. Every piece's origin is its centre, north is −z, and its sockets are named n, e, s, w (and top, bottom for stairs and lifts).

standardKit

function standardKit(): Record<string, KitPiece>

A ready kit of pieces at sensible sizes for a first-person shooter (a player about 1.8 tall): rooms, a hall, a courtyard, corridors, stairs, doors (plain, red, blue and yellow keyed, secret), a lift, an exit alcove, a slime room and a pillared hall; an octagonal hub, angled and curved bends, window walls (straight and zig-zag), a balcony room, curved and spiral stairs, a courtyard with a walkway, a slime canal with a bridge, a computer room, a toilet block, an office and a lift up to a ledge. Change the sizes by calling pieces yourself.

triangulate

function triangulate(outer: readonly Point[], holes: readonly (readonly Point[])[] = []): { points: Point[]; tris: number[] }

Triangles covering outer with holes cut out, as index triples into the returned points. The outer ring and the holes may wind either way; holes must lie inside the outer ring and not touch one another. Ear clipping after bridging each hole to the outer ring: quadratic, which is fine for the dozens of points a sector has.

Classes

SectorMap

class SectorMap

A 2.5D map of sectors, as the early-1990s shooters had: polygons with floor and ceiling heights and light, walls worked out from where the polygons touch, steps and lips between them, doors, lifts, crushers and platforms, light effects, damaging floors, secrets, and triggers on entering, using, crossing and shooting. It answers what a game asks each step: can this body move here (steps, headroom, drops), what is the floor under it, can these two points see each other through the openings, what does a shot hit, who hears a noise, and the way from here to there. Draw it with buildMeshes. Get one from createSectorMap.

  • readonly sectors: Sector[] — The sectors, in the order given.
  • readonly lines: Line[] — Walls and openings.
  • readonly bounds: [number, number, number, number] — The map's bounds: min x, min z, max x, max z.
  • constructor(data: SectorMapData, check = true)
  • placementProblems(): string[] — Problems with where fixtures, signs and screens are, as sentences (for checkMap).
  • fixture(id: string): number — A fixture's index by id, or −1.
  • hitFixture(id: string, damage: number, at?: { x: number; y: number; z: number }): MapEvent[] — Damage a fixture by id: a window loses damage hit points and breaks at none (a broken event, its break triggers, and the way through opened for routes); doors and cabinets shrug it off. Returns the events.
  • blastFixtures(x: number, y: number, z: number, radius: number, damage: number): MapEvent[] — A blast at x, y, z: every whole window within radius it can reach takes up to damage, less with distance.
  • shotBlocker(ax: number, ay: number, az: number, bx: number, by: number, bz: number): { fixture: string; x: number; y: number; z: number } | null — The nearest fixture that stops a shot between two points in 3D (a window between an enemy and the player), or null.
  • fixtures(): FixtureView[] — Fixtures as they are now, for a presenter: hinged doors, cabinets and windows with what each needs to be drawn.
  • fixtureState(index: number): FixtureState | null — Fixture state by index (a copy), or null.
  • signs(): SignView[] — Signs as they are now, for a presenter: where each hangs, its words, colours, frame and brightness.
  • screens(): ScreenView[] — Screens as they are now, for a presenter: where each is, what it shows, a terminal's lines on show and a camera's view.
  • flyers(): FlyerView[] — Flyers as they are now, for a presenter: where each is, its heading and climb, and its light.
  • get source(): SectorMapData — The data the map was built from (a copy).
  • sector(id: string): number — A sector's index by id, or −1.
  • sectorAt(x: number, z: number): number — The innermost sector a point is in (solid ones included), or −1 outside the map.
  • neighbours(index: number): number[] — Sectors sharing an opening with one.
  • linesOf(index: number): number[] — The lines (walls and openings) around a sector, by index.
  • floor(index: number): number — Floor height of a sector now.
  • ceiling(index: number): number — Ceiling height of a sector now.
  • light(index: number): number — Light of a sector now, 0 to 1, with its glow.
  • revision(index: number): number — How many times a sector's heights have changed: a presenter rebuilds its meshes when this moves.
  • floorAt(x: number, z: number, radius = 0): number — The floor under a point (the highest floor among sectors a body of radius touches there), or −Infinity outside.
  • ceilingAt(x: number, z: number, radius = 0): number — The ceiling over a point (the lowest a body of radius touches), or −Infinity outside.
  • lights(): (Required<Pick<MapLight, 'x' | 'z' | 'y' | 'color' | 'intensity' | 'radius' | 'flicker' | 'kind'>> & { cone: number | null; yaw: number; pitch: number; tag: string | null; on: boolean; sector: number; index: number })[] — The map's lights as they are now: each with its height worked out (0.4 below the ceiling where it stands, unless it says), the engine's yaw for a spot, the sector it is in, and whether it is lit. A spot's cone stays in degrees as written; yaw and pitch are radians.
  • things(skill?: string): (MapThing & { yaw: number; floorY: number; sector: number })[] — Things on the map for a skill (all when none is given), with the engine's yaw and their floor height.
  • gravityAt(x: number, z: number): number — Gravity at a point as a share of the game's: its sector's gravity (default 1), or 1 outside the map.
  • pushAt(x: number, y: number, z: number): { x: number; z: number } — The push on a body whose feet are at x, y, z, in units per second: a wind's anywhere in its sector, a conveyor's while the body stands on that sector's floor (feet within 0.05 of it). { x: 0, z: 0 } when nothing pushes.
  • launch(x: number, y: number, z: number, gravity: number): { x: number; y: number; z: number; sector: string; sound: string | null } | null — What a jump pad does to a body whose feet are at x, y, z: the velocity it throws it at (units per second, y up), the pad's sector id and its sound, or null unless the body stands on a pad's floor (feet within 0.05 of it). gravity is the game's pull in units per second squared, before this map's scale, which is taken where the body starts. A pad with to works out an arc that comes down there under that pull; with no pull at all, a straight line that takes a second. Throws on a gravity that is not a number.
  • opening(i: number): { low: number; high: number } — The opening of a line: the highest floor and the lowest ceiling of its two sides (closed for a wall).
  • fits(x: number, z: number, body: MoveBody): { ok: boolean; floor: number; ceiling: number } — Whether a body fits at a point: inside an open sector, clear of walls and blocking edges, with headroom, not stepping up more than its step and (an enemy) not standing over a drop deeper than its step. With the floor and ceiling it would have there.
  • move(x: number, z: number, dx: number, dz: number, body: MoveBody): { x: number; z: number; floor: number; ceiling: number; blocked: boolean } — Move a body by dx, dz, sliding along walls: the whole move if it fits, else along x or z alone, else not at all. Long moves go in steps no longer than the body's radius. Returns where it ends up, the floor and ceiling there, and whether anything stopped it. A fixture the body already overlaps (a door swung into it) lets it out.
  • sees(ax: number, az: number, bx: number, bz: number, ay?: number, by?: number): boolean — Whether two points see each other: no wall, closed door or step in the way, and no fixture that hides what is behind it (a hinged door's leaf, a cabinet, frosted glass). With heights (eyes), the line must pass through every opening it crosses and over or under fixtures; without, only walls, shut openings and fixtures block.
  • ray(x: number, y: number, z: number, yaw: number, pitch: number, max: number): MapRayHit | null — What a ray from x, y, z along yaw (the engine's) and pitch (positive looks down) hits within max units along the ground: a wall, a floor, a ceiling or a fixture (a door's leaf, a cabinet, a whole window: fixture names it), or null (it went out under the sky, or nothing in reach). With y NaN the ray is flat and only walls, shut openings and fixtures stop it.
  • hears(x: number, z: number, radius: number): Set<number> — The sectors a noise at x, z reaches within radius units, through openings that are not shut or quiet.
  • reach(fx: number, fz: number, body: MoveBody): (x: number, z: number) => number — How far a body would walk from fx, fz to anywhere, by one search: a function giving the walking distance in units to a point (Infinity where there is no way). For choosing among many goals at once (the nearest pickup); route then gives the way to the one chosen.
  • route(fx: number, fz: number, tx: number, tz: number, body: MoveBody): { x: number; z: number; door?: string }[] | null — The way from one point to another for a body, as points to walk to, next first, each that enters a door naming it (a door sector's id, or a hinged fixture's), or null when there is none. Unlocked doors count as open (and a running crusher as up: the walker times it), whole windows as shut, and a hinged door standing open is in the way where its leaf is; steps, drops and headroom are the body's; floors that hurt cost more, so the way goes round slime when it can. Fields toward a goal are shared for half a second of map time, so a crowd chasing the player costs one.
  • use(x: number, z: number, yaw: number, keys: readonly string[] = [], reach = 1.2): { result: MapUse; events: MapEvent[] } — Press use from x, z facing yaw, within reach units: a door or lift whose edge is ahead works (when keys holds its key), a use trigger on the wall ahead fires, and a fixture ahead (a hinged door, a cabinet) opens or shuts, firing its use triggers. Returns what happened and the events it caused.
  • visit(who: 'player' | 'enemy', fromX: number, fromZ: number, toX: number, toZ: number): MapEvent[] — A body moved from one point to another: fire enter, leave and cross triggers it set off, start a lift it stepped onto, and (the player) report a secret sector entered for the first time.
  • shot(line: number): MapEvent[] — The player shot line line: fire shoot triggers on it.
  • killed(tag: string): MapEvent[] — Something the game noticed: the last thing tagged tag died. Fires kill triggers for that tag.
  • fireTrigger(id: string, events: MapEvent[] = []): boolean — Fire a trigger by id, as if it had been set off (a script, a cut-scene). False when there is none.
  • tick(dt: number, bodies: readonly MapBody[] = []): MapEvent[] — Run the map on by dt seconds (0 to 10): start triggers on the first step, delayed actions, doors, lifts, crushers, platforms and moves, hinged doors and cabinets, and flyers. bodies are what stands in the map: a door going down on one goes back up, a hinged door swinging shut into one swings open again, a crusher hurts one it catches, and a floor that does damage hurts one standing on it.
  • enemyWorld(): SectorEnemyWorld — The map as fps-enemies needs it: pass it to createHorde(config, map.enemyWorld()). Doors are named by sector id, hinged doors by fixture id; enemies open hinged doors that are neither locked nor keyed.
  • get time(): number — Seconds the map has run.
  • get secretsFound(): string[] — Secret sectors found so far, by id.
  • get secretCount(): number — How many sectors are secrets.
  • mover(index: number): MoverState | null — A mover's state by sector index, or null.
  • get state(): SectorMapState — A copy of the state: everything a save needs.
  • restore(state: SectorMapState): void — Put back a saved state of this map. Throws on one that does not fit.

SectorMeshes

class SectorMeshes

The meshes of a sector map. groups lists every piece; verts(key) builds a piece's triangles at the map's current heights; changed() names the pieces whose sectors have moved since it was last asked.

  • readonly groups: MeshGroup[] — Every piece.
  • constructor(map: SectorMap, opts: MeshOptions = {})
  • changed(): string[] — The pieces whose sectors' heights have changed since the last call (or since the meshes were built).
  • verts(key: string): Float32Array — A piece's triangles at the current heights: 8 floats a vertex (x, y, z, normal x, y, z, u, v). Empty when it has nothing to show now.

Types

AirPoint

type AirPoint = [number, number, number]

A point in the air: [x, z, y], y the height above the map's zero.

CabinetFixture

interface CabinetFixture extends FixtureBase

A box that opens: a cabinet, a locker, a filing drawer, a chest. It stands in the way of bodies, sight and shots like a block of its size, and the first time it opens the game is told its contents, to spawn in front of it.

  • kind: 'cabinet' — 'cabinet'.
  • at: Point — The middle of its footprint, [x, z].
  • facing?: number — The way its front faces, degrees clockwise from north; default 0.
  • size?: [number, number, number] — Width along the front, depth and height, each above 0 and at most 20; default [0.8, 0.5, 1.8] (a locker).
  • y?: number — Its base above the floor (a cupboard hung on a wall); default 0.
  • opens?: 'door' | 'drawer' | 'lid' — How it opens: 'door' (on a hinge at its left edge), 'drawer' (slides out) or 'lid' (lifts); default 'door'.
  • look?: string — What it looks like, for the presenter: 'locker', 'cabinet', 'filing', 'safe', 'chest' or the game's own; default 'cabinet'.
  • contents?: string[] — Thing types it holds (pickups, or an enemy that jumps out), given to the game the first time it opens.
  • time?: number — Seconds it takes to open or shut, above 0; default 0.4.
  • open?: boolean — Starts open (its contents already taken). Default false.

CabinetView

interface CabinetView extends FixtureViewBase

A cabinet, as a presenter draws it: a box size at at, its front toward facing, opening by opens.

  • kind: 'cabinet' — 'cabinet'.
  • at: Point — The middle of its footprint.
  • facing: number — The way its front faces, compass degrees.
  • yaw: number — The engine's yaw of the way its front faces.
  • size: [number, number, number] — Width, depth, height.
  • y: number — Its base height in the world.
  • opens: 'door' | 'drawer' | 'lid' — 'door', 'drawer' or 'lid'.
  • look: string — What it looks like.
  • contents: string[] — What is still inside: empty once it has been opened.

Facing

type Facing = 'n' | 'e' | 's' | 'w'

A compass direction: which way a socket faces out of its piece.

FixtureBase

interface FixtureBase

What every fixture has.

  • id: string — Unique id among the fixtures; triggers and actions name it.
  • tag?: string — A group name: an action naming it reaches every fixture with it.
  • key?: string — A key the player needs to open it, by name ('red'); default none.
  • locked?: boolean — Starts locked: use does nothing until an unlock action. Default false.
  • sounds?: FixtureSounds — Sounds.
  • texture?: string — Its texture, for the presenter.

FixturePhase

type FixturePhase = 'opening' | 'open' | 'closing' | 'closed' | 'hit' | 'broken' | 'locked' | 'unlocked' | 'refused'

What happened to a fixture: it started opening, came open, started closing, came closed; a window was hit and held, or broken; it was locked or unlocked by an action; or use found it refused (locked).

FixtureSounds

interface FixtureSounds

Sounds a fixture makes, by name, played where it is.

  • open?: string — As it starts to open.
  • close?: string — As it starts to shut.
  • locked?: string — Used while locked.
  • break?: string — A window breaking.
  • hit?: string — A window struck but holding.

FixtureState

interface FixtureState

A fixture's state.

  • open: number — How far open, 0 (shut) to 1 (open); a window is 0 whole and 1 broken.
  • target: 0 | 1 — Where it is heading: 0 (shutting) or 1 (opening).
  • side: 1 | -1 — A hinged door's swing: 1 clockwise, −1 the other way.
  • locked: boolean — Locked by locked or a lock action (a key is separate).
  • hp: number — A window's hit points left.
  • timer: number — Seconds before an open door with autoClose shuts.
  • given: boolean — A cabinet's contents have been handed out.

FixtureView

type FixtureView = HingedView | CabinetView | WindowView

A fixture as a presenter sees it now.

FlyerView

interface FlyerView

A flyer as a presenter draws it.

  • index: number — Its index.
  • id: string — Its id.
  • tag: string | null — Its tag, or null.
  • kind: string — What it is.
  • x: number — Where it is now (a beam's: where it lands).
  • y: number — Height.
  • z: number — Where it is now.
  • heading: number — The way it is heading, compass degrees (a beam: the way it shines).
  • yaw: number — The engine's yaw of its heading.
  • pitch: number — Its climb, radians, positive down (a beam: how steeply it shines down).
  • on: boolean — Moving now.
  • size: number — Scale.
  • from: AirPoint | null — A beam's fixed end, or null.
  • light: { color: string; intensity: number; radius: number; cone: number | null } | null — The light it carries, or null.
  • sound: string | null — A looping sound, or null.

GridCell

interface GridCell

What a grid character means: the sector settings its cells get, and maybe a thing standing on it.

  • floor?: number — Floor height.
  • ceiling?: number — Ceiling height.
  • light?: number — Light.
  • wall?: string — Wall texture.
  • side?: string — Step and lip texture.
  • floorTexture?: string — Floor texture.
  • ceilingTexture?: string — Ceiling texture.
  • sky?: boolean — Open to the sky.
  • solid?: boolean — Solid (a pillar inside the map).
  • mover?: SectorMover — A door, lift, crusher or platform.
  • damage?: number — Damage per second.
  • secret?: boolean — A secret.
  • tag?: string — A tag for triggers.
  • glow?: SectorGlow — A light effect.
  • jump?: SectorJump & { cell?: [number, number] } — A jump pad, landing at to in world units or at the middle of cell ([column, row]).
  • gravity?: number — Gravity as a share of the game's.
  • push?: SectorPush — A conveyor or a wind.
  • liquid?: boolean — The floor is a liquid.
  • floorFx?: SurfaceFx — How the floor moves and shimmers.
  • ceilingFx?: SurfaceFx — How the ceiling moves and shimmers.
  • wallFx?: SurfaceFx — How the walls move and shimmer.
  • window?: { texture?: string } — A window: give the cell a sill and lintel by its floor and ceiling, and this hangs texture (default 'glass') across its openings, which bodies cannot cross.
  • hinged?: Omit<HingedFixture, 'id' | 'kind' | 'hinge' | 'width' | 'facing' | 'direction'> & { side: Facing; hinge?: 'start' | 'end'; outward?: boolean } — A hinged door on every cell of this character, along the cell's side, hinged at its hinge end ('start', the west or north end, or 'end'), swinging into the cell (or out of it, outward). Ids are the area's id with -door, -door-2… after it.
  • cabinet?: Omit<CabinetFixture, 'id' | 'kind' | 'at'> & { against?: Facing } — A cabinet on every cell of this character: in its middle, or pushed against one side and facing away from it. Ids as for hinged, with -cabinet.
  • id?: string — A sector id for this character's first area (later ones get -2, -3…); default from the character.
  • thing?: string — A thing on every cell of this character, by type, facing north unless facing says.
  • facing?: number — The thing's facing in degrees.

GridMap

interface GridMap

A map painted as rows of characters: each character a kind of cell, cell units square.

  • rows: string[] — The rows, north first. A space, or a character the legend leaves out, is solid rock.
  • legend: Record<string, GridCell> — What each character means.
  • cell?: number — Cell size in world units; default 2.
  • things?: (Omit<MapThing, 'x' | 'z'> & { at: [number, number] })[] — Things placed by cell: at: [column, row], standing in the cell's middle.
  • triggers?: MapTrigger[] — Triggers, naming sectors by the legend's ids and tags.
  • lights?: (Omit<MapLight, 'x' | 'z'> & { at: [number, number] })[] — Lights placed by cell: at: [column, row], in the cell's middle.
  • signs?: ByCell<MapSign>[] — Signs placed by cell, standing or hanging at the cell's middle.
  • screens?: ByCell<MapScreen>[] — Screens placed by cell.
  • flyers?: (Omit<MapFlyer, 'path' | 'from'> & { path: AirPoint[]; from?: AirPoint })[] — Flyers whose path points are [column, row, y], in the cells' middles.
  • fixtures?: MapFixture[] — Fixtures, in world units (a hinge belongs on a cell's edge, not its middle).
  • name?: string — A name for the map.
  • sky?: string — The sky texture.
  • defaults?: MapDefaults — Defaults.
  • meta?: Record<string, unknown> — Anything else to keep with the map (par time, music).

HingedFixture

interface HingedFixture extends FixtureBase

A door on a hinge: a toilet stall's, a gate, one leaf of a saloon door, a cupboard's. The leaf runs width from the hinge toward facing while shut and swings swing degrees open. While shut or part open, the leaf blocks bodies and sight, and shots too unless it is a grate.

  • kind: 'hinged' — 'hinged'.
  • hinge: Point — The hinge, [x, z].
  • width: number — The leaf's length from the hinge, above 0 and at most 20.
  • facing: number — The way the shut leaf runs from the hinge, degrees clockwise from north.
  • swing?: number — How far it swings open, degrees, above 0 and at most 180; default 90.
  • direction?: 'cw' | 'ccw' | 'both' — Which way it swings seen from above: 'cw' (clockwise), 'ccw', or 'both' (away from whoever uses it); default 'cw'.
  • height?: number — The leaf's height, above 0; default 2.1.
  • bottom?: number — The gap under the leaf, 0 or more (a stall door has about 0.25); default 0.
  • thickness?: number — The leaf's thickness, above 0 and at most 1; default 0.08.
  • speed?: number — Degrees per second it swings, above 0; default 240.
  • autoClose?: number — Seconds it stays open before it swings shut by itself, above 0; default never.
  • open?: boolean — Starts open. Default false.
  • grate?: boolean — Bars or a grille: it blocks bodies, but sight and shots pass. Default false.

HingedView

interface HingedView extends FixtureViewBase

A hinged door, as a presenter draws it: a box width × height × thickness from hinge to tip.

  • kind: 'hinged' — 'hinged'.
  • hinge: Point — The hinge.
  • tip: Point — The far end of the leaf now.
  • facing: number — The way the leaf runs from the hinge now, compass degrees.
  • yaw: number — The engine's yaw of the way the leaf's face looks now (the leaf's run turned 90° clockwise).
  • centre: [number, number, number] — The middle of the leaf now: x, y (half-way up it) and z.
  • width: number — Its length, height, the gap under it and its thickness.
  • height: number — Leaf height.
  • bottom: number — Gap under it.
  • thickness: number — Leaf thickness.
  • y: number — The floor under it.
  • grate: boolean — Bars: sight and shots pass.

KitPiece

interface KitPiece

A reusable piece of map: sectors, things and triggers in its own coordinates, and its sockets.

  • sectors: SectorDef[] — Sectors, ids local to the piece.
  • things?: MapThing[] — Things.
  • triggers?: MapTrigger[] — Triggers; they name the piece's own sectors, tags and fixtures.
  • lights?: MapLight[] — Lights, in the piece's own coordinates.
  • fixtures?: MapFixture[] — Fixtures (hinged doors, cabinets, windows), ids local to the piece.
  • signs?: MapSign[] — Signs, in the piece's own coordinates.
  • screens?: MapScreen[] — Screens, in the piece's own coordinates.
  • flyers?: MapFlyer[] — Flyers, their paths in the piece's own coordinates and heights.
  • sockets?: Record<string, Socket> — Sockets by name.

Line

interface Line

A wall or opening between two sectors, worked out from where their edges touch.

  • a: Point — One end.
  • b: Point — The other end. The front sector lies to the left going from a to b, seen from above with z up the page.
  • front: number — The sector in front (never −1).
  • back: number — The sector behind, or −1 for a solid wall.
  • owners: { sector: number; edge: number }[] — The polygon edges it came from: { sector, edge }.
  • block: boolean — Bodies may not cross.
  • blockEnemies: boolean — Enemies may not cross.
  • quiet: boolean — Sound does not cross.
  • middle: string — A see-through texture hung across the opening, or ''.
  • middleHeight: number | null — How high middle reaches from the bottom of the opening, or null for all of it.

MapBody

interface MapBody

A body the map moves and pushes: the player, an enemy.

  • id: string — Who it is, for crush events.
  • x: number — Position.
  • z: number — Position.
  • y: number — Feet height.
  • radius: number — Radius.
  • height: number — Height.

MapDefaults

interface MapDefaults

Map-wide defaults and settings.

  • floor?: number — Floor height; default 0.
  • ceiling?: number — Ceiling height; default 4.
  • light?: number — Light; default 1.
  • wall?: string — Wall texture; default 'wall'.
  • floorTexture?: string — Floor texture; default 'floor'.
  • ceilingTexture?: string — Ceiling texture; default 'ceiling'.

MapEvent

type MapEvent = | { type: 'mover'; sector: string; phase: string } | { type: 'sound'; sound: string; x: number; y: number; z: number } | { type: 'crush'; body: string; damage: number } | { type: 'secret'; sector: string } | { type: 'trigger'; trigger: string } | { type: 'action'; trigger: string; action: TriggerAction } | { type: 'locked'; key: string } | { type: 'hurt'; body: string; damage: number } | { type: 'fixture'; fixture: string; phase: FixturePhase; x: number; y: number; z: number } | { type: 'contents'; fixture: string; things: string[]; x: number; y: number; z: number; facing: number } | { type: 'sign'; sign: string } | { type: 'screen'; screen: string } | { type: 'flyer'; flyer: string; phase: 'start' | 'stop' | 'end' }

What a step of the map did.

MapFixture

type MapFixture = HingedFixture | CabinetFixture | WindowFixture

Something that opens or breaks.

MapFlyer

interface MapFlyer

Something moving along a path through the air or the sky: a ship, a drone, birds, a blimp, or a searchlight's beam sweeping along the ground. The map moves it, deterministically, and keeps where it is in its state.

  • id?: string — Unique id, for start and stop actions; default its place in the list.
  • tag?: string — A group name for start and stop.
  • kind: string — What it is, by name, for the presenter: 'ship', 'drone', 'bird', 'blimp', 'searchlight' or the game's own.
  • path: AirPoint[] — The way it flies, 2 or more points.
  • speed?: number — Units per second, above 0; default 4.
  • mode?: 'loop' | 'pingpong' | 'once' — 'loop' (back to the first point and round again), 'pingpong' (back and forth) or 'once' (stops at the end); default 'loop'.
  • curve?: boolean — Fly a smooth curve through the points rather than straight between them. Default false.
  • on?: boolean — Moving at the start. Default true.
  • start?: number — How far along the path it starts, 0 to 1; default 0.
  • from?: AirPoint — A beam: it stands at this fixed point and shines at the moving point (a searchlight sweeping the yard).
  • light?: { color?: string; intensity?: number; radius?: number; cone?: number } — A light it carries (a beam's shines from from toward the moving point).
  • size?: number — Scale for the presenter's model, above 0; default 1.
  • sound?: string — A looping sound by name, to play where it is.

MapLayout

interface MapLayout

A map put together from pieces.

  • name?: string — A name for the map.
  • sky?: string — The sky texture.
  • defaults?: MapDefaults — Defaults for sectors.
  • pieces?: Record<string, KitPiece> — Pieces this layout defines for itself, beside the kit's.
  • place: Placement[] — The pieces placed, in order: a join may only name a piece placed before it.
  • sectors?: SectorDef[] — More sectors, with ids of their own.
  • things?: MapThing[] — More things.
  • triggers?: MapTrigger[] — More triggers: they name pieces' sectors as <placement id>.<local id>.
  • lights?: MapLight[] — More lights, in map coordinates.
  • fixtures?: MapFixture[] — More fixtures, in map coordinates.
  • signs?: MapSign[] — More signs, in map coordinates.
  • screens?: MapScreen[] — More screens, in map coordinates.
  • flyers?: MapFlyer[] — More flyers, in map coordinates.
  • meta?: Record<string, unknown> — Anything else to keep with the map.

MapLight

interface MapLight

A light the map places: a lamp over a door, a torch on a wall, a green glow over slime, a red emergency light. The map keeps it (on or off); the game turns it into a real light.

  • x: number — Position in world units.
  • z: number — Position in world units.
  • y?: number — Height; default 0.4 below the ceiling of the sector it is in.
  • color?: string — Colour, CSS; default '#ffffff'.
  • intensity?: number — Brightness (inverse-square units: a lamp lighting a room 6 units across wants about 4 to 10); default 6.
  • radius?: number — How far it reaches; default 8.
  • flicker?: number — Flicker, 0 (steady) to 1 (a guttering torch); default 0.
  • cone?: number — A spot: the cone's half-angle in degrees; default none (a point light).
  • facing?: number — A spot's direction, degrees clockwise from north; default 0.
  • pitch?: number — A spot's tilt down, degrees; default 0.
  • tag?: string — A group name, for lamp actions.
  • on?: boolean — Lit at the start; default true.
  • kind?: 'lamp' | 'torch' | 'glow' — What it looks like, for the presenter: a 'lamp' fixture, a 'torch' flame, or a 'glow' with no visible source; default 'lamp'.

MapRayHit

interface MapRayHit

Where a ray stopped.

  • dist: number — Distance along the ground.
  • x: number — Where it stopped.
  • y: number — Where it stopped.
  • z: number — Where it stopped.
  • kind: 'wall' | 'floor' | 'ceiling' | 'fixture' — What it hit.
  • line: number — The line hit, or −1 for a floor, a ceiling or a fixture.
  • sector: number — The sector whose surface it hit (for a wall, the side it came from; for a fixture, the sector it stands in).
  • fixture?: string — The fixture hit (a door's leaf, a cabinet, a window), by id; only with kind 'fixture'.

MapScreen

interface MapScreen extends MountPlace

A screen on a wall, or a hologram standing in the air.

  • id?: string — Unique id, for screen actions; default its place in the list.
  • tag?: string — A group name for screen actions.
  • kind: ScreenKind — - 'terminal': lines of text scrolling up, rows at a time. - 'video': a video from src. - 'static': snow. - 'image': the picture picture. - 'hologram': picture (or lines) standing in the air, see-through, turning spin degrees a second. - 'map': the level from above, the region of it. - 'camera': what camera sees.
  • lines?: string[] — Terminal and hologram: the text.
  • rows?: number — Terminal: lines shown at once, 1 to 60; default 6.
  • scroll?: number — Terminal: lines per second it scrolls, 0 (still) to 60; default 0.5.
  • src?: string — Video: its address.
  • picture?: string — Image and hologram: a picture name.
  • region?: [number, number, number, number] — Map: the part of the level it shows, [x0, z0, x1, z1]; default all of it.
  • camera?: ScreenCamera — Camera: where it looks from.
  • color?: string — Text or tint colour, CSS; default '#7dffb0'.
  • background?: string — Background colour, CSS; default '#04100a'.
  • glow?: number — How much light of its own it gives, 0 to 1; default 0.9.
  • flicker?: number — Flicker, 0 to 1; default 0.
  • spin?: number — Hologram: degrees a second it turns; default 0.
  • on?: boolean — On at the start. Default true.

MapSign

interface MapSign extends MountPlace

Text on a wall or hanging: a room number, a warning, an exit sign, a neon name.

  • id?: string — Unique id, for sign actions; default its place in the list.
  • tag?: string — A group name for sign actions.
  • text: string — The words; \n breaks a line.
  • color?: string — Text colour, CSS; default '#ffffff'.
  • background?: string — Background colour, CSS; default '#22262c', 'transparent' for none (letters on the wall).
  • glow?: number — How much light of its own it gives, 0 (lit by the room) to 1; default 0, or 0.8 for neon and screen frames.
  • flicker?: number — Flicker, 0 (steady) to 1 (a failing tube); default 0.
  • frame?: 'plate' | 'neon' | 'screen' | 'poster' — 'plate' (a fixed panel), 'neon' (glowing tubes), 'screen' (a lit panel) or 'poster' (paper); default 'plate'.
  • picture?: string — A picture drawn beside the text (an arrow, a hazard mark, a person), by name, the presenter's.
  • hanging?: boolean — Hanging from the ceiling, readable from both sides. Default false.
  • on?: boolean — Lit at the start. Default true.

MapThing

interface MapThing

A thing on the map: where the player starts, an enemy, a pickup, a prop, a decoration, by type.

  • type: string — What it is, by name: 'start', an enemy kind, an item, a prop (a barrel, a crate), anything the game knows.
  • x: number — Position in world units.
  • z: number — Position in world units.
  • facing?: number — Which way it faces, degrees clockwise from north (0 north, 90 east); default 0.
  • y?: number — Height above the floor (a floating pickup); default 0.
  • skill?: string[] — The skill levels it appears on, by name (['normal', 'hard']); default all.
  • ambush?: boolean — An enemy that waits for sight, deaf to shots. Default false.
  • patrol?: boolean — An enemy that walks a beat. Default false.
  • tag?: string — A group name, for kill triggers (the last enemy or breakable prop with it gone).

MapTrigger

interface MapTrigger

When something happens, and what.

  • id?: string — Unique id, for enable and disable; default its place in the list.
  • on: TriggerOn — - 'enter' / 'leave': a body enters or leaves sector, any sector tagged tag, or the region polygon. - 'use': the player presses use facing wall. - 'cross': a body crosses wall or line. - 'shoot': the player shoots wall. - 'start': when the map starts. - 'kill': the last thing tagged tag dies (the game reports it). - 'use' with fixture: the player uses that fixture (a cabinet, a hinged door) and it opens or shuts. - 'break': the window fixture breaks.
  • fixture?: string — A fixture's id, for use and break.
  • sector?: string — A sector, for enter and leave.
  • tag?: string — A sector tag (enter, leave) or a thing tag (kill).
  • region?: Point[] — A polygon, for enter and leave.
  • wall?: { sector: string; edge: number } — A wall: a sector's edge.
  • line?: [Point, Point] — A line anywhere, for cross.
  • by?: 'player' | 'enemy' | 'any' — Who sets it off: 'player' (default), 'enemy' or 'any'.
  • once?: boolean — Fires once, then is spent; default true.
  • delay?: number — Seconds after it fires that its actions happen; default 0.
  • key?: string — A key the player needs for it to work (use).
  • disabled?: boolean — Starts switched off until an enable action; default false.
  • do: TriggerAction[] — What happens.

MapUse

type MapUse = | { type: 'door'; sector: string; opening: boolean } | { type: 'lift'; sector: string } | { type: 'locked'; key: string } | { type: 'switch'; trigger: string } | { type: 'fixture'; fixture: string; opening: boolean } | { type: 'nothing' }

What pressing use did.

MeshGroup

interface MeshGroup

One drawable piece of the map.

  • key: string — A stable key: '<sector>:<part>:<texture>', with ~ and its motion after it when it scrolls, animates, has an effect or is a liquid.
  • sector: number — The sector it belongs to (its light).
  • part: 'floor' | 'ceiling' | 'wall' | 'middle' — 'floor', 'ceiling', 'wall', or 'middle' (a see-through texture hung across an opening, drawn both sides).
  • texture: string — The texture name.
  • deps: number[] — Sectors whose heights change it.
  • scroll: [number, number] — Texture repeats per second it scrolls along u and v ([0, 0] for still): add scroll × seconds to its uvs.
  • animate: number — Frames per second of an animated texture; 0 for a still one.
  • effect: SurfaceEffect | null — A surface effect to draw it with (ripple, shine, holo, glow, frost, fire), or null.
  • liquid: boolean — A floor that is a liquid (water, slime, lava).

MeshOptions

interface MeshOptions

How meshes are built.

  • wallScale?: number — World units one repeat of a wall texture covers; default 2.
  • flatScale?: number — World units one repeat of a floor or ceiling texture covers; default 2.

MountPlace

interface MountPlace

Where a sign or screen is: on a wall, or standing (or hanging) at a point.

  • wall?: { sector: string; edge: number } — On a wall: a sector's edge; it faces into that sector.
  • along?: number — With wall: how far along the edge its middle is, 0 to 1; default 0.5.
  • at?: Point — Instead of wall: its middle, [x, z].
  • facing?: number — With at: the way its face looks, degrees clockwise from north; default 0.
  • y?: number — Height of its middle above the floor where it is.
  • size?: [number, number] — Width and height in units, each above 0 and at most 40.

MountView

interface MountView

Where a sign or a screen is, as a presenter places it: a quad width × height at x, y, z, facing yaw.

  • index: number — Its index in the list.
  • id: string — Its id.
  • tag: string | null — Its tag, or null.
  • x: number — Its middle.
  • y: number — Its middle's height in the world.
  • z: number — Its middle.
  • facing: number — The way its face looks, compass degrees.
  • yaw: number — The engine's yaw of the way its face looks.
  • width: number — Width.
  • height: number — Height.
  • on: boolean — On now.
  • brightness: number — How bright now, 0 to 1, with its flicker (0 while off).
  • glow: number — How much light of its own it gives.
  • sector: number — The sector it is in.
  • rev: number — How many times it has changed: redraw its face when this moves.

MoveBody

interface MoveBody

How a body moves: its size and how it climbs.

  • radius: number — Radius, above 0.
  • height: number — Height, above 0.
  • step: number — Highest step it walks up.
  • y: number — Feet height now.
  • fly?: boolean — A flyer: no step limit, no drop limit.
  • enemy?: boolean — An enemy: kept off blockEnemies edges and away from drops deeper than its step.
  • keys?: readonly string[] — For routes: keys it holds, so doors locked with them count as a way through.
  • drop?: number — For routes: the deepest drop it will walk off; default its step (the player can drop any height: pass Infinity).

MoverState

interface MoverState

A mover's state.

  • kind: SectorMover['kind'] — Its kind.
  • phase: string — 'closed' | 'opening' | 'open' | 'closing' for doors, 'up' | 'lowering' | 'down' | 'raising' otherwise.
  • timer: number — Seconds left waiting.
  • on: boolean — Crushers and platforms: running.
  • top: number — The top height it moves to.
  • bottom: number — The bottom height it moves to.

PieceLook

interface PieceLook

Surfaces and settings any piece may take.

  • floor?: number — Floor height; default 0.
  • ceiling?: number — Ceiling height; default 4 (stairs: their top step plus 4).
  • light?: number — Light 0..1; default 1.
  • wall?: string — Wall texture.
  • floorTexture?: string — Floor texture.
  • ceilingTexture?: string — Ceiling texture.
  • sky?: boolean — Open to the sky.
  • tag?: string — A tag for triggers.
  • glow?: SectorGlow — A light effect.
  • secret?: boolean — Counts as a secret when entered.
  • damage?: number — Damage per second on the floor.
  • jump?: SectorJump — A jump pad on the floor, in the piece's own coordinates.
  • gravity?: number — Gravity as a share of the game's.
  • push?: SectorPush — A conveyor or a wind, heading in the piece's own degrees.
  • liquid?: boolean — The floor is a liquid.
  • floorFx?: SurfaceFx — How the floor moves and shimmers.
  • ceilingFx?: SurfaceFx — How the ceiling moves and shimmers.
  • wallFx?: SurfaceFx — How the walls move and shimmer.

Placement

interface Placement

One piece put into a map.

  • id: string — Unique id: the piece's sector, tag, trigger and fixture ids become <id>.<local id>.
  • piece: string | KitPiece — A piece name in the kit, or a piece itself.
  • at?: Point — Where its origin goes; default [0, 0], or worked out by join.
  • turn?: number — Degrees clockwise seen from above, any angle (0, 90, 180 and 270 keep whole-number corners); default 0, or worked out by join.
  • mirror?: boolean — Mirror it east to west before turning. Default false.
  • join?: { socket: string; to: string } — Snap its socket onto socket to ('<placement id>.<socket>') of a piece placed earlier: turned to face it, moved onto it and raised to its height.
  • raise?: number — Added to every height in the piece; default 0, or the joined socket's height.
  • light?: number — Every sector's light, overriding the piece's.
  • textures?: Record<string, string> — Textures renamed: { stone: 'brick' }.
  • things?: MapThing[] — Things placed in this piece, in its own coordinates (they turn and move with it): how a level puts enemies and pickups in a room.
  • triggers?: MapTrigger[] — Triggers belonging to this piece, naming its sectors by their local ids, in its own coordinates.
  • lights?: MapLight[] — Lights placed in this piece, in its own coordinates: a lamp over the door, torches along the walls.
  • fixtures?: MapFixture[] — Fixtures placed in this piece, in its own coordinates.
  • signs?: MapSign[] — Signs placed in this piece, in its own coordinates (a wall sign names the piece's sector by its local id).
  • screens?: MapScreen[] — Screens placed in this piece, in its own coordinates.
  • flyers?: MapFlyer[] — Flyers placed in this piece, in its own coordinates.
  • set?: Record<string, Partial<SectorDef>> — Settings merged into some of its sectors, by local id: { room: { light: 0.4, glow: { kind: 'flicker' } } }.

Point

type Point = [number, number]

A point seen from above: [x, z] in world units, x east, z south.

ScreenCamera

interface ScreenCamera

A security camera's view, for a 'camera' screen.

  • at: Point — Where the camera is, [x, z].
  • y?: number — Its height above the floor there; default 0.3 below the ceiling.
  • facing: number — The way it looks, degrees clockwise from north.
  • pitch?: number — How far it looks down, degrees; default 20.
  • fov?: number — Its field of view, degrees, above 0 and below 180; default 70.

ScreenKind

type ScreenKind = 'terminal' | 'video' | 'static' | 'image' | 'hologram' | 'map' | 'camera'

What a screen shows.

ScreenView

interface ScreenView extends MountView

A screen as a presenter draws it.

  • kind: ScreenKind — What it shows now.
  • lines: string[] — Its text lines.
  • rows: number — Terminal rows shown at once.
  • offset: number — Lines scrolled so far (a terminal's), fractional: the presenter may slide the text by the fraction.
  • shown: string[] — The rows lines on show now, a terminal's (the text wraps round).
  • src: string — Video address, or ''.
  • picture: string — Picture name, or ''.
  • region: [number, number, number, number] — Map: the region shown, [x0, z0, x1, z1].
  • camera: { x: number; y: number; z: number; yaw: number; pitch: number; fov: number } | null — Camera: where it looks from, the engine's yaw and pitch (radians, positive down) and its field of view in degrees; null for other kinds.
  • color: string — Text or tint colour.
  • background: string — Background colour.

Sector

interface Sector

A sector as compiled: its authored settings and where it sits among the others.

  • id: string — Its id.
  • index: number — Its index in sectors.
  • points: Point[] — Its outline.
  • def: SectorDef — The authored settings.
  • parent: number — The sector it was drawn inside, or −1.
  • children: number[] — Sectors drawn inside it.
  • centre: Point — Its centre.
  • area: number — Area, square units.

SectorDef

interface SectorDef

One area of the map: a polygon with a floor and a ceiling.

  • id: string — Unique id; triggers and things refer to it.
  • points: Point[] — The outline, 3 or more points, either way round, not crossing itself.
  • floor?: number — Floor height; default the map's (0).
  • ceiling?: number — Ceiling height; default the map's (4). For a door, its open height.
  • light?: number — Light, 0 (black) to 1 (full); default the map's (1).
  • floorTexture?: string — Floor texture.
  • ceilingTexture?: string — Ceiling texture.
  • wall?: string — Wall texture for its edges.
  • side?: string — Texture for the faces it shows its neighbours where it is higher or lower: a dais's sides, a door's face; default wall.
  • edges?: Record<string, SectorEdge> — Per-edge settings by edge index ("0", "1"…).
  • sky?: boolean — Open to the sky: no ceiling is drawn, and an upper face between two sky sectors is not. Default false.
  • solid?: boolean — Solid through (a pillar, a block of rock): nothing enters it. Default false.
  • mover?: SectorMover — A door, lift, crusher or platform.
  • damage?: number — Damage per second to a body standing on its floor (slime, lava); default 0.
  • secret?: boolean — Counts as a secret when the player first enters it. Default false.
  • tag?: string — A group name for triggers and actions (several sectors may share one).
  • glow?: SectorGlow — A light effect.
  • jump?: SectorJump — A jump pad on its floor.
  • gravity?: number — Gravity in it as a share of the game's, 0 (none) to 10; default 1. Below 1 is a low-gravity room.
  • push?: SectorPush — A conveyor on its floor, or a wind through it.
  • liquid?: boolean — Its floor is a liquid (water, slime, lava): for the presenter, which may draw it see-through or wavy. Default false.
  • floorFx?: SurfaceFx — How its floor moves and shimmers.
  • ceilingFx?: SurfaceFx — How its ceiling moves and shimmers.
  • wallFx?: SurfaceFx — How its walls (and the step faces it shows) move and shimmer, unless an edge's fx says otherwise.

SectorEdge

interface SectorEdge

What one edge of a sector looks like and does. Edge i runs from points[i] to points[i + 1] (the last back to the first).

  • wall?: string — The texture of the wall on this edge, and of the step and lip faces this sector shows its neighbour there.
  • middle?: string — A texture hung across the opening (bars, a grate, a window): drawn on both faces, see-through where clear.
  • block?: boolean — No body may cross, though sight and shots pass (a railing, a window, bars). Default false.
  • blockEnemies?: boolean — Enemies may not cross (the edge of a ledge they should keep to). Default false.
  • quiet?: boolean — Sound does not carry across. Default false.
  • middleHeight?: number — How high middle reaches from the bottom of the opening (a railing 1 tall); default the whole opening.
  • fx?: SurfaceFx — How the faces on this edge (its wall, steps, lintels and middle) move and shimmer.

SectorEnemyWorld

interface SectorEnemyWorld

The map as enemies see it, for fps-enemies: sight through openings, moves with steps and drops, routes through doors (named by sector id), hearing, rays, doors to open and floor heights.

  • sees(ax: number, az: number, bx: number, bz: number, ay?: number, by?: number): boolean — An unbroken line between two points, through openings at the given heights.
  • move(x: number, z: number, dx: number, dz: number, body: { radius: number; height: number; step: number; fly: boolean }, y?: number): { x: number; z: number; y: number } — Move a body, sliding, with its step and drop limits.
  • route(fx: number, fz: number, tx: number, tz: number, body: { radius: number; height: number; step: number; fly: boolean }): { x: number; z: number; door?: string }[] | null — The way between two points.
  • hearing(x: number, z: number, radius: number): (x: number, z: number) => boolean — Who hears a noise.
  • wallDistance(x: number, z: number, yaw: number, max: number, y?: number): number | null — How far a flat ray goes before a wall.
  • doorShut(door: string): boolean — Whether a door blocks the way.
  • openDoor(door: string): boolean — Open a door; true when it starts opening.
  • floorAt(x: number, z: number): number — The floor at a point.

SectorGlow

interface SectorGlow

A light effect on a sector.

  • kind: 'flicker' | 'pulse' | 'strobe' — 'flicker' (random), 'pulse' (smooth) or 'strobe' (on and off).
  • low?: number — The lowest light as a fraction of the sector's, 0 to 1; default 0.3.
  • speed?: number — Cycles per second; default 1 (flicker: changes per second, default 8).

SectorJump

interface SectorJump

A jump pad: a body standing on the sector's floor is thrown into the air, straight up and along a heading, or on an arc worked out to land on a point. The game moves the body; the map works out the throw (SectorMap.launch).

  • up?: number — Upward speed in units per second, above 0. Needed unless to is given, which works out its own.
  • speed?: number — Speed along facing, units per second, 0 or more; default 0 (straight up). Ignored with to.
  • facing?: number — The way speed throws, degrees clockwise from north; default 0. Ignored with to.
  • to?: Point — A point to land on, [x, z]: the throw is worked out from the gravity where the body starts, to come down there.
  • y?: number — With to: the height to land at; default the floor there.
  • peak?: number — With to: how far the arc rises above the higher of its two ends, in units, above 0; default 2.
  • sound?: string — A sound by name, played on the pad as it throws.

SectorMapData

interface SectorMapData

A whole map, as JSON.

  • format?: 'sector-map' — 'sector-map', so a file says what it is. Optional.
  • version?: 1 — The format version: 1. Optional.
  • name?: string — A name for the map.
  • sky?: string — The sky texture, for sky sectors.
  • defaults?: MapDefaults — Defaults for sectors.
  • sectors: SectorDef[] — The sectors.
  • things?: MapThing[] — Things on the map.
  • triggers?: MapTrigger[] — Triggers.
  • lights?: MapLight[] — Lights.
  • fixtures?: MapFixture[] — Things that open or break: hinged doors, cabinets, windows.
  • signs?: MapSign[] — Signs on walls and hanging.
  • screens?: MapScreen[] — Screens on walls and standing in the air.
  • flyers?: MapFlyer[] — Things moving along paths through the air.
  • meta?: Record<string, unknown> — Anything else the game wants to keep with the map (music, par time, a title).

SectorMapState

interface SectorMapState

Everything that changes; a save holds exactly this.

  • time: number — Seconds the map has run.
  • floors: number[] — Floor heights by sector index.
  • ceilings: number[] — Ceiling heights by sector index.
  • lights: number[] — Base light by sector index.
  • movers: (MoverState | null)[] — Movers by sector index (null for none).
  • moves: ({ floor?: { to: number; speed: number }; ceiling?: { to: number; speed: number } } | null)[] — Moves started by actions, by sector index.
  • spent: boolean[] — Triggers: whether each is spent and whether each is enabled.
  • enabled: boolean[] — Triggers switched on.
  • queue: { at: number; trigger: number }[] — Actions waiting for their delay.
  • secrets: string[] — Secret sectors found.
  • started: boolean — Whether the start triggers have run.
  • lamps: boolean[] — Each map light: lit or not.
  • rng: number[] — The random stream (flicker).
  • fixtures: FixtureState[] — Each fixture, in the map's order.
  • signs: { text: string; on: boolean; rev: number }[] — Each sign: its text now, lit or not, and how many times it has changed.
  • screens: { on: boolean; kind: ScreenKind; lines: string[]; src: string; picture: string; since: number; rev: number }[] — Each screen: on or not, what it shows now, when that began (for scrolling), and how many times it has changed.
  • flyers: { at: number; dir: 1 | -1; on: boolean }[] — Each flyer: how far along its path, which way it is going (1 or −1) and whether it is moving.

SectorMover

interface SectorMover

Something that moves a sector's floor or ceiling: a door, a lift, a crusher, a platform.

  • kind: 'door' | 'lift' | 'crusher' | 'platform' — - 'door': the ceiling is drawn at its open height and starts shut on the floor; using an edge (or a trigger) raises it, it waits wait seconds and comes down, going back up if anything is underneath. - 'lift': the floor is drawn at its top; it goes down to to (default the lowest neighbouring floor), waits and comes back up. - 'crusher': once started, the ceiling comes down to gap above the floor and back, over and over, hurting what is caught. - 'platform': once started, the floor moves between its height and to, over and over.
  • to?: number — Lift and platform: the other floor height.
  • speed?: number — Units per second; default door 4, lift 3, crusher 1.5, platform 2.
  • wait?: number — Seconds it waits open or down; default 3. 0 for a door keeps it open.
  • key?: string — A key it needs, by name ('red'); default none.
  • use?: boolean — Pressing use on one of its edges works it; default true for doors and lifts.
  • walk?: boolean — Stepping onto it works it (a lift at the top); default false.
  • on?: boolean — Crusher and platform: running from the start; default false. Door: starts open.
  • gap?: number — Crusher: the gap it closes to; default 0.2.
  • damage?: number — Crusher: damage per second to what is caught; default 50.
  • sounds?: { start?: string; stop?: string } — Sounds by name, played where it is: as it starts moving and as it stops.

SectorPush

interface SectorPush

A push on bodies in a sector: a conveyor under their feet, or a wind that blows through it.

  • speed: number — Units per second, 0 or more.
  • facing: number — The way it pushes, degrees clockwise from north (0 north, 90 east).
  • air?: boolean — A wind: it pushes bodies anywhere in the sector, in the air too. Default false: a conveyor, which pushes only bodies standing on its floor.

SignView

interface SignView extends MountView

A sign as a presenter draws it.

  • text: string — The words now.
  • color: string — Text colour.
  • background: string — Background colour ('transparent' for none).
  • flicker: number — Flicker, 0 to 1.
  • frame: 'plate' | 'neon' | 'screen' | 'poster' — 'plate', 'neon', 'screen' or 'poster'.
  • picture: string | null — A picture name, or null.
  • hanging: boolean — Hanging: readable from both sides.

Socket

interface Socket

Where a piece joins another: a point on its outline, the way out, the opening's width and the floor height there.

  • at: Point — The middle of the opening, in the piece's own coordinates.
  • facing: Facing | number — Which way it faces out of the piece: a compass letter, or degrees clockwise from north (45 is north-east).
  • width?: number — The opening's width; joined sockets of different widths are an error. Default unchecked.
  • y?: number — The floor height there, in the piece's own heights; default 0.

SurfaceEffect

interface SurfaceEffect

One of the renderer's surface effects.

  • kind: 'ripple' | 'shine' | 'holo' | 'glow' | 'frost' | 'fire' — - 'ripple': a liquid's moving ripples and refraction. - 'shine': a glint sweeping across (polished metal, wet tiles). - 'holo': scan lines and shimmer (a hologram, a force field). - 'glow': lit from inside, breathing (a computer wall, a light panel). - 'frost': rime that creeps and sparkles. - 'fire': flames licking upward.
  • amount?: number — How strong, 0 to 1; default 0.5.
  • speed?: number — How fast, 0 to 10, 1 being the effect's own pace; default 1.
  • color?: string — A tint, CSS; default none (the texture's own colours).

SurfaceFx

interface SurfaceFx

How a surface moves and shimmers: its texture scrolling, animated frames and a renderer effect.

  • scroll?: [number, number] — Texture repeats per second along u and v; default [0, 0]. On a wall u runs along it and v down it, so [0, -0.5] runs a waterfall's texture down; on a floor or ceiling u is east and v south.
  • animate?: number — Frames per second of an animated texture, 0 to 60 (the presenter's texture has the frames); default 0.
  • effect?: SurfaceEffect — A surface effect.

TriggerAction

type TriggerAction = | { open: string } | { close: string } | { lock: string } | { unlock: string } | { break: string } | { sign: string; text?: string; on?: boolean } | { screen: string; on?: boolean; kind?: ScreenKind; lines?: string[]; src?: string; picture?: string } | { start: string } | { stop: string } | { floor: string; to: number; speed?: number } | { ceiling: string; to: number; speed?: number } | { light: string; to: number } | { lamp: string; on: boolean } | { sound: string; at?: Point; y?: number } | { message: string } | { spawn: string; at: Point; facing?: number; tag?: string } | { teleport: Point; facing?: number } | { exit: 'normal' | 'secret' } | { enable: string } | { disable: string } | { event: string; data?: unknown }

Something that happens when a trigger fires. Targets name an id or a tag: open and close reach doors (sectors) and fixtures, start and stop movers and flyers, lock, unlock and break fixtures, sign signs and screen screens.

TriggerOn

type TriggerOn = 'enter' | 'leave' | 'use' | 'cross' | 'shoot' | 'start' | 'kill' | 'break'

What sets a trigger off.

WindowFixture

interface WindowFixture extends FixtureBase

A pane of glass across a sector edge that opens onto another sector. While whole it stops bodies and shots, and sight passes unless it is frosted; shots and blasts take its hit points and at none it breaks, leaving the opening clear.

  • kind: 'window' — 'window'.
  • wall: { sector: string; edge: number } — The edge it fills: one that opens onto another sector.
  • hp?: number — Hit points, above 0; default 10.
  • frosted?: boolean — Frosted: sight does not pass while it is whole. Default false.
  • broken?: boolean — Starts broken. Default false.

WindowView

interface WindowView extends FixtureViewBase

A window pane, as a presenter draws it: a quad from a to b between heights low and high.

  • kind: 'window' — 'window'.
  • a: Point — One end.
  • b: Point — The other end.
  • low: number — The pane's bottom, in the world.
  • high: number — The pane's top.
  • hp: number — Hit points left.
  • broken: boolean — Broken: draw the empty frame (and shards when it broke).
  • frosted: boolean — Frosted glass.
  • yaw: number — The engine's yaw of the side facing into the sector it was set on.