The pack
railRoute
function railRoute(): Pack<{ railRoute: typeof api }>
Install the rail route API.
Helpers
buildPath
function buildPath(leg: LegGeometry, from: Frame): BuiltPath
Build a leg's path from its geometry and the frame it starts from.
createRail
function createRail(def: RailDef): Rail
Validate a definition and build a running rail.
frameFrom
function frameFrom(pos: Vec3, forward: Vec3, up: Vec3): Frame
Build an orthonormal frame from a forward and an approximate up.
frameToWorld
function frameToWorld(f: Frame, p: Vec3): Vec3
A point given in a frame's local axes (x right, y up, z forward) as a world point.
keyedFrame
function keyedFrame(route: Frame, keys: readonly LegKey[] | undefined, s: number, pos: Vec3 = route.pos): Frame
The keyed body frame at s: the route frame turned by the keys' yaw, pitch, look-at and roll.
pathFrame
function pathFrame(path: BuiltPath, s: number): Frame
The route frame (no keys) at distance s along a built path; past either end it extends the end tangent.
rayBox
function rayBox(o: Vec3, d: Vec3, h: Vec3): number | null
Slab test of the ray o + d t against an axis-aligned box [-h, h] about the origin: entry t or null.
raySphere
function raySphere(o: Vec3, d: Vec3, c: Vec3, r: number): number | null
Distance from the ray o + d t (unit d, t >= 0) to a sphere: the entry t, or null on a miss.
splinePoints
function splinePoints(points: Vec3[], per = 16): Vec3[]
Sample a list of points into a polyline through them (centripetal Catmull-Rom, mirrored ends).
turnFrame
function turnFrame(f: Frame, yaw: number, pitch: number, roll: number): Frame
Turn a frame by yaw (right is positive), then pitch (nose up is positive), then roll (bank right is positive: the up axis leans toward the right), each about the frame's own current axes.
worldToFrame
function worldToFrame(f: Frame, p: Vec3): Vec3
A world point in a frame's local axes.
Functions
anglesOf
function anglesOf(local: Vec3): { yaw: number; pitch: number }
Yaw and pitch (radians) of a direction expressed in a frame's local axes, for turnFrame.
dirFromFrame
function dirFromFrame(f: Frame, d: Vec3): Vec3
A local direction in world axes (no translation).
dirToFrame
function dirToFrame(f: Frame, d: Vec3): Vec3
A world direction in a frame's local axes (no translation).
keyLookAt
function keyLookAt(keys: readonly LegKey[] | undefined, s: number): Vec3 | null
The latest lookAt point at or before s (or the first one ahead), if any key sets one.
keyValue
function keyValue(keys: readonly LegKey[] | undefined, field: KeyField, s: number, fallback: number): number
A keyed field at distance s: smoothstep between the surrounding keys that set it, fallback if none do.
normalize
function normalize(a: Vec3, fallback: Vec3 = { x: 0, y: 0, z: -1 }): Vec3
Unit vector (or fallback for a zero vector).
segmentHitsBox
function segmentHitsBox(a: Vec3, b: Vec3, h: Vec3, r: number): boolean
Does the segment a-b pass within r of an axis-aligned box [-h, h] about the origin?
segmentPointDistance
function segmentPointDistance(a: Vec3, b: Vec3, p: Vec3): number
Closest distance from point p to the segment a-b.
Constants
add
const add = (a: Vec3, b: Vec3): Vec3=> …
a + b.
clamp
const clamp = (n: number, lo: number, hi: number): number=> …
Clamp a number.
cross
const cross = (a: Vec3, b: Vec3): Vec3=> …
Cross product a x b.
distance
const distance = (a: Vec3, b: Vec3): number=> …
Distance between two points.
dot
const dot = (a: Vec3, b: Vec3): number=> …
Dot product.
length
const length = (a: Vec3): number=> …
Length.
lerp3
const lerp3 = (a: Vec3, b: Vec3, t: number): Vec3=> …
Linear interpolation.
madd
const madd = (a: Vec3, b: Vec3, k: number): Vec3=> …
a + b * k.
scale
const scale = (a: Vec3, k: number): Vec3=> …
a * k.
smooth
const smooth = (t: number): number=> …
Smoothstep on 0..1.
sub
const sub = (a: Vec3, b: Vec3): Vec3=> …
a - b.
vec3
const vec3 = (x = 0, y = 0, z = 0): Vec3=> …
Make a vector.
Types
Behaviour
type Behaviour = (t: RailTarget, ctx: BehaviourContext, dt: number) => void
A behaviour: edits a target each step.
BehaviourContext
interface BehaviourContext extends RailContext
Context for behaviours.
body: Frame— The rider's body frame (route frame, keys and pilot offset, no bank or look).params: Record<string, number | string | boolean>— Behaviour parameters from the motion definition.fire(t: RailTarget, projectile?: string): RailProjectile | null— Fire one of this target's projectiles now (kind default from its fire schedule).remove(t: RailTarget, reason?: string): void— Remove a target with a reason (reported asexpiredwith that reason).
BranchDef
interface BranchDef
A branch at the end of a leg.
options: Array<{ leg: string; when?: (ctx: RailContext) => boolean; label?: string }>— Candidate legs.choose?: "first" | "random" | ((ctx: RailContext) => string)— Selection policy (default'first'passingwhen); a preselection fromchoose()or input wins.
BuiltPath
interface BuiltPath
A leg's geometry, built once from its definition.
length: number— Total length in world units (0 for a stationary leg).samples: PathSample[]— The arc-length table.start: Frame— The frame at the start.end: Frame— The frame at the end.
CameraDef
interface CameraDef
The camera the rider looks through: aim and projection share it.
fov?: number— Vertical field of view in radians (default 1.0).aspect?: number— Width over height of the screen the aim limits assume (default 4/3).near?: number— Nothing nearer than this projects (default 1).aim?: { u: number; v: number; down?: number }— How far the crosshair may move, as view-plane extents|u|,|v|, anddownfor-v(defaultv); default the screen edges.
CameraPose
interface CameraPose extends Frame
The camera pose for presenters.
eye: Vec3— The eye (same aspos).roll: number— Roll of the view about forward relative to the route frame (bank plus keys), radians.velocity: Vec3— Rider velocity in world space.
CueDef
interface CueDef
A timed spawn on a leg, keyed to leg distance (at) or leg time (time).
at?: number— Fire when the rider's leg distance reaches this.time?: number— Fire when the leg time reaches this (seconds).spawn: SpawnSpec | SpawnSpec[] | ((ctx: RailContext) => SpawnSpec[])— What to spawn: specs, or a function of the context returning specs.every?: number— Repeat interval in the same unit (distance or seconds).count?: number— How many times in all (default 1, or unlimited withevery).when?: (ctx: RailContext) => boolean— Skip a due firing unless this is true (it is retried next step).
FireDef
interface FireDef
A target's firing schedule.
projectile: string— Projectile kind id.every: number— Seconds between shots.first?: number— Seconds before the first shot (default a seeded fraction ofevery).jitter?: number— Interval jitter, 0..1 ofevery(default 0).window?: { near?: number; far?: number }— Only fire while the target's depth is in this window.chance?: number— Chance each due shot is actually fired (default 1).max?: number— At most this many of its projectiles alive at once (default unlimited).from?: Vec3— Fire from this local offset (default the centre).
Frame
interface Frame
An orthonormal frame: a position and the right, up and forward axes at it.
pos: Vec3— The frame's origin in world space.forward: Vec3— Unit forward (the direction of travel or view).up: Vec3— Unit up.right: Vec3— Unit right,forward x upin the right-handed world.
GunDef
interface GunDef
The player's gun.
mode?: "ray" | "bolt"—'ray'resolves along the aim ray (afterdelay);'bolt'travels and is swept (default'ray').delay?: number— Ray mode: seconds from trigger to the first hit test (converging lasers). Default 0.duration?: number— Ray mode: seconds the beam keeps testing afterdelayuntil it hits (Star Wars: 8 frames). Default 0, one test.follow?: boolean— Ray mode: a lasting beam follows the current crosshair rather than the aim it was fired at. Default false.speed?: number— Bolt speed, units per second (default 6000).range?: number— Maximum range (default 1e6).cooldown?: number— Seconds between shots (default 0.15).damage?: number— Damage per hit (default 1).max?: number— Shots in flight at once (default 8).auto?: boolean— Holding the trigger repeats (default true); false needs a fresh press each shot.replace?: boolean— A new shot ends any shot still testing (Star Wars: a press restarts the 8-frame beam). Default false.
HoldDef
interface HoldDef
Stop the rider until a condition.
at?: number— Leg distance to stop at (default the leg's end).until?: (ctx: RailContext) => boolean— Resume when this is true.cleared?: string | true— Resume when this group (or, withtrue, every target spawned on this leg) is gone and the cues are done.time?: number— Resume after this many seconds of holding at the latest.
LegDef
interface LegDef
One leg of the route.
id: string— Unique id.phase?: string— Free-text phase name for rules and presenters.length?: number— Straight run continuing the start frame (ignored whenpathis set).path?: PathDef— Spline path.from?: string— Leg whose end frame this leg starts from (default the previous leg in the list).speed?: number— Route speed, units per second (default the rail'sspeed).keys?: LegKey[]— Keys along the leg.pilot?: PilotDef— Pilot movement.look?: LookDef— View turn.cues?: CueDef[]— Timed spawns.hold?: HoldDef— A stop.next?: string | BranchDef— The next leg or a branch (default the following leg in the list; the last leg ends the route).end?: boolean— The route ends at this leg even if another follows in the list.keepTargets?: boolean— Keep this leg's targets when leaving it (default false: they are removed).
LegGeometry
interface LegGeometry
Minimal leg shape the path builder reads (the full LegDef lives in rail.ts).
length?: number— A straight run continuing the previous leg's heading, in world units.path?: PathDef— A spline path.keys?: LegKey[]— Keys along the leg.
LegKey
interface LegKey
A keyed value along a leg, interpolated with smoothstep between keys that set the same field.
at: number— Distance along the leg, in world units.speed?: number— Route speed (units per second) from here.roll?: number— Bank about the direction of travel, radians (positive leans the up axis right).yaw?: number— View turned off the tangent, radians (positive right).pitch?: number— View tilted off the tangent, radians (positive up).lookAt?: Vec3— A world point the view turns toward, weighted bylookWeight.lookWeight?: number— 0..1, how far the view turns towardlookAt(default 1 wherelookAtis set).
LookDef
interface LookDef
View turn from steering: the view yaws and pitches toward the steer direction.
yaw?: number— Yaw at full steer, radians (default 0).pitch?: number— Pitch at full steer, radians (default 0).rate?: number— Turn rate, radians per second (default 1.5).follow?: "steer" | "aim"—'steer'or'aim'(default'aim').track?: (ctx: RailContext) => Vec3 | null— Auto-tracking: a world point the view turns toward atrate(unlimited angle), or null to hold. Star Wars' space phase, where R2-D2 swings the X-wing toward the current attacker. Overridesyaw/pitchwhile it returns a point.
MotionDef
type MotionDef = | { type: "static" } | { type: "velocity"; v: Vec3 } | { type: "path"; keys: Array<{ t: number; x: number; y: number; z: number }>; loop?: boolean } | { type: "behaviour"; id: string; params?: Record<string, number | string | boolean> }
How a target moves.
PathDef
interface PathDef
A spline path for a leg: control points the route passes through.
points: Vec3[]— Control points (at least one). The route passes through every point.relative?: boolean— When true the points are in the previous leg's end frame (xright,yup,zforward from its end), and the leg's start point is prepended, so a relative path always continues the route. Default false (world space, used as given).samples?: number— Samples per span for the arc-length table (default 16, at most 256).
PathSample
interface PathSample
One sample of a built path.
s: number— Distance from the leg start.pos: Vec3— Position.forward: Vec3— Unit tangent.up: Vec3— Unit up (rotation-minimising).
PickResult
interface PickResult
A hit query result.
what: "target" | "projectile"—'target'or'projectile'.id: string— Its id.kind: string— Kind id.region: string— Region id for targets ('body'without regions).distance: number— Distance along the ray.at: Vec3— World hit point.
PilotDef
interface PilotDef
Pilot movement inside a leg: the offset range is the corridor's walls.
x?: [number, number]— Lateral offset range[min, max]in route-frame units (default[0, 0]).y?: [number, number]— Vertical offset range[min, max](default[0, 0]).mode?: "position" | "velocity"—'position': the control picks a point in the range and the offset moves there atrate(default).'velocity': the control sets the offset speed,rateat full deflection (the Star Wars yoke on the Death Star surface and in the trench).rate?: number | [number, number]— Offset speed limit (position) or full-deflection speed (velocity), units per second; one number or[x, y](default 400).relative?: boolean—rateis a fraction of the current route speed instead of units per second (default false).bank?: number— Bank in radians at full lateral speed (default 0).bankLag?: number— Seconds the bank takes to follow (default 0.15).follow?: "steer" | "aim"—'steer'followsinput.steer;'aim'follows the crosshair (default'steer').
ProjectileKind
interface ProjectileKind
A kind of enemy projectile.
id: string— Unique id.radius?: number— Radius for hits on the rider and by shots (default 20).speed: number— Speed (relative to the rider when homing), units per second.damage?: number— Shield damage on reaching the rider (default 1).homing?: boolean | number—truecloses on the rider every step; a number is a turn rate in rad/s;falseflies straight, led.shootable?: boolean— Shots can destroy it (default true).hp?: number— Hit points (default 1).points?: number— Points reported when shot down.life?: number— Seconds to live (default 12).halfLife?: number— Close on the rider exponentially: the offset from the eye halves everyhalfLifeseconds, so the projectile holds its place on screen and grows (Star Wars fireballs close 1/8 of the way per frame). Overridesspeedandhoming.needsAim?: boolean— Damage only when it arrives inside the crosshair's reachable area (Star Wars fireballs). Default false.reach?: number— Distance from the eye at which it strikes (default its radius plus the rider's radius).gain?: { x?: number; y?: number; z?: number }— World-anchored drift with per-axis pulls toward the rider: each second the offset from the eye, measured in the rider's body frame (xright,yup,zahead), shrinks byexp(-gain)on that axis, on top of the projectile's own velocity (Star Wars ground and trench guns creep in and home sideways and up). Overridesspeed/homingwhen set.
Rail
interface Rail
A running rail.
readonly def: RailDef— The definition.readonly state: RailState— Live state (plain data).readonly leg: LegDef— The current leg definition.readonly targets: readonly RailTarget[]— Alive targets.readonly projectiles: readonly RailProjectile[]— Alive projectiles.readonly shots: readonly RailShot[]— Shots in flight.tick(seconds: number, input?: RailInput): void— Advance bysecondsin fixed steps.step(input?: RailInput): void— Advance one fixed step.drain(): RailEvent[]— Take the events since the last drain.pose(): CameraPose— The view pose (body plus bank and look).body(): Frame— The body frame (no bank or look): what rider-space targets ride in.toCamera(p: Vec3): Vec3— A world point in camera space (xright,yup,zdepth).project(p: Vec3, view: ViewRect): { x: number; y: number; z: number } | null— A world point on a screen rect, or null behind the near plane.focal(view: ViewRect): number— Focal length in screen units for a rect (vector-wire'sfocalLength).screenToAim(sx: number, sy: number, view: ViewRect): { u: number; v: number }— Screen point to view-plane aim.aimToScreen(aim: { u: number; v: number }, view: ViewRect): { x: number; y: number }— View-plane aim to a screen point.aimRay(aim?: { u: number; v: number }): { origin: Vec3; dir: Vec3 }— The world ray through an aim.aimLimits(): { u: number; v: number; down: number }— The aim limits|u|,vup anddown.legFrame(leg: string, s: number): Frame— The route frame (no keys) on a leg at distances.routePoint(leg: string, s: number, x?: number, y?: number): Vec3— A route-space point (xright,yup at distancesonleg) in world space.path(leg: string): BuiltPath— Built geometry of a leg.targetFrame(t: RailTarget): Frame— A target's world frame (position and oriented axes).localToWorld(t: RailTarget, p: Vec3): Vec3— A target-local point in world space.spawn(spec: SpawnSpec): RailTarget | null— Spawn a target now.launch(kind: string, from: Vec3, source?: string, opts?: { vel?: Vec3 }): RailProjectile | null— Fire a projectile of a kind from a world point now;vel(world units per second) overrides its aiming.remove(id: string, reason?: string): void— Remove a target (no event unlessreasonis given).hit(id: string, damage?: number, region?: string): void— Damage a target as if shot (rules-driven hits).hurt(amount: number, cause?: string): void— Damage the rider.kick(amount: number, seconds: number, settle?: boolean): void— Kick the view's roll:settlejumps byamountand fades back overseconds(a surface collision); otherwise it spins byamountoversecondsand stays (a hit in space).setShields(n: number): void— Set the shield count.addShields(n: number): void— Add shields (clamped to the maximum).fire(aim?: { u: number; v: number }): RailShot | null— Fire the gun now (ignores the trigger, respects cooldown).pick(aim?: { u: number; v: number }): PickResult | null— What the aim ray meets first.goto(leg: string, s?: number): void— Jump to a leg.choose(leg: string): void— Preselect a branch leg.flag(name: string, value: number | string | boolean): void— Set a rules flag.setScale(scale: Partial<RailState["scale"]>): void— Scale route speed, firing rate and projectile speed.kind(id: string): TargetKind— Look up a target kind.projectileKind(id: string): ProjectileKind— Look up a projectile kind.target(id: string): RailTarget | undefined— A target by id.snapshot(): RailState— Deep copy of the state.restore(s: RailState): void— Restore a snapshot from a rail built from the same definition.reset(): void— Back to the start.
RailContext
interface RailContext
Context for predicates and cue functions.
rail: Rail— The rail.state: RailState— Its state.leg: LegDef— The current leg definition.flags: Record<string, number | string | boolean>— Rules flags.random(): number— Seeded random in [0, 1).
RailDef
interface RailDef
The full rail definition.
legs: LegDef[]— Legs; the first is the start unlessstartLegsays otherwise.startLeg?: string— Starting leg id.start?: StartDef— Route start frame.speed?: number— Default leg speed (default 0).camera?: CameraDef— Camera.rider?: RiderDef— Rider.kinds?: TargetKind[]— Target kinds.projectiles?: ProjectileKind[]— Projectile kinds.gun?: GunDef— The gun (default a ray gun).shields?: { start?: number; max?: number }— Shield counter (default 1, max = start).behaviours?: Record<string, Behaviour>— Named behaviours formotion: { type: 'behaviour' }.seed?: number— Seed (default 1).step?: number— Fixed step in seconds (default 1/60).limits?: { targets?: number; projectiles?: number }— Resource bounds (defaults 512 targets, 512 projectiles).
RailEvent
type RailEvent = | { type: "leg-enter"; leg: string; phase: string } | { type: "leg-exit"; leg: string; phase: string } | { type: "hold"; leg: string } | { type: "resume"; leg: string; held: number } | { type: "branch"; from: string; to: string } | { type: "route-end"; leg: string } | { type: "spawn"; target: string; kind: string } | { type: "refused"; what: "target" | "projectile"; kind: string } | { type: "shot"; shot: string; aim: { u: number; v: number } } | { type: "hit"; target: string; kind: string; region: string; damage: number; invulnerable: boolean; friendly: boolean; at: Vec3 } | { type: "part-destroyed"; target: string; kind: string; region: string; points: number; at: Vec3 } | { type: "destroyed"; target: string; kind: string; points: number; by: "shot" | "collision" | "rules"; at: Vec3; data: TargetData } | { type: "miss"; shot: string; at: Vec3 } | { type: "passed"; target: string; kind: string; data: TargetData } | { type: "crossed"; target: string; kind: string; local: Vec3; data: TargetData } | { type: "expired"; target: string; kind: string; reason: string; data: TargetData } | { type: "fired"; projectile: string; kind: string; from: string; at: Vec3 } | { type: "projectile-destroyed"; projectile: string; kind: string; points: number; at: Vec3 } | { type: "projectile-hit"; projectile: string; kind: string; damage: number; at: Vec3 } | { type: "projectile-expired"; projectile: string; kind: string } | { type: "collision"; target: string; kind: string; damage: number; at: Vec3 } | { type: "damage"; amount: number; cause: string; shields: number; before: number } | { type: "shields-empty" }
Events, drained by the rules pack or presenter.
RailInput
interface RailInput
Input for one step.
aim?: { u: number; v: number }— Crosshair as a view-plane direction(u, v, 1)in camera space.steer?: { x: number; y: number }— Steering in [-1, 1] on each axis.fire?: boolean— Trigger held.branch?: string— Preselect a branch leg.
RailProjectile
interface RailProjectile
A live enemy projectile (world space).
id: string— Unique id.kind: string— Kind id.pos: Vec3— World position.vel: Vec3— World velocity.age: number— Seconds alive.hp: number— Hit points.from: string— Target that fired it, if any.depth: number— Depth in front of the rider.fixed: boolean— Launched with a fixed velocity: no homing, no pulls.dead: boolean— Marked for removal.
RailShot
interface RailShot
A player shot in flight or awaiting its delayed hit test.
id: string— Unique id.aim: { u: number; v: number }— Aim when fired.age: number— Seconds since firing.pos: Vec3— Bolt position (world).vel: Vec3— Bolt velocity (world).end: Vec3 | null— Where the shot ended, once resolved.done: boolean— Resolved (hit or missed).
RailState
interface RailState
Everything that changes; plain data.
time: number— Seconds since reset.leg: string— Current leg id.s: number— Distance along the current leg.legTime: number— Seconds on the current leg.holding: boolean— Stopped at a hold.holdTime: number— Seconds held.held: boolean— The hold on this leg has been released.ended: boolean— The route has ended.speed: number— Current route speed (after scale).rider: RiderState— Rider.shields: number— Shield count.targets: RailTarget[]— Targets alive.projectiles: RailProjectile[]— Projectiles alive.shots: RailShot[]— Shots alive.cooldown: number— Gun cooldown left.trigger: boolean— Trigger state last step.cues: Array<{ fired: number; next: number }>— Per-cue progress on this leg: firings so far and the next trigger value.branch: string | null— Preselected branch.flags: Record<string, number | string | boolean>— Rules flags for predicates.scale: { speed: number; fire: number; projectile: number }— Scale factors.stats: { shots: number; hits: number; kills: number; projectilesShot: number; damage: number }— Counters.rng: number[]— The seeded random stream's state: four words, from the kernel'srng.snapshot(). It advances in place and is saved with the state.nextId: number— Next id number.
RailTarget
interface RailTarget
A live target.
id: string— Unique id (kind-n).kind: string— Kind id.space: Space— Space ofpos.leg: string— Route space: the legpos.zis measured along.pos: Vec3— Position in its space (route: x right, y up, z = s alongleg; rider: x right, y up, z ahead).vel: Vec3— Velocity in its space, units per second.yaw: number— Yaw in its space's frame.pitch: number— Pitch.roll: number— Roll.age: number— Seconds alive.hp: number— Hit points left.parts: Record<string, number>— Hit points left per destructible region.exposed: boolean— Hittable this step (window and exposure).depth: number— Depth in front of the rider's body frame (negative behind).w: Vec3— World position this step.mode: string— Behaviour mode.modeTime: number— Seconds in the current mode (reset when a behaviour changesmode).data: TargetData— Rules/behaviour data.group: string— Group.spawnLeg: string— The leg it was spawned on.fireAt: number— Next firing age.collided: boolean— Already collided with the rider.crossed: boolean— Already reportedcrossed.ghost: boolean— Ignored by shots and collisions while true (a spinning, thrown Vader); rules set it.hits: number— Times hit.motion: MotionDef | null— Motion override.dead: boolean— Marked for removal this step.
RegionDef
interface RegionDef
A sphere or box in a target's local frame (x right, y up, z forward).
id: string— Region id, unique within the kind.shape?: "sphere" | "box"— Shape (default sphere).at?: Vec3— Centre offset in the target's local frame.radius?: number— Sphere radius.size?: Vec3— Box full size.hp?: number— Own hit points: the region is a destructible part.points?: number— Points reported when this part is destroyed.damage?: number— Damage multiplier for hits here (default 1).kills?: boolean— Destroying this part destroys the target.friendly?: boolean— Hits here are on a protected target (a hostage).hittable?: boolean— Shots can hit this region (default true).solid?: boolean— The rider can collide with this region when the kind is solid (default true).
RiderDef
interface RiderDef
The player's craft.
radius?: number— Collision radius, world units (default 30).invulnerable?: number | ((shieldsBefore: number) => number)— Seconds of immunity after taking damage, or a function of the shield count before the hit (default 0).
RiderState
interface RiderState
The rider's pilot and view state.
x: number— Lateral offset in the route frame.y: number— Vertical offset.vx: number— Lateral offset speed.vy: number— Vertical offset speed.bank: number— Current bank (radians).lookYaw: number— Current look yaw.lookPitch: number— Current look pitch.aim: { u: number; v: number }— Current aim.invulnerable: number— Immunity seconds left.prev: Vec3— Eye position last step (for swept collisions).roll: number— Extra view roll from kicks (radians).kick: { amount: number; seconds: number; t: number; settle: boolean } | null— An active roll kick: total, seconds, elapsed, settle (decay back to zero) or spin (keep it).
Space
type Space = "world" | "route" | "rider"
Where a target's position lives.
SpawnSpec
interface SpawnSpec
A spawn order: one target of a kind, placed in a space.
kind: string— Kind id.space?: Space— Space (default the kind'sspace, else'route').x?: number— Right of the frame (route/rider) or world X.y?: number— Up of the frame (route/rider) or world Y.z?: number— Rider space: ahead of the rider. World space: world Z.s?: number— Route space: absolute distance alongleg.ahead?: number— Route space: distance ahead of the rider (default 0 whensis not set).leg?: string— Route space: which leg (default the current one).vel?: Vec3— Initial velocity in the target's space.yaw?: number— Initial yaw (radians, in the space's frame; pi faces back down the route).pitch?: number— Initial pitch.roll?: number— Initial roll.group?: string— A group forhold.clearedand rules queries (default the kind's group).data?: TargetData— Data copied onto the target.mode?: string— Initial mode string for behaviours (default'start').motion?: MotionDef— Motion override for this target.
StartDef
interface StartDef
The starting frame of a route.
position?: Vec3— Where the route starts (default the origin).forward?: Vec3— Initial direction of travel (default -z, into a default 3D camera's screen).up?: Vec3— Initial up (default +y).
TargetData
type TargetData = Record<string, number | string | boolean>
Plain data a rules pack may hang on a target.
TargetKind
interface TargetKind
A kind of target: enemies, scenery that can be hit or collided with, pickups.
id: string— Unique id.space?: Space— Default space for spawns of this kind (default'route').radius?: number— Hit and collision sphere radius when there are no regions (default 40).hp?: number— Hit points (default 1).invulnerable?: boolean— Hits register but never damage (Vader's TIE).points?: number— Points reported when destroyed.hittable?: boolean— Shots can hit it (default true).regions?: RegionDef[]— Hit regions and parts (default one sphere ofradius).solid?: boolean— The rider collides with it (towers, catwalks, asteroids).collide?: { damage?: number; destroy?: boolean }— Collision outcome.window?: { near?: number; far?: number }— Hittable only while its depth in front of the rider is inside this window.expose?: Array<[number, number]> | { up: number; down: number; offset?: number }— Hittable only during these windows of its age: a list of[from, to], or a cycle.face?: "fixed" | "velocity" | "rider"— Automatic facing for presenters (default'fixed').motion?: MotionDef— Motion (default static).fire?: FireDef— Firing schedule.life?: number— Seconds to live (default unlimited).behind?: "remove" | "keep"— What happens when it falls behind the rider bymargin(default remove withpassed).margin?: number— Distance behind the eye beforebehindapplies (default the radius plus 50).group?: string— Default group.data?: TargetData— Data copied onto every target of the kind.friendly?: boolean— The whole target is protected: hitting it is a penalty for the rules pack.cross?: boolean— Reportcrossedwith the eye in the target's local frame when the rider passes its depth (fly-between bonuses).
Vec3
interface Vec3
A point or direction in 3D, in world units.
x: number— X component.y: number— Y component (up).z: number— Z component.
ViewRect
interface ViewRect
A screen rectangle for projection helpers.
w: number— Width.h: number— Height.


