Screens
Puts every authored screen of *First Light: Sabaean Madcaps* on the glass and drives it. Mounted once, on `mount_screens`; it needs nothing else on that entity.
Screens
Puts every authored screen of First Light: Sabaean Madcaps on the glass and
drives it. Mounted once, on mount_screens; it needs nothing else on that
entity.
What it draws
| Screen | Layer | What it is |
|---|---|---|
mc-menu | 960 | whichever card the phase calls for |
mc-hud | 120 | the climb rail, the madcap gauge, the dawn rail, the censer, the pause pip |
mc-alert | 118 | first light, and the censer going dark |
mc-say | 980 | the subtitle — every spoken line, in writing, always |
The subtitle sits above the cards on purpose: an ending speaks while its
card is on the glass, and a line nobody can read is a line the game did not
say. Its root is an anchor, not a full-screen box, so it covers only the band
it draws in — a screen root that fills the viewport takes every tap inside it,
painted or not.
The alert layer is its own screen because its motion loops, and a HUD repaint would restart the loop every time the clock ticked.
What decides which card is up
MC.state.phase, which the loop slice owns. This component never invents a
phase: it reads one and paints it.
| Phase | Card |
|---|---|
title | the title card |
opening | none — a staged shot, with only the words over it |
play | none — the HUD |
paused | the pause card |
won / lost | first light on the altar, or Wahab'il's taper |
How to play is an overlay over whichever card opened it, not a phase, and closing it puts the focus ring back on the line that opened it.
When the player takes a line this component emits uiRequest(action) —
"start", "pause", "resume", "restart", "title" — and waits. If nothing
has moved the phase after a moment it moves the phase itself, so the game stays
reachable from its own title card whatever else is or is not running. The moment
Game answers a uiRequest, the fallback stops firing on its own.
Controls
game.screens.uimenu goes live the instant a card goes up and is released the
instant the last one comes down; it stands down run, player and uipause
while it holds. game.screens.uipause carries the one control that stays live
during the climb.
- Focus moves on
navigate(arrow keys / d-pad) andnavigateStick(left stick), wraps at both ends, and lands on something the instant a card opens. The focused line carries a gold ring, a lit edge marker and a diamond; hover and press are styled differently on purpose, so a pointer resting on one line never reads as the ring sitting on another. - Choose on
confirm(Enter, Space, south), leave onback(Escape, Backspace, right mouse, east), and an end card also answersrestart(R, north). - A pointer or a thumb takes a line by touching it, and doing so moves the ring there, so a player mixing devices never loses their place. Every line is at least 100 logical points tall.
- Each card shows the legend for the family actually in the player's hands,
read from
/runtime/input/device: a contact on the glass means a thumb, a connected pad means a controller, otherwise it is a keyboard. The touch reading is held for a minute, because a player who taps a line and then reads the card is still holding a phone thirty seconds later.
Public fields
menuMap: assetRef(inputMap)— the menu scheme. Defaultgame.screens.uimenu.pauseMap: assetRef(inputMap)— the pause control. Defaultgame.screens.uipause.
Methods
:repaint()— force the next tick to rebuild every screen. A screen is only repainted when its own inputs change, and a hot reload ofmcuiormcscreensis not one of those inputs, so this is how an edit to the look reaches the glass without restarting anything.
Lifecycle
awake()— paints the first frame.update(dt)/editorUpdate(dt)— one tick either way: takes over the bus from whatever chunk held it, reads the device, ages the subtitle, resolves the card the phase asks for, and repaints only the screens whose inputs changed.onDestroy()— drops every bus handle, releases both schemes, and unregisters every screen it put up.
Scoped to this part · feeds back into the world's score.