Log inGet started
World

Lamplighter's Round

Branchmain
Branchesmain
Commitea9749977c

README.md

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

ScreenLayerCarriesChanges
lamp_hud10the lamp rail, the Dread meter, the oil gauge, the ember count and the three upgrade tracksslowly — refreshed a few times a second
lamp_focus12the hold-to-light ring, the prompt, the message, the Pale warning, the win/lose card, and the screen-edge bruisefast — 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"
  • dread oil lightProgress sting — each 0..1
  • lampsLit lampTotal embers — counts
  • tracks — the ordered upgrade rows, each { key, label, blurb, rank, max, cost, can, reason, effect }. cost = nil means the track is maxed; can / reason come straight from the rules, so a dim row says exactly why it is dim.
  • prompt message — the two lines of text
  • paleState paleDist — 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 affordable
  • round: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.