acdream/src/AcDream.App
Erik 89db9a794c feat(ui): authored state media animates, so the unseen-text indicator blinks
The blink is not code. It is data, and we were throwing it away.

A retail UI state's media is a small program: images interleaved with timed
pauses, branches, and a terminal hand-off to another state. Our importer kept
the FIRST image per state and dropped the rest, so nothing authored could ever
animate — the indicator was correct in every other respect and simply sat
still.

Measured from the installed dats (LayoutDump --media 0x1000048C), the chat
unseen-text indicator's Normal state authors thirteen steps: two frames
alternating every half second, three times, then `State 13` — Ghosted, whose
authored 0x3B is Invisible.

So retail's indicator is a three-second attention FLASH that hides itself, not
a badge that stays lit until you scroll to the bottom. Nobody would guess that
from the code, because there is no blink code anywhere; the behaviour lives
entirely in the authored sequence. Our shipped version stayed lit, which is
the one thing the data says it must not do.

Sampling is a pure function of (steps, elapsed) rather than a playback object
holding a cursor, so an element only has to remember WHEN its state began and
the whole thing is testable without a clock, a GPU or a frame loop. One shared
UiMediaClock is advanced once per frame by RetailUiRuntime; a UI element has
no tick of its own.

The controller change is the other half: it starts the flash on the rising
edge ONLY. Re-setting Normal every frame would pin the sequence on frame zero
and it would never blink at all — which is the failure mode the second new
test exists to catch, and which no "is it visible?" assertion would notice.
When the sequence reaches its terminal step the controller follows it down
instead of re-lighting it.

Two guesses are refused rather than made, and both are registered: a Pause's
max duration (every sequence measured sets min == max, and what the range MEANS
is not in the decomp) and a sub-1 branch probability (falls through, the
direction where a malformed sequence stops rather than animates forever).
A jump-cycle with no elapsed time is bounded so a bad sequence cannot spin
inside a frame.

Kept `Other` steps in the list rather than filtering them, so a jump's authored
index still lands on the entry it names.

Register: CT-3, CT-4.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-21 11:14:53 +02:00
..
Audio fix #417: world ambience kept playing at character select after the in-world logoff 2026-08-17 18:46:04 +02:00
Combat fix(ui,runtime): OP4 review fixes — live re-seed, enable-gating, Combat panel re-point, universal timestamps 2026-08-11 05:30:26 +02:00
Composition fix(ui): restore retail vitals and window interactions 2026-08-20 13:26:35 +02:00
Configuration feat(runtime): share chat commands and run login sequence 2026-08-14 20:27:45 +02:00
Credentials fix(launcher): close Campaign LA LA1 review findings 2026-08-14 17:00:09 +02:00
Diagnostics fix: retail text and golden-string tests must not follow the machine's locale 2026-08-19 19:56:09 +02:00
Input fix(input): free-fly is unreachable, and Escape no longer answers to it 2026-08-21 09:55:16 +02:00
Interaction chore: secure-trade closeout - strip [trade] gate probes, roadmap ledger 2026-08-14 12:48:31 +02:00
Net fix #417: world ambience kept playing at character select after the in-world logoff 2026-08-17 18:46:04 +02:00
Physics refactor(physics): hoist the live-entity collision builder to Runtime (#330 groundwork) 2026-08-07 01:49:13 +02:00
Platform docs: Campaign LA — pinned launch-contract schema COMMITTED into plan LA1 2026-08-14 16:04:32 +02:00
Plugins feat(mosstank): banes, protections and weapon auras 2026-08-20 19:49:51 +02:00
Rendering fix(world): rotate the DAT-scenery root too — the flyers actually orbit now 2026-08-21 05:52:44 +02:00
Runtime feat(chargen): Campaign CC slice CC5 — Summary page, Finish flow, RandomizeCharacter port 2026-08-16 00:01:07 +02:00
Settings fix(ui): restore retail vitals and window interactions 2026-08-20 13:26:35 +02:00
Spells Revert "Campaign V slice V4a" - it lost world multisampling 2026-07-27 18:29:28 +02:00
Streaming fix: make locale-independence real, not assumed — parsing, casing, comparison 2026-08-19 20:11:32 +02:00
UI feat(ui): authored state media animates, so the unseen-text indicator blinks 2026-08-21 11:14:53 +02:00
Update feat(audio): Campaign A slice A5 — retail's region ambient soundscape 2026-08-08 22:53:41 +02:00
World fix: retail text and golden-string tests must not follow the machine's locale 2026-08-19 19:56:09 +02:00
AcDream.App.csproj feat(mosstank): cast back-to-back, and a settings view for the thresholds 2026-08-20 18:51:15 +02:00
GlobalUsings.cs feat(runtime): share chat commands and run login sequence 2026-08-14 20:27:45 +02:00
packages.linux-x64.lock.json build: make release restore reproducible 2026-08-18 10:29:00 +02:00
packages.neutral.lock.json build: make release restore reproducible 2026-08-18 10:29:00 +02:00
packages.win-x64.lock.json build: make release restore reproducible 2026-08-18 10:29:00 +02:00
Program.cs feat(plugins): MossTank — a self-buffing plugin, and the automation surface it needed 2026-08-20 16:22:28 +02:00
RuntimeOptions.cs feat(app): Campaign CC slice CC4 — chargen screen shell + Heritage/Profession/Skills/Town pages 2026-08-15 17:45:51 +02:00