At a glance

File
cutscenes.toml at the pack root; optional.
Parser
legaia_expansion_format::cutscene (the step shapes, the reachability and spin checks, the validator rules).
Runtime
The sequencer legaia_engine_expansion::cutscene (CutsceneRun, its camera and screen layer, the workbench's preview); engine-core's world::expansion_cutscene runs its commands on the World.
Hosts
Both play hosts frame the shot through camera_view::pack_cutscene_view and draw the fades and letterbox through screen_layers::expansion_cutscene_prims; nothing of a cutscene is host-side.
Ids
Declares cutscene; references line, formation, boss, quest, map.
Seen flag
cutscene.<id>, a pack flag saved with the pack's progress.

Why a step list, not field-VM bytecode

Retail's own cutscenes are field-VM records (cutscenes): camera beats through op 0x45, actor moves, inline dialogue, flag ops. A pack cutscene is a list of named steps on a sequencer of its own instead, for three reasons:

  • A pack never writes a retail story flag. Field-VM bytecode reaches the flag bank, the scene control block and every placement's script state; a step list has no op for any of them, and its flags are pack flags, exactly as a pack dialogue line's are.
  • It is checked as a whole. Every actor, line, label, track, flag, fight and tile is known before the cutscene runs, so the validator refuses a broken one.
  • It is written by hand and edited in the workbench. A step reads as what it does; the workbench's step-list editor is a form over the same shape.

cutscenes.toml

[cutscenes.tower_intro]
title = "The Tower Wakes"
map = "genesis_1f"
letterbox = true

[[cutscenes.tower_intro.steps]]
do = "camera"
focus = { tile = [7, 11] }
pitch = -14.0
zoom = 0.55

[[cutscenes.tower_intro.steps]]
do = "start_track"
track = "crane"

[[cutscenes.tower_intro.steps]]
do = "say"
line = "intro_hall"

[[cutscenes.tower_intro.tracks.crane.steps]]
do = "camera"
focus = { tile = [7, 1] }
zoom = 2.3
frames = 300
KeyMeaning
titleDisplay title.
mapThe pack map it plays on: its tiles and NPCs, and the engine refuses it elsewhere. Without it, tiles are the scene's field-grid tiles and actors the player and retail:<slot>.
skippableStart skips it once seen (default on).
lock_playerThe player is held throughout (default on).
letterboxCinematic bars while it runs.
stepsThe main track; the cutscene ends when it does.
tracks.<name>.stepsTracks a start_track step runs beside it.

Steps

A step's do key names it. Frames are display frames, 60 a second; a step that takes time accepts wait = false to let the next one start at once.

doWhat it does
waitWaits frames.
sayShows a line and waits for it to close; on_choice names a label per option.
moveWalks an actor through to / path tiles (optional speed, run, clip); a leg that would cross a wall goes round it on the collision grid.
face, clip, teleportTurn an actor (sector or toward another), play a clip, put it on a tile.
show, hideBring a pack NPC on or take it off.
camera, camera_reset, shakeMove the shot, ease it back, shake it.
fade, flash, tintThe screen layer: fade to black / white / clear, a dying flash, a held colour.
bannerA title across the lower screen in the place-name banner's balloon: a dialog line's first page.
set_flag, clear_flag, counterPack flags and counters.
label, goto, branchJump targets and jumps; a branch reads the quest gate shape and a counter.
start_track, joinStart a track; wait for one.
lock, unlockHold or free the player midway.
battle, bossEnd on a battle.toml fight.
give_item, take_item, gold, give_cardRewards.
start_questStart a quest.
sfx, bgmA sound effect from the static table; switch the music.
sound, music, music_releaseA retail cue or pack sound; a held music pick (a pack track too) cross-fading over fade frames; the music back to the map (audio).
endEnd here.

Actors and walks

An actor is "player", a pack NPC of the cutscene's map, or "retail:<slot>". The player walks at the pad walk's pace (8 world units a frame, 12 running) and plays its walk clip; an NPC walks each leg on the motion VM. A walk goes straight from stop to stop where that keeps to open ground, and round a wall on the collision grid where it would not; a leg with no way round walks straight. A pack NPC's present gate keeps it off the map until it holds; hide parks it on retail's own off-map hide box, out of every draw, the talk probe and the collision boxes.

Camera

A camera step moves the shot from the follow camera's own: focus replaces the follow focus (a tile, or an actor followed while it moves), yaw and pitch are degrees added to the follow shot's, and zoom scales the eye-space translation so the shot pulls straight back along its line of sight. A glide eases still at both ends; frames = 0 cuts. A cutscene that never moves the camera looks exactly like the field.

Hooks

HookPlays
A map trigger, kind = "cutscene"When the player steps into the zone (once, requires as usual).
A map's enter_cutscenesOn arrival: the first unseen entry whose gate holds, or one with repeat.
A pack NPC's cutsceneWhen the player talks to it, in place of its line.
A quest's start_cutscene / complete_cutsceneAfter the quest's line, once back in the field.
A boss's intro / outroAs its fight is called (the fight follows), and back on the field after a win.

A hook queues the cutscene; it starts on the first field frame with no box open, no fight waiting and no scene change in flight.

Runtime

The sequencer is a deterministic interpreter: each frame it advances its clocks, clears the waits that are over and runs each track to its next wait. It reads the world only through a narrow environment (is this actor walking, is the box closed, which option was picked, does this gate hold) and writes it only through commands, so the same answers give the same commands frame for frame. Each command uses a path the world already has - the faithful dialogue runner for a line, the motion VM for an NPC leg, the pack's queued fight for a battle. While a cutscene holds the player, the one predicate the walk, the talk probe, the menu button and the encounter roll already read answers that the player is engaged; the map's zones and exits fire nothing under it and its patrols pause.

Skipping and saves

A cutscene seen to the end once raises cutscene.<id>; from then on Start skips it: walks land, glides arrive, unshown lines are skipped, and every flag, item and quest step still happens. A line ending on a menu stops the skip, since the choice is the player's. A cutscene is never a save state: a host save is refused while one runs and the pause menu cannot open; a loaded save starts outside any cutscene.

Validation

  • Errors: an actor or tile the cutscene's map does not have; a line, fight, quest or card that does not exist; on_choice on a line without a menu or with more labels than options; a jump to an undefined label, a label defined twice; a step no flow reaches; a loop that never waits a frame; an unknown track; a malformed face; a zoom, pitch, frame count or shake out of range; a hook naming a missing cutscene, or an arrival cutscene bound to another map.
  • Warnings: a track nothing starts.

The workbench's Cutscenes tab edits the step lists and shows a text timeline of each cutscene played on the engine's own sequencer against a stand-in world (workbench).

Gaps

  • The field draws the party leader only, so the other members cannot be moved.
  • The path round a wall is the collision grid's: a prop with no wall bits under it is walked through.
  • A scene change ends a cutscene, so no step changes map midway.
  • A player clip names a clip base of the party bank, not a free animation.