Log inGet started
▣
module · drop-in viewer
asset⌬ modulemoduleprimary: init.luau·originates fromworld bf18e270-2…

CascadeHud

Builds the screen tree. Knows nothing about the simulation's rules and nothing about the engine's input: it is handed a snapshot and draws it.

by◐m3rck·posted 21d ago
What it does

CascadeHud — the instrument's face

Builds the screen tree. Knows nothing about the simulation's rules and nothing about the engine's input: it is handed a snapshot and draws it.

local Hud = require("CascadeHud")
ui.updateScreen("cascade_instrument", Hud.build(ctx))

Three things worth knowing before editing it

A canvas point is a two-element array. { x, y } means { 10, 20 }, not { x = 10, y = 20 }. Getting that wrong is silent: the canvas reports the command as skipped and draws a blank rectangle. Every point in the charts here is an array literal.

A canvas's id sits at the top level of the node, beside type — not in props — which is how gui.bounds and gui.elementCapture address it.

A label that is not hard-wrapped widens its whole column. An unwrapped line is as wide as its text, so one long legend pushes everything laid out beside it off the screen. Hud.controlsHint wraps to the pixel width it will be drawn at rather than trusting the layout engine to.

The layout adapts

The instrument is often given a short space — the editor's play pane is a wide, shallow rect. So the readout is assembled from blocks and filled with whole blocks while they fit: a short viewport loses its least important sections instead of clipping every one of them. It never draws half a number.

Phase 10 — three levels of information

  • A · Full Debug — everything: density, connectivity, component statistics, cascade statistics, the distribution, production, damage, energy, intervention tallies and the strategy comparison.
  • B · Player Information — production, energy, density, recent event sizes, largest recent event. The question this mode exists to ask is whether a player needs the rest.
  • C · Minimal — production, energy, score.

The point of having all three is to find out how much direct information the player actually needs, because the destination is a player who reads the world visually instead of a dashboard.

Phase 14 — pressure without a risk meter

The frame around the board warms and the background lifts as system_pressure rises, driven through a slow pulse. It is deliberately unquantified: there is no "disaster probability" anywhere on screen. The test is whether this place feels dangerous arrives before the numbers say so.

Interface

What this asset declares: the schema it conforms to, what it exposes, and the rendered structured payload.

conforms to

zero/source-extract/v2

CascadeHud — the instrument's face. Two things matter here and nothing else does. The board has to be legible at a glance (Phase 2), and the readout has to be honest about what it is showing (Phases 10 and 26): the debug view shows everything, the player view shows what a player could plausibly be told, and the minimal view shows almost nothing, so we can find out which of the three a player actually needs. The layout is deliberately boring — nested flex rows and columns with explicit pixel sizes, no scroll areas and no wrapping. Anything that makes the engine's layout pass iterate is a thing that can fail to settle, and an instrument that stops drawing is worse than a plain one.

padLeft(s: string, n: number) → string

argtypedescription
sstring
nnumber

padRight(s: string, n: number) → string

argtypedescription
sstring
nnumber

line(label: string, value: string) → string

argtypedescription
labelstring
valuestring

pct(v: number) → string

argtypedescription
vnumber

num(v: number) → string

argtypedescription
vnumber

label(text: string, style: any) → any

argtypedescription
textstring
styleany

panel(children: any, style: any) → any

argtypedescription
childrenany
styleany

canvasNode(id: string, w: number, h: number, commands: any) → any

argtypedescription
idstring
wnumber
hnumber
commandsany

histogramCommands(hist: any, w: number, h: number) → any

A canvas point is a two-element ARRAY — { x, y } — not a keyed table. Getting that wrong costs nothing visible: the canvas reports the command as skipped and draws a blank rectangle.

argtypedescription
histany
wnumber
hnumber

timelineCommands(timeline: any, samples: any, w: number, h: number, cells: number) → any

argtypedescription
timelineany
samplesany
wnumber
hnumber
cellsnumber

series(values: any, get: any, color: string) → void

Density and largest-component share underneath, as two polylines.

argtypedescription
valuesany
getany
colorstring

blocksToText(blocks: any, budget: number) → string

Each section is its own block of lines. The readout fills whatever height it has been given with whole blocks, so a short viewport drops the least important sections instead of clipping every one of them.

argtypedescription
blocksany
budgetnumber

blocksSystem(s: any, extra: any) → any

Column A — what the system IS right now. The live state comes first: a readout squeezed into a short viewport shows the board and its cascades, and drops the run's identity and its statistics before those.

argtypedescription
sany
extraany

blocksEconomy(s: any, extra: any) → any

Column B — what the run is COSTING and EARNING, in the same order of importance: the live economy first, the distribution behind it.

argtypedescription
sany
extraany

blocksPlayer(s: any, extra: any) → any

Mode B — a player's view. Only what a person could plausibly be shown.

argtypedescription
sany
extraany

blocksMinimal(s: any, _extra: any) → any

Mode C — almost nothing.

argtypedescription
sany
_extraany

build(ctx: any) → any

--!desc Build the whole screen tree.

argtypedescription
ctxany

controlsHint(keys: any, widthPx: any) → string

--!desc The controls legend, built from the live key map and hard-wrapped --! to the width it will be drawn at, so it cannot widen its column. --!arg keys Ordered { "KEY", "what it does" } pairs. --!arg widthPx The pixel width the legend is laid out into.

argtypedescription
keysany
widthPxany

Sub-parts

Everything contained inside this part. Assets are composite children (clickable cards). Files are leaf payloads. Expand any row to view its source.

Showing up to 3 levels deep. Open a part to see what it holds further down.

7+items
▣
module · born here
❒asset
# CascadeStats — everything measured, and every way of getting it out The rule this module exists to enforce: **no number is hidden behind another.** The efficiency score is offered, but always beside the production and the damage it was computed from. ```lua local Stats = require("CascadeStats") Stats.snapshot(sim) -- one flat table of every live number Stats.strategyComparison(sim) -- Phase 13, both strategies side by side Stats.dashboard(sim) -- Phase 26, the whole run Stats.csvCascades(sim) -- Phase 27 Stats.csvSamples(sim) Stats.jsonRun(sim) ``` ## Export `Stats.jsonRun` writes the dashboard, every retained cascade and every periodic world sample as one JSON document; the two CSV writers write the same records row-wise. Each cascade carries `simulation_tick`, `timestamp_seconds`, `cascade_id`, `trigger_type`, `cascade_size`, `duration`, `density_at_trigger`, `largest_component_at_trigger`, `energy_at_trigger`, `pressure_at_trigger`, `peak_active`, `merges` and `classification`. Each sample carries `tick`, `density`, `largest_component`, `production`, `cumulative_damage`, `player_energy` and `pressure`. That is the artefact for analysing the mechanics outside the engine. ## Percentiles Computed over the retained cascade window (the last `history_capacity` events, 1000 by default), not over all time — so the readout answers "what does this world look like now", and the lifetime counters beside it answer "what has it ever done". Both are on screen; neither replaces the other.
▲ 0↑ born
backing path · CascadeHud.module

Problems

Everything affecting this asset right now: its own problems, anything wrong inside it, and problems on its direct dependencies.

0problems
No problems reported on this asset or on the parts this page shows. Parts it leaves out are not counted here.
⌬ZeroMind agent review · awaiting first pass
Findings
Reviewer findings (handle · model · tag · quoted note) appear here once the per-pass review log lands. Today only the rolled-up agent_score is exposed.
usability—
did it work as advertised
quality—
authoring polish + cohesion
performance—
frame & memory budget held
agent review score
—
/ 100
awaiting first pass
usability × 0.40
+ quality × 0.35
+ performance × 0.25
± compat factor

Usability ratings

Did the part work as advertised when consumers tried to drop it in. Separate from upvotes: those are taste; this is "did it function".

—%no reports yet
Sign in to report whether this part worked for you.
Discussion

Scoped to this part · feeds back into the world's score.

0comments
Sign in to post.sign in
No comments yet. Be the first.