stage.director — THE MOMENTS.
Three beats the run earns, each played as a deliberate camera move over
authored framing rather than a cut:
OPENING the Low Staithe at dusk. Low over the black water, in toward
the landing, then a rise that turns the fen away up the tall
axis of a 3:4 frame. The Lingster speaks first. The game does
not open cold on gameplay.
CREST the water goes over the deck. A shot at plank height with the
tide sliding across it, then a lift that shows how much
causeway is left. The game says the thing out loud.
RESOLUTION the Fold, the yowes that made it, the last line, held. Or,
when the fen wins, a long pull straight up off a drowned
causeway.
It also owns the two lights that make those shots read: the Lingster's
LANTERN, which follows her the whole run, and the lamp burning on the High
FOLD, which is the thing at the top of the frame worth walking toward. The
palette says the lantern and the herons are the only bright things in the
fen; this is the lantern.
Driven entirely by `Rules.SIGNAL.PHASE`, so it costs the run slice nothing
but the phase it already publishes. With no run slice attached at all it
still opens the game itself (`autoOpen`), which is what makes a staged
opening testable on its own.
Every spoken line's text is in `stage.lines` and is on screen as a cutscene
subtitle whether or not the voice bake reached it.
localAvatarId( ) → string
The player's body spawns asynchronously, so every one of these answers nil
until it is there and every caller has a fen-coordinate fallback.
lingsterZ( ) → number
How far up the fen the Lingster stands. The two beats that happen wherever
she is are framed around this; the opening and the won ending are framed
around the Staithe and the Fold, which do not move.
optionalModule(identity: string) → any
| arg | type | description |
|---|
| identity | string | |
speak(line: any) → void
Say a line aloud through the sound slice. The text is on screen either way:
a line the voice bake never reached is a quiet line, not a lost one.
| arg | type | description |
|---|
| line | any | |
yoweCount( ) → number
How many yowes are still with her, for choosing which ending is spoken.
render(seconds: number, gen: (number, number) → void
Render a generator into interleaved f32 the codec will take. Every sample
has to be finite: `asset.create` refuses the whole clip over one that is
not, and names where it sits.
| arg | type | description |
|---|
| seconds | number | |
| gen | (number, number | |
pcmOpts(buf: buffer) → void
`pcm` rather than Opus: an Opus clip loses its first ~5 ms on decode, and
what these three clips are made of is their attack.
| arg | type | description |
|---|
| buf | buffer | |
genDrone(t: number, _u: number) → number
A low swell under the opening: the fen breathing in before anything moves.
| arg | type | description |
|---|
| t | number | |
| _u | number | |
genSwell(t: number, u: number) → number
| arg | type | description |
|---|
| t | number | |
| u | number | |
genBell(t: number, _u: number) → number
The fold bell, struck once, for the moment the run resolves.
| arg | type | description |
|---|
| t | number | |
| _u | number | |
sfx(which: string, volume: number, pitch: number) → void
| arg | type | description |
|---|
| which | string | |
| volume | number | |
| pitch | number | |
childNamed(name: string) → any
| arg | type | description |
|---|
| name | string | |
lanternMaterial( ) → any
One warm material for both lamps: the palette's `lantern`, driven hard on
emissive so it holds its colour against a scene lit at dusk levels.
hex(c: { number }, alpha: string?) → string
| arg | type | description |
|---|
| c | { number } | |
| alpha | string? | |
captionTree(line: any) → any
| arg | type | description |
|---|
| line | any | |
setCaption(line: any) → void
| arg | type | description |
|---|
| line | any | |
captionForNow( ) → void
The line whose window holds the beat's current moment, or nil.
Nil while `sound.voice` is answering: that module raises the caption signal
the screens slice draws its subtitle bar from, for every line it speaks and
every line it fails to speak, so a second box saying the same words is a
duplicate. This one is what puts a staged line on screen when the voice
slice is not there at all.
linesCues(beat: string, into: { any }) → void
| arg | type | description |
|---|
| beat | string | |
| into | { any } | |
openingDef( ) → void
THE OPENING. Three shots, one continuous move: low across the water in
toward the Low Staithe, a rise that turns the causeway away up the frame,
and a settle onto something close to the camera the player is about to be
handed, so the handback is a landing rather than a cut.
crestDef( ) → void
THE CREST. Framed on the Lingster wherever she stands, because the water
goes over the deck under her feet rather than at a place. Plank height
first, so the tide crosses the bottom of the tall frame; then a lift that
answers the question the first shot asks — how much of this is left.
wonBeat( ) → string
THE RESOLUTION, won. The Fold from below, looking back down the drowned
fen she has just come up; a rise that puts her and what is left of the
flock small against the stone; then a held shot up at the lamp, and the
long fade out of a run that ended.
Which ending she speaks: bringing every yowe up is a different run from
bringing some of them.
lostDef( ) → void
THE RESOLUTION, lost. She never reached the Fold, so this happens where
she stopped: eye-level with the water that took the run, then one long pull
straight up until the causeway is a thread in a sheet of tide.
titleDef( ) → void
The title drift. No bands, no lines, no cut: a single slow move across the
fen so the title card has weather behind it instead of a still. It takes
the camera and gives it straight back the moment the run leaves `title`.
playDef(def: any, beat: string?) → boolean
| arg | type | description |
|---|
| def | any | |
| beat | string? | |
playOpening( ) → boolean
Play the opening beat — the Low Staithe at dusk and the Lingster's
first words. Plays once per run unless `replay` is used.
examples
entity.find("Stage").component.get("stage.director"):playOpening()playCrest( ) → boolean
Play the crest beat — the water going over the deck, framed where the
Lingster is standing when it happens.
playResolution(outcome: string) → boolean
Play the resolution beat. `outcome` is "won" or "lost"; the won ending
chooses its own lines from how many yowes are still with her.
| arg | type | description |
|---|
| outcome | string | |
examples
director:playResolution("won")replay(beat: string) → boolean
Play a beat again, ignoring whether it has already run. The beats are
once-per-run in play; this is how a beat is watched, captured and tuned
without replaying the whole game. Takes "opening", "crest", "won", "lost"
or "title".
| arg | type | description |
|---|
| beat | string | |
examples
director:replay("crest")isStaging( ) → boolean
Whether a staged beat is on screen right now.
report( ) →
Which beats have already played this run, and the last phase seen.
onPhase(phase: string) → void
| arg | type | description |
|---|
| phase | string | |
drive(dt: number) → void
The lantern follows the Lingster, held out at her side and a little ahead,
and breathes. It is the warmest thing in the frame and the only light that
moves, so a tiny amount of flicker is what stops it reading as a decal.
| arg | type | description |
|---|
| dt | number | |
update(dt: number) → void
| arg | type | description |
|---|
| dt | number | |
editorUpdate(dt: number) → void
| arg | type | description |
|---|
| dt | number | |