Stage
The moments of *First Light: Crowfeet*, and the phase machine that runs the game from the title to an end card. One instance, on the scene's `stage` entity.
Stage
The moments of First Light: Crowfeet, and the phase machine that runs the
game from the title to an end card. One instance, on the scene's stage
entity.
What it owns
The beats. game.stage.Beats writes each staged moment down as a shot —
a duration and a list of timed cues. Stage plays one at a time and emits
around it, so the rest of the game can answer a moment without knowing what is
in it.
| Beat | When | What the camera does |
|---|---|---|
opening | start (the title card's Play) | Opens on the sea in the dark, lifts its eyes up the whole face, climbs it, and finds the crow on the strand. 11.4 s, skippable. |
firstLight | the firstLight event | Leaves the crow, turns up to the roost where eleven birds are waking. 4.4 s, skippable, and deferred while the crow is airborne so a beat never lands mid-hop. |
won | phase → won | Pushes in on the roost, the murder lifts, the Old Crow goes up with it, and the frame washes to first light. 9.6 s. |
lost_sea | phase → lost (sea) | Drops with the crow, kicks, pulls back over the water and the sea takes the frame. |
lost_starved | phase → lost (starved) | Pushes in close, then drifts up and away as the frame goes out. |
lost_late | phase → lost (late) | Up to the roost, the murder goes without you, and back down to one bird alone. |
The voice. All nine Old Crow lines, each said once a round, through
CF.say — so the words reach the caption band whether or not the sound slice
has a recording of them. Beats.LINES is where the text lives.
The murder. game.stage.Flock builds eleven birds on the roost under one
temporary root. They sleep, stir at first light, and take wing at the end.
The skip. game/stage/skip.inputMap is activated for exactly as long as a
skippable beat is playing and stood down when it ends, so a Skip button is on
the touch overlay during the crane and gone afterwards. Space or Enter, the
pad's south face or Start, or the on-screen button — all three families, and a
skipped shot still fires the cues it had left, so it still says its line and
still leaves the game where the shot was going to leave it.
Public fields
skipMap: AssetRef<inputMap>— the map the Skip control lives in. Defaults togame.stage.skip; if the scene predates the field the component resolves that identity itself rather than losing the control.autoStartAfter: number— seconds on the title card before the opening starts itself, so a recording is never wedged on a menu.0disables it.
Events it emits
| Event | Payload | Meaning |
|---|---|---|
stage.beat | { name, duration } | a staged moment started |
stage.cinema | { active, beat } | the frame is being staged — hide or inset the HUD while this is true |
stage.resolved | { outcome, reason } | the ending has FINISHED playing — put the end card up on this, not on the phase change, or the card lands on top of the shot that earns it |
phase, line | via CF | the phase machine and the Old Crow's voice |
It listens for start, restart, reset, phase, firstLight,
hungerLow, eat and crumble.
Rehearsing it
local S = require("game.CF").stage
S.rehearse("opening") -- play a moment without earning it
S.status() -- beat, clock, cues fired, the staged frame, the flock
S.skip() -- as if the player pressed Skip
S.clear() -- take the staged frame off and hand the shot back
One thing to know
game.CF belongs to the climb slice, and every edit of it hands back a NEW
module table with a NEW, empty event bus. A component that subscribed to the
old one goes silently deaf — no error, no warning, a game whose ending simply
never gets staged. So this component re-reads game.CF every frame and
re-arms the whole slice against a table it has not registered on.
Owned by the staging slice. Design: /zero/source/design/spec.md.
Scoped to this part · feeds back into the world's score.