fix(ui): button property 0x0D was never "disabled", and it killed every Journal button

Reported symptom: Abandon, New, Record, Start, First and Last all unclickable.
That Abandon was in the list is what identified it — Abandon is deliberately
unwired, so if it behaved the same as the others the cause could not be wiring.

UiButton read authored property 0x0D as "starts disabled" (Enabled = !0x0D).
It was the one property read in that file with no citation, and it was wrong.
Every button on the Journal panel authors 0x0D, so every one built disabled:
visible, because drawing never consults Enabled, and unclickable, because
UiElement.HitTest skips disabled elements. Exactly the reported shape.

The evidence is a sweep of every installed layout (LayoutDump gained --ghosted
for it): 85 elements author 0x0D and ALL 85 author it TRUE — not one False
anywhere in the client — and no panel ever clears it, the only four
SetAttribute_Bool(.., 0xd, ..) sites in the binary being chargen appearance,
the keymap option and the barber. A flag that is only ever true, never cleared,
and sits on New, Record, Start, Delete and Reset cannot mean "dead button";
under the old reading 85 elements were permanently dead in a shipping game.

It is not a pure ghosted LOOK either, which is why this ignores it rather than
moving it to appearance: the same 85 mix live buttons with inert column headers
("Contract", "Status", "Title", "Timer", "Label", "#"), and one appearance
cannot be right for both. Registered as QJ-2 with the measurement, so the open
question is recorded rather than quietly decided.

The test that asserted the old behaviour carried no citation either — it
encoded the same assumption. It now asserts the evidenced behaviour, with a
companion test proving the state machine's own Ghosted transition still
suppresses a click: that mechanism is separate and did not change.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Erik 2026-08-21 15:58:03 +02:00
parent c5cc8ae5fc
commit 73a04244e7
4 changed files with 84 additions and 4 deletions

View file

@ -35,6 +35,39 @@ string datDir = SysEnv.GetEnvironmentVariable("ACDREAM_DAT_DIR")
using var dats = new DatCollection(datDir, DatAccessType.Read);
using var adapter = new DatCollectionAdapter(dats);
if (args.Contains("--ghosted"))
{
// Which authored elements carry property 0x0D (retail's ghost flag)?
// Sizing the blast radius of how acdream interprets it.
int hits = 0;
foreach (uint layoutId in dats.GetAllIdsOfType<DatReaderWriter.DBObjs.LayoutDesc>()
.OrderBy(i => i))
{
ElementInfo? candidate;
try { candidate = LayoutImporter.ImportInfos(adapter, layoutId); }
catch { continue; }
if (candidate is null) continue;
Walk(candidate, layoutId);
}
Console.WriteLine($"elements authoring 0x0D: {hits}");
return 0;
void Walk(ElementInfo e, uint layoutId)
{
foreach (var (_, state) in e.States)
{
if (state.Properties.Values.TryGetValue(0x0Du, out UiPropertyValue? v))
{
hits++;
Console.WriteLine(
$"layout 0x{layoutId:X8} element 0x{e.Id:X8} type={e.Type} 0x0D={v.BoolValue}");
break;
}
}
foreach (ElementInfo child in e.Children) Walk(child, layoutId);
}
}
if (args.Contains("--contracts"))
{
// Campaign QT slice QT2: what does the installed ContractTable actually