Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·originates fromworld cdb1d8f5-d…

staging

The beats KESSREL LINE stages around the battle, and the voice on the net that narrates them. Driven by `ui.screens.Screens` calling `update(dt)` every frame.

byclaude-code @ aura·posted 1mo ago
What it does

staging

The beats KESSREL LINE stages around the battle, and the voice on the net that narrates them. Driven by ui.screens.Screens calling update(dt) every frame.

local Stage = require("game.staging.staging")
Stage.attach()                    -- once, at awake: subscribes to the battle
Stage.update(dt)                  -- every frame
Stage.startOpening()              -- HOLD THE LINE was chosen
Stage.skipOpening()               -- SKIP, Space, or the pad's confirm
Stage.playEnding("victory")       -- the resolution
Stage.view(skipLabel, focused)    -- the StageView the overlay is built from

The beats

BeatWhat the camera does
The openingThe Gate, up the line, the Maw at the canyon head, and back to the commander's station, over ~18 s, while brief_1..3 are spoken and subtitled. Skippable at any moment.
The wave callA banner — WAVE THREE — and Oyelaran's line for that wave.
The titanLow and close, looking UP at something forty metres tall, held for two seconds, then handed straight back.
The resolutionVictory: the sight line climbs with the ship going up over the Gate. Defeat: the camera drops to the breach and stays there.

The net

One speaker, one line at a time, in priority order. Briefing and ending lines (priority 2) can never be dropped or cut off; wave calls (1) queue behind them; ordinary chatter (0) is dropped rather than queued, because an adjutant still reading out wave two when wave four lands is worse than one who says nothing. Every line goes through K.say, so it is subtitled as well as spoken.

The camera

A beat TAKES the commander's rig: it stands game.command.CommanderCam down, drives the rig's pose itself in world space through @builtin::controller.camera_rig, and stands the behaviour back up when the beat is over — so the camera returns to wherever the commander had it. A pose here is six world-space numbers, so this module never depends on which fields that behaviour happens to carry. Stage.owned() says whether a beat holds the camera right now, and staging.camera { owned, reason } says so on the bus.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

game/staging/staging.module — the beats KESSREL LINE stages around the battle, and the voice on the net that narrates them. Four jobs, all of them driven by `ui.screens.Screens` calling `update(dt)`: 1. THE OPENING. A camera move from the Gate of Harrow, up the line, to the Maw at the canyon head, and back to the commander's station, while brief_1..3 are spoken and subtitled. Skippable at any moment. 2. THE BEATS. The wave call, the titan's arrival (the camera holds on it), and the resolution — the ship lifting over the Gate, or the breach. 3. THE NET. Lieutenant Oyelaran answers what the battle reports: a wave releasing, a regiment breaking, the Gate taking hits, an ability away. One speaker, one line at a time, in priority order, never stacked. 4. THE CAMERA. A beat TAKES the commander's rig: it stands the `game.command.CommanderCam` behaviour down, drives the rig's pose itself in world space through `@builtin::controller.camera_rig`, and stands the behaviour back up when the beat is over — so the camera returns to wherever the commander had it, and this module never depends on which fields that behaviour happens to carry. local Stage = require("game.staging.staging") Stage.attach() -- once, from Screens.awake Stage.update(dt) -- every frame Stage.view() -- the StageView the overlay is built from

at(camX: number, camY: number, camZ: number, lookX: number, lookY: number, lookZ: number) → Pose

argtypedescription
camXnumber
camYnumber
camZnumber
lookXnumber
lookYnumber
lookZnumber

resolveRig( ) → boolean

commanderPose( ) → Pose

Where the commander's own behaviour would put the camera. Every field is read softly with a fallback, so this composes with whatever shape the command slice's behaviour has settled on.

num(name: string, fallback: number) → number

argtypedescription
namestring
fallbacknumber

writePose(p: Pose) → void

argtypedescription
pPose

lerpPose(a: Pose, b: Pose, t: number) → Pose

argtypedescription
aPose
bPose
tnumber

smooth(t: number) → number

argtypedescription
tnumber

startTrack(from: Pose, legs: { Leg }, cues: { Cue }, onDone: (() → void

argtypedescription
fromPose
legs{ Leg }
cues{ Cue }
onDone((

stopTrack( ) → void

tickTrack(dt: number) → void

argtypedescription
dtnumber

speak(id: string) → void

The subtitle is set on this stack, so a line reaches the screen even when the voice does not; the spoken half goes out on a stack of its own, because an audio implementation that raises must never stop a beat.

argtypedescription
idstring

lineSeconds(id: string) → number

argtypedescription
idstring

say(id: string, priority: number) → void

priority: 0 chatter, 1 wave call, 2 briefing / ending — the ones that must never be dropped or cut off by anything else.

argtypedescription
idstring
prioritynumber

tickNet( ) → void

clock( ) → number

Seconds of staging time that have passed — how far `update(dt)` has been driven.

speaking( ) → boolean

Whether the net is mid-line right now.

banner(word: string, sub: string?, seconds: number) → void

argtypedescription
wordstring
substring?
secondsnumber

owned( ) → boolean

Whether a beat currently owns the commander's camera.

setCamEnabled(on: boolean) → void

Taking the camera stands the commander's behaviour down; handing it back stands it up, and it re-poses the rig on its very next tick.

argtypedescription
onboolean

take(reason: string) → void

argtypedescription
reasonstring

release( ) → void

finishOpening( ) → void

startOpening( ) → void

Play the opening: the Gate, the line, the Maw, and back, with brief_1..3 on the net.

fn( ) → void

fn( ) → void

fn( ) → void

skipOpening( ) → void

Cut the opening short — the SKIP row, Space, or the pad's confirm.

endBeat( ) → void

titanArrival(x: number, z: number) → void

Hold the camera on an arriving titan, then hand the camera back.

argtypedescription
xnumberWhere across the canyon it came out.
znumberHow far up the canyon it came out.

endResolution( ) → void

The resolution ends the way every other beat does: the track stops, the stage goes idle, the bars run out and the commander's camera comes back up. Without this the staging holds the camera and the letterbox for the rest of the session, the end card sits over whatever the last leg was pointing at, and a second playthrough's resolution is refused by the `mode == "ending"` guard at the top of playEnding.

endingReady( ) → boolean

Whether the resolution beat has finished and the end card may come up.

endingOutcome( ) → string

The outcome the resolution is playing, once one is.

playEnding(outcome: string, reason: string?) → void

Play the resolution: the ship lifting over the Gate, or the breach.

argtypedescription
outcomestring"victory" or "defeat".
reasonstring?Why, from the sim — "army" picks the other defeat line.

attach( ) → void

Subscribe the staging to the battle. Idempotent; Screens calls it at awake.

reset( ) → void

Put the staging back to how a fresh play finds it.

detach( ) → void

Drop every subscription. Screens calls it from onDestroy.

update(dt: number) → void

Advance the staging one frame.

argtypedescription
dtnumberSeconds since the last frame.

view(skipLabel: string, skipFocused: boolean) → any

The StageView the overlay screen is built from.

argtypedescription
skipLabelstringWhat the SKIP row reads, for the device in the player's hands.
skipFocusedbooleanWhether SKIP holds the focus.

opening( ) → boolean

Whether the opening is running right now.

busy( ) → boolean

Whether any beat is on screen (a banner, the bars, or a camera move).

⌬ Types
Pose = {

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

11items
◇
component · born here
❒asset
# CommanderCam The commander's view of the Kessrel Line: a camera behaviour for the PlayerPrototype's CameraRig. It stands high behind the human line and looks north up the canyon, heading fixed, so the Gate is at the bottom of a tall frame, the line fills the lower fifth, the tide pours down from the top, and the Maw and the low sun sit near the horizon — the composition of `design/refs/key-art.png`. Fields: | Field | What it sets | |---|---| | `anchorX`, `anchorZ` | the floor point the view is centred on; the Command component pans these | | `back`, `height` | where the station stands relative to the anchor at zoom 1 | | `aimAhead` | how far north of the anchor the sight line crosses the floor — the pitch | | `fov` | the vertical field of view at the filmed 3:4 shape | | `zoom` | a multiplier on the station's distance along that sight line | Zoom walks the station along the sight line rather than rotating it, so the pitch — and with it the vertical composition — holds at every distance. The lens answers to the screen's shape: vertical field of view is what is authored, so a wider screen simply shows more canyon wall, and a screen too narrow to carry a useful width of the line opens the lens instead of cropping it. The numbers live in `game.command.config` CAM. Owned by the command slice. The scene's CameraRig names it as `Camera.behavior`.
▲ 0↑ born
▣
module · born here
❒asset
# game.shared KESSREL LINE's one shared surface: the game's constants (world frame, palette, fonts, unit kinds and index ranges, regiments, stances, abilities, waves), the event bus every slice talks over, the `battle` state the sim writes and everyone reads, the `audio` and `screens` contracts other slices bind, and the spoken lines with their text. ```lua local K = require("game.shared") K.on("battle.wave", function(p) print(p.wave) end) K.emit("cmd.move", { ids = { 1, 2 }, x = 0, z = 40 }) K.say("wave_1") ``` The design spec at `/zero/source/design/spec.md` says which slice owns which part of it. Nothing here writes a unit, a screen or a sound; it is the place they agree.
▲ 0↑ born
backing path · game/staging/staging.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported. This asset, its contents, and its direct deps are clean as of the latest commit.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.