Event/Dialog Implementation Notes¶
Living notes for the wiki, journal, tutorial, event, and dialog feature.
Scope¶
- Build the feature direction from
docs/WIKI_EVENT_DIALOG_DESIGN.md. - Keep content/prose separate from structural encounter/event data.
- Keep player-facing scenario/dialog encounters separate from the existing technical
EventBus. - Preserve explicit runtime ownership; dialog choices dispatch commands instead of mutating gameplay owners directly.
- Keep this note as a compact implementation compass, not a detailed changelog.
Current State¶
- Wiki prose lives in
docs/wiki/and is loaded throughsrc/content/contentRegistry.js. - Authored wiki links use Obsidian/Zensical-compatible CommonMark file links like
[Travel](gameplay/travel.md). - Runtime content identity uses stable frontmatter IDs; import rewrites resolved wiki file links to runtime article IDs.
- Global event files are loaded from
GLOBAL_EVENT_DEFINITION_PATHSinsrc/content/eventDefinitionLoader.js. - Optional map-local encounter definitions load from
events.jsonin the current map folder during map finalization. - Duplicate event IDs are rejected across global and map-local files; map-local files may only add IDs.
- Startup/map-load validation checks wiki
relatedIDs, wiki file links, encountercontentIdreferences, and semantic UI highlight targets before encounter definitions are used. - Content validation failures are surfaced on the title screen with multiline details; default-map startup treats these as fatal authoring errors instead of falling through to fallback textures.
- Runtime owners are
wikiRuntime,journalRuntime,eventRuntime,eventDialogPersistenceRuntime,conditionEventTriggerRuntime,wikiPanelRuntime,journalPanelRuntime,encounterPanelRuntime,uiHighlightRuntime, andeventDebugPanelRuntime. - Player-facing terminology is Encounter for blocking/tutorial/dialog definitions; internal module names, DOM IDs, storage keys, and data folders still use
event/eventDebugnaming short-term for compatibility. - Blocking player-facing definitions are now presented as center-screen Encounters through
encounterPanelRuntime; the Wiki side dock is reference-only and no longer renders active encounter choices. - Encounter definitions can request temporary semantic UI highlights through
presentation.uiHighlights;uiHighlightRuntimemaps semantic target IDs to DOM elements and owns color, thickness, pulse, and source-based clearing. - Encounter triggers may use
trigger.exclusive: trueso the highest-priority eligible exclusive definition consumes a trigger call and skips lower-priority matching definitions. This is the intended map-local override path. - First-use tutorial triggers currently cover
gameplay_started,pathfinding_started,travel_committed,inspect_started,gathering_started,water_started,rest_started, andhunting_started. - Event/journal state persists locally through
terrain:event-dialog-state:v1; unsupported future payload versions are ignored. - The wiki panel includes a
Reset Tutorialsprototyping action that clears event state, journal entries, and the local persistence payload. - Wiki and Journal are separate player-facing panels opened by HUD
WandJ; the wiki panel no longer owns a journal side list. - In gameplay mode, Wiki, Journal, Inventory, and RD use fixed side-dock slots derived from the left stats width. Side-dock visibility is priority-resolved by
src/ui/sideDockRuntime.jsin increasing priority order: Journal, Inventory, Wiki, RD. - A compact HUD Journal Feed spans the center 420-unit mockup band directly above the HUD, shows the latest entry when collapsed, and expands upward into a short scrollable journal list.
- HUD
Jtoggles the Journal panel open/closed. The condition-effect strip is constrained so it does not cover theRD/knowledge system buttons. - The full Journal panel has a category filter populated from current entries; the HUD
Jbutton and Journal Feed show a lightweight entry-present indicator. Clicking a journal entry opens its wiki article without closing the Journal panel. - RD-dev remains an independent debug panel with the same side-dock width and highest side-dock priority.
- The bottom HUD spans the full viewport width and uses viewport-scaled Excalidraw ratios:
340 / 80 / 260 / 80 / 170 / 170for stats/effects, system/knowledge buttons, time/weather diorama, activity buttons, Activity status, and Inspect status. - The left stats area is split into two equal four-row blocks; the second block currently contains placeholders for future stats.
- Activity status is always visible and shows an
Idlebaseline when no movement/activity/preview is active. - Inspect is enabled by default and no longer has a dedicated HUD toggle button; blocking/disabled presentation remains available for activities such as rest.
RD > Encounters > Debugprovides debug-only encounter trigger buttons and readouts for active encounter, queue, definitions, seen/repeat/flag state, and journal entries.RD > Encounters > Debugalso shows a read-only Content Health card with article/global/map-local/active encounter counts, current validation status, last validation details, and aVCbutton that re-runs active wiki/encounter reference validation.- The first explicit debug encounter definition is
debug.sample_dialog, backed bytutorial.event_debug;debug.sample_noticecovers non-blocking notice behavior. RD > Encounters > Debugalso shows the last trigger result, including matched definitions and skip reasons such as already seen, repeat policy, queued, active, or no matching definition.- Survival warning events live in
assets/data/events/survival.json; hydration crossing down through 50 and fatigue crossing up through 50 create one-shot notice/journal entries. assets/map3/events.jsonis intentionally kept as a temporary map-local proof fixture. It uses obvious test copy frommap.map3_gathering_testand should be removed or rewritten when map-specific production content begins.- Content creation/polish is intentionally deferred. Current prose exists only where needed to exercise architecture and catch runtime/content-contract issues.
Closure Status¶
The Encounter/Wiki/Journal architecture is stable enough to treat the implementation slice as complete.
Completed architecture:
- Wiki, Journal, Encounter, side-dock, highlight, persistence, and RD debug owners are separated.
- Blocking Encounters are no longer mixed into the Wiki side panel.
- Journal entries are content references and can link to Wiki articles without closing the Journal.
- Global and map-local definitions load through one validated definition set.
- Map-local definitions can add new IDs and can override default trigger behavior with
trigger.exclusive. - Content reload paths bypass browser cache for authored Markdown and event JSON.
- Validation catches article links, related IDs, event content references, duplicate IDs, and semantic UI highlight targets.
- RD Encounters debug provides preview, validation health, trigger diagnostics, queue/active state, seen/repeat/flag state, and journal readouts.
Deferred intentionally:
- Final tutorial/survival/map content.
- Savegame/scenario-state integration beyond the temporary local browser persistence.
- Broad schema tooling beyond current runtime validation and tests.
- Large UI target expansion for highlights/help until content actually needs those targets.
Remaining Work¶
These are not blockers for the current architecture slice. They are follow-up improvements for later development.
- Improve Markdown rendering only if wiki content needs more structure; keep arbitrary HTML/script execution disallowed.
- Add article search/filter if wiki content volume makes manual navigation awkward.
- Add responsive/mobile layout for Wiki, Journal, and Encounter surfaces if mobile or small-window support becomes a target.
- Expand contextual help and semantic highlight targets across Inventory, route menus, condition bars, RD panels, terrain, resources, tracks, and entities when authored content needs them.
- Add journal summaries/snippets, visual variants, and richer de-duplication policies once journal entries are more than linked field notes.
- Move Encounter/Journal persistence from temporary
localStorageinto savegame or scenario-state storage when that layer exists. - Persist active Encounter/node/queue/choice history only if mid-encounter save becomes required.
- Decide whether encounter authoring remains JSON or gains a YAML/build normalization step.
- Add discovery/resource/track/scenario triggers when those gameplay signals have stable meaning.
- Add survival warning escalation or repeat policies when the survival loop needs more than one-shot threshold notices.
- Add standalone validation tooling if content validation needs to run outside app startup, map reload, RD debug, and tests.
- Replace or remove the
assets/map3/events.jsonproof fixture when real map-local content begins.
Decisions¶
docs/wiki/is the canonical authoring location for now.build-tauri.ps1copies it into.tauri-dist/docs/wiki/for packaged desktop runtime fetches.- Article IDs are stable frontmatter IDs. Derived IDs are development-only and must not be used by authored encounter definitions.
- Authored wiki prose links must be CommonMark
.mdfile links, not runtime IDs. contentRegistryresolves wiki file links to frontmatter IDs during import and rewrites loaded runtime bodies for in-game navigation.docs/wiki/index.mdremains manually authored for now; generation is deferred until article count or navigation complexity makes manual upkeep error-prone.- Global event definition files are listed in
GLOBAL_EVENT_DEFINITION_PATHSand merged in order byeventDefinitionLoader. - Map-local event files are optional
events.jsonfiles in the current map folder. They may only add event IDs; duplicate IDs are authoring errors. - First-use tutorial triggers are emitted after the owning command path succeeds. They must not preempt, validate, or mutate gameplay state.
- Event/dialog local persistence uses an explicit payload version. Unsupported versions are ignored rather than partially applied.
- The wiki panel may expose reset/debug actions for tutorial/event prototyping, but reset behavior is owned by runtime modules and persistence, not by the UI renderer.
- Generated wiki panel controls should carry explicit accessible labels because their visible text can be compact article IDs or short choice labels.
- The scenario/dialog encounter runtime is not the technical
EventBus; internally it is still namedeventRuntimefor compatibility, but it owns player-facing encounter queue state. - Journal entries store content references, not copied article bodies.
- Local browser persistence is temporary until a proper savegame/scenario-state layer exists.
- Gameplay mutations from dialog choices must route through explicit command dispatch.
- Non-command choice outcomes are intentionally narrow:
journal/add,event/setFlag, andevent/clearFlag. - Wiki/event content reference validation is an authoring guard, not a runtime recovery path.
- Startup and map-local content validation failures use a typed content-validation error so default-map fallback does not hide broken authored wiki/encounter data.
- Missing-article UI remains useful for runtime/dev safety even though shipped content should validate cleanly.
- Wiki panel keyboard, focus, help-click, generated-control labels, and reset-button behavior are owned by
wikiPanelRuntime. - Encounter panel keyboard, focus trap, backdrop, choice labels, and close behavior are owned by
encounterPanelRuntime. - UI highlights are presentation-only. Authored encounters reference semantic target IDs, not DOM IDs; highlights decorate visible controls and never change gameplay availability.
- Journal panel and HUD Journal Feed rendering are owned by
journalPanelRuntime;journalRuntimeremains the state/persistence owner. - HUD knowledge buttons are split from system/debug shell buttons:
?enables contextual help,Wopens the wiki, andJopens the journal. - Encounter debug trigger/readout UI lives under
RD > Encounters > Debugso it does not compete with player-facing journal/wiki UX. - Content health validation in
RD > Encounters > Debugis read-only; it may update debug/status text but must not mutate encounter, journal, wiki, or gameplay state. - Condition warning triggers are post-change observers owned by
conditionEventTriggerRuntime; condition mutation stays inconditionRuntimeand activity/resource owners. - Hydration/fatigue threshold warning events are one-shot notices for now. Repeating/escalating warnings are deferred until the survival loop needs them.
- Wiki/Journal side placement is presentation state only. It is not persisted yet and does not affect RD-dev, which remains the always-on-top debug surface.
- The current weather-status HUD row is a layout placeholder until a weather/runtime owner exists.
Future Improvements¶
- Decide whether some blocking encounters require an explicit final action instead of marking seen on close.
- Move long-term Encounter/Journal persistence from
localStorageinto a savegame or scenario-state layer. - Decide whether non-blocking notices need toast-style presentation in addition to Journal/feed/status feedback.
- Decide whether authoring stays JSON or gains a YAML/build normalization step.
- Add discovery/resource/track triggers once those gameplay signals have stable meaning.
- Add warning escalation/repeat policy for survival conditions once the survival loop needs it.
- Add journal summaries/snippets and visual variants when journal content grows beyond linked field notes.
- Expand semantic highlight/help targets across Inventory, route menus, condition bars, and RD only when authored content needs them.
- Add standalone content validation tooling if validation needs to run outside the app/test harness.
- Replace or remove the
assets/map3/events.jsonproof fixture when real map-local content begins.
Stabilization Notes¶
- Owner-module boundaries are in good shape.
eventRuntimeowns player-facing queue/trigger/choice state,encounterPanelRuntimeowns blocking presentation,wikiRuntimeowns reference article navigation,journalRuntimeowns journal state,sideDockRuntimeowns panel arbitration,uiHighlightRuntimeowns semantic highlight application, and content modules own loading/validation. main.jsremains the integration/composition surface, but the Encounter/Wiki/Journal behavior is not implemented as ad-hocmain.jsstate paths.- Dialog choices dispatch commands through the injected dispatcher; Encounter runtime does not directly mutate gameplay owners.
- Content creation is intentionally out of scope for this closure pass.
Historical Handoff¶
- Current branch:
feature/event-dialog-system. - Latest checkpoint before this layout slice:
36cb99e Add event dialog and journal systems. - The gameplay HUD layout is now proportional to the Excalidraw mockup, scaled to viewport width instead of hardcoded 1100px.
- Horizontal HUD ratios are
340 / 80 / 260 / 80 / 170 / 170, mapped as30.9091vw / 7.2727vw / 23.6364vw / 7.2727vw / 15.4545vw / 15.4545vw. - Left stat/effect side width equals Wiki/Journal side dock width.
- Stats area is split into two equal four-row blocks; only the first block has live stats for now, and the second block contains inert placeholders.
- Effects occupy the top quarter of the left stat area. Stats occupy the lower three quarters.
- Journal feed spans the 420-unit center band above the left buttons, diorama, and right buttons. Collapsed height matches the effects/weather row; expanded height matches the stats row.
- Activity and Inspect panels are equal width and sit inside the bottom HUD right side.
- The right activity button area intentionally stays in the 80-unit mockup slot and uses a compact
3x3grid for the current nine controls. - Inspect has no HUD toggle button now.
inspectPerceptionRuntimeinitializes enabled by default, while rest/scout can still block Inspect presentation. - Wiki/Journal side placement is presentation-only and not persisted. Header
Swapexchanges preferred Wiki/Journal sides subject to side-dock priority. - RD-dev is independent from Wiki/Journal side swapping and has highest side-dock priority.
- Weather Status is a layout placeholder only; no weather owner is wired into that row yet.
- This session added category filtering to the full Journal panel, entry-present indicators on HUD
Jplus the compact Journal Feed, kept Journal open when opening linked articles, aligned RD panel width with Wiki/Journal, moved Inventory into the same side-dock layout, and added side-dock priority arbitration. - This session split blocking tutorial/dialog presentation out of the Wiki panel into the centered Encounter panel. Markdown articles remain shared content; structural definitions choose
presentation.surface. - Untracked mockup files were intentionally left uncommitted:
Excalidraw/andScreenshot 2026-05-29 031220.png.
Recommended first browser checks next session:
- Start gameplay and confirm the bottom HUD visually matches the Excalidraw ratios across the full viewport.
- Confirm left stats form two equal blocks of four rows, with placeholders only in block two.
- Confirm Activity and Inspect are equal width.
- Confirm journal collapsed/expanded feed aligns only over the middle 420-unit band.
- Confirm Wiki/Journal side docks match the left/right yellow mockup columns and swap correctly.
- Confirm RD-dev opens above the left side dock.
- Confirm Inspect is active on startup and becomes visually disabled during blocking activities like rest/scout.
Milestones¶
- Added wiki article loading, safe Markdown rendering, help mode, and baseline wiki content.
- Added journal entries as content references with local persistence.
- Added article-backed blocking encounters, notice/silent events, queueing, time behavior, repeat policy, and flags.
- Added node-based dialog choices, command dispatch, event-owned outcomes, consequence visibility, and failure feedback.
- Switched wiki authoring links to Obsidian/Zensical-compatible
.mdfile links with import-time ID resolution. - Added content reference validation for wiki and encounter data.
- Added global and map-local event definition loading with duplicate-ID rejection.
- Added first-use tutorial triggers for gameplay start, pathfinding, travel, inspect, gathering, water, rest, and hunting.
- Added local persistence versioning, migration handling, and reset/debug behavior.
- Added keyboard/focus/accessibility behavior for the Wiki and Encounter panels.
- Added
RD > Encounters > Debugplus sample blocking dialog and notice encounters. - Split Wiki and Journal into separate panels and added the compact/expandable HUD Journal Feed.
- Added last-trigger diagnostics and first survival warning events for hydration/fatigue thresholds.
Latest Validation¶
- Stabilization closure pass:
node --check src\content\contentRegistry.js: pass.node --check src\gameplay\eventRuntime.js: pass.node --check src\ui\eventDebugPanelRuntime.js: pass.node --check src\ui\uiHighlightRuntime.js: pass.node --check src\main.js: pass.node --test tests\*.test.js: pass, 350 tests.- Targeted markdown lint for touched docs: pass.
- Full
npm run lint:mdis currently blocked by unrelated trailing whitespace indocs/notes.md.
Previous validation checkpoint:
node --check src\ui\eventDebugPanelRuntime.js: pass.node --check src\gameplay\eventRuntime.js: pass.node --check src\ui\encounterPanelRuntime.js: pass.node --check src\gameplay\conditionEventTriggerRuntime.js: pass.node --check src\ui\journalPanelRuntime.js: pass.node --check src\ui\wikiPanelRuntime.js: pass.node --check src\ui\bindings\canvasBinding.js: pass.node --check src\ui\rd\resourceDebugMarkupRuntime.js: pass.node --check src\main.js: pass.- JSON parse for
assets\data\events\tutorials.json: pass. - Focused event/wiki/encounter/content tests: pass, 42 tests.
node --test tests\*.test.js: pass, 323 tests.npm run lint:md: pass.