2 story content loop
forgejo-actions edited this page 2026-07-13 19:05:50 +00:00

Story Content Loop

What This System Is

The story content loop connects quests, dialogue, NPC definitions, scene placements, rewards, unlocks, and runtime event ids. Authors usually touch several files for one quest-giver flow: the quest catalog says what state changes and rewards exist, the NPC catalog says who offers the interaction, the dialogue catalog says what topic plays, and scene content places or triggers the NPC.

At runtime, quest projection turns authored quests plus actor state into journal rows, map markers, accept/turn-in affordances, and snapshots. NPC runtime resolution picks the active NPC state variant and primary interaction. Dialogue runtime follows topic ids into catalog sequences, branches, choices, and shared effects.

How Authors Use It

For a new quest-giver flow, use the transactional story-slice wizard contract in crates/world-domain/src/story_slice.rs. The wizard stages the complete before/after workspace, validates required fields and collisions before apply, then creates the linked NPC, quest and reward, dialogue route, scene placement, trigger, and shared semantic ids as one undoable change. An invalid or duplicate slice leaves the original workspace unchanged.

Quest definitions include stable ids, display title, journal and completion text, availability conditions, objectives, steps, rewards, map markers, offer_npc_ids, turn_in_npc_ids, acceptance/turn-in flags, and follow-up quest ids. Quest objectives can read quest flags, inventory counts, party tags, faction reputation, scene variables, seen unlocks, and seen runtime events.

NPC definitions include a stable NPC id, display data, tags, default_topic_id, quest and relationship profile ids, speaker/presentation data, reusable interaction slots, and state_variants. State variants can carry conditions, priority, availability, outfit, topic, role, and replacement interactions.

Dialogue catalog entries provide lines and subtitles. Dialogue sequences provide ordered steps, waits, choices, branches, repeat behavior, cooldowns, and optional seen-state keys. Choice options and branches can carry conditions; choice options can apply shared authored gameplay effects.

Scene placements and scene triggers are the final link. A scene placement introduces a resolved NPC into a scene. A scene trigger can start dialogue through dialogue_npc:<npc_id>|<topic_id> or emit quest/runtime events that the quest projection later sees.

Files That Must Change Together

For a new quest-giver flow, update these together:

  • assets/quests/quest_catalog.json: quest id, objectives, availability, rewards, map markers, offer NPCs, turn-in NPCs, and follow-ups.
  • assets/npc/npc_catalog.json: NPC id, default_topic_id, quest/relationship profile ids, interaction slot, speaker presentation, and any state variants that change topic/role/availability.
  • assets/dialogue/dialogue_catalog.json: the dialogue route for the NPC topic, usually the sequence addressed by the NPC dialogue event id.
  • Scene content: the NPC placement and any trigger that starts the NPC interaction, opens a gate, marks an event, or transitions the player.
  • Shared semantics: every quest flag, item id, party tag, scene variable, unlock id, and runtime event id used by the flow.

Treat these ids as an API. Changing one without the others usually produces missing dialogue, missing NPC interactions, hidden NPCs, unavailable quests, or rewards that preview but never become authoritative.

Rules And Invariants

Quest ids, NPC ids, dialogue topic ids, unlock ids, runtime event ids, and shared condition keys are durable references. Rename them only when every referring catalog, scene trigger, placement, validation fixture, and save/runtime projection is migrated together.

NPC state variants are ordered by condition match and priority. A high-priority unavailable variant hides the NPC for that actor state, so use unavailable variants intentionally and keep their conditions narrow. Interaction priorities are ascending; lower numbers win the primary interaction.

Quest accept and turn-in actions are projected from quest runtime state. Do not duplicate that state only in dialogue branches. Dialogue can explain or mutate story state, but the quest catalog remains the owner of quest objectives, rewards, follow-up quest ids, and offer/turn-in NPC links.

Authoritative rewards and durable state changes must use shared effect and runtime-event ids. Preview can show the intended route, but server-owned completion, persistence, and replicated state must still be verified through the authoritative path.

Runtime Flow

NPC resolution starts from the scene placement and reusable NPC definition. The runtime chooses an active state variant by matching conditions and priority. If the winning variant is unavailable, the NPC is hidden. Topic selection prefers placement topic, then active variant topic, then default_topic_id; the special requested topic interact falls back to the resolved topic.

Interaction selection uses resolved slots. The primary slot is the lowest priority interaction, with kind, label, and id as tie breakers. If authored slots are absent, runtime helpers can synthesize fallback talk or quest interactions from the resolved NPC and quest projection.

Quest projection builds accept and turn-in entries per NPC. An accept entry appears when the quest requires acceptance, the NPC is in offer_npc_ids, the quest is available, and the actor has not accepted or completed it. A turn-in entry appears when the NPC is in turn_in_npc_ids and the runtime state says the quest is ready, or the objectives make it ready for a quest that requires turn-in.

Dialogue routes use the NPC id and topic id to find the intended sequence. Branches and choices use authored conditions to decide available routes. Choice effects and quest rewards share the same gameplay-effect vocabulary for quest flags, inventory deltas, party tags, faction reputation, scene variables, unlocks, and runtime events.

Rewards And Unlocks

Quest rewards include experience, state effects, unlock ids, and runtime event ids. Reward application can unlock follow-up quests, mutate condition state, mark unlocks as seen, and mark or emit runtime events. Dialogue choices can prepare the same kind of shared state changes, which is why quest and dialogue ids should use the shared condition/effect grammar documented in the reference page.

Use runtime event ids for story beats that multiple systems need to observe. Use unlock ids for durable author-facing gates. Use quest flags for quest-local or quest-family state. Use scene variables when the state belongs to a scene or scene-authored flow.

Validation And Debugging

Use catalog validation and bake checks after changing quest, dialogue, NPC, or scene content. The source of truth for these catalogs is the serde loader plus validation code, not a separate JSON Schema file.

When a quest giver does not behave as expected, check in this order:

  • NPC visibility: active state variant conditions, variant priority, and available.
  • NPC topic: placement topic, variant topic, default_topic_id, and the requested topic.
  • Interaction choice: resolved interaction slots, priorities, kind, label, and event id.
  • Quest projection: offer_npc_ids, turn_in_npc_ids, accepted/completed/runtime-ready state, and availability conditions.
  • Dialogue route: the dialogue_npc:<npc_id>|<topic_id> event and the matching dialogue sequence, branch, or choice target.
  • Reward state: quest reward state_effects, unlock_ids, event_ids, and any follow-up quest ids.

NPC runtime decision traces are useful for previewing which NPC variant and primary interaction were selected. Quest projection snapshots explain journal rows, markers, accepted quests, ready-to-turn-in quests, completed quests, rewarded quests, seen unlocks, and seen events.

Examples

A guide who offers a shortcut quest needs a quest definition with offer_npc_ids=["guide"], a guide NPC definition with a default or variant topic such as interact, a dialogue sequence reachable from dialogue_npc:guide|interact, and reward effects such as add_quest_flags, unlock_ids, or event_ids. If the dialogue choice opens the shortcut, the same unlock or event id should be visible to the quest and trigger systems.