diff --git a/docs/plans/2026-08-21-journal-campaign.md b/docs/plans/2026-08-21-journal-campaign.md new file mode 100644 index 00000000..33e8e419 --- /dev/null +++ b/docs/plans/2026-08-21-journal-campaign.md @@ -0,0 +1,99 @@ +# Campaign QJ — the Journal and Page List tabs + +**Status:** ACTIVE 2026-08-21. Completes the panel Campaign QT mounted: QT +shipped the Contracts tab and left the other two inert by design. + +**Scope:** retail's `gmJournalUI` (element type `0x10000048`, page +`0x10000563`) and `gmPageListUI` (type `0x10000049`, page `0x10000564`). + +## What this actually is + +A **per-character notebook**, entirely client-side. No wire, no server +involvement, no dat content — the player writes the pages. Each page carries a +label, a title, free-form notes, a recorded LOCATION, and a countdown TIMER. +The Page List tab is a searchable index over those pages. + +Nothing about it depends on quests; it shares the panel with Contracts and +nothing else. That it is called "Journal" while the panel is also called +"Journal" is retail's own naming, not a mistake here. + +## Measured ground truth + +### The file format + +`gmJournalUI::SavePages @0x00497270` / `LoadPages @0x00496AC0`. A plain tagged +text file, `fopen` mode `w+`. Both call sites pass the literal prefix +`"Journal"`; the path template is `%s%s-%s-%s.txt`, i.e. +`{dir}Journal-{server}-{character}.txt`. + +``` + begins a page (a file that does not open with one is refused) + %d page number + %s label (authored max length 16) + %s title (32) + %s notes (2048) + %d timer days + %d timer hours + %d timer minutes + %f recorded location + %f +