hud
The **view** for *Lamplighter's Round*, and nothing else. It turns a plain snapshot table into two widget trees and registers them; it reads no game state, holds no game state, and decides nothing. `game.dread` builds the snapshot every frame and hands it here.
ui.hud — the lamplighter's HUD
The view for Lamplighter's Round, and nothing else. It turns a plain
snapshot table into two widget trees and registers them; it reads no game
state, holds no game state, and decides nothing. game.dread builds the
snapshot every frame and hands it here.
local Hud = require("ui.hud")
Hud.mount(onCallback) -- register + show both screens
Hud.refresh(view) -- push a snapshot ("hud" / "focus" to refresh one)
Hud.unmount()
The two screens
| Screen | Layer | Carries | Changes |
|---|---|---|---|
lamp_hud | 10 | the lamp rail, the Dread meter, the oil gauge, the ember count and the three upgrade tracks | slowly — refreshed a few times a second |
lamp_focus | 12 | the hold-to-light ring, the prompt, the message, the Pale warning, the win/lose card, and the screen-edge bruise | fast — every frame while a taper is held or a sting is fading |
The snapshot
Every field is optional; a partial snapshot still renders.
phase—"prelude"/"round"/"won"/"lost"dreadoillightProgresssting— each 0..1lampsLitlampTotalembers— countstracks— the ordered upgrade rows, each{ key, label, blurb, rank, max, cost, can, reason, effect }.cost = nilmeans the track is maxed;can/reasoncome straight from the rules, so a dim row says exactly why it is dim.promptmessage— the two lines of textpaleStatepaleDist— what the Pale is doing
Callbacks
mount takes an onCallback(id, value) and registers it through
ui.registerCallbackEnv, because a module is not a component and a widget
callback needs a persistent owner. Two ids are raised:
buy:<track>— a track row was clicked while it was affordableround:restart— WALK IT AGAIN on a win or lose card
Why it looks the way it does
Warm gaslight (#ffb257) against cold moon (#8fa6c4), soot-black smoked
glass plates with a brass hairline, serif small-caps for labels and a
monospace face for every number. The Dread meter runs cold steel → ember →
blood as the number climbs, and picks up a double-thump opacity pulse past
45%, faster the higher it goes.
Nothing on the lamp rail animates its scale: animating an SVG's size
re-rasterises it at a new display resolution every frame, and nine of those
cost more than the whole rest of the HUD. Opacity is free.
Scoped to this part · feeds back into the world's score.