neon-sprawl/docs/decomposition/modules/E7_M1_QuestStateMachine.md

9.8 KiB
Raw Permalink Blame History

E7.M1 — QuestStateMachine

Summary

Field Value
Module ID E7.M1
Epic Epic 7 — Quest / Faction
Stage target Prototype
Status Ready — Slice 1 backlog E7M1-prototype-backlog.md E7M1-01 NEO-112E7M1-12 NEO-123 landed. Client capstone NEO-123 manual QA; client README — End-to-end onboarding quest loop (NEO-123). Epic 7 Slice 1 client capstone complete.
Linear Label E7.M1 · E7M1-prototype-backlog.md

Purpose

Data-driven quest lifecycle: start, step progression, branching, failure/reset, and completion with durable persistence. Integrates crafting and combat outcomes so guided content ties together gathercraftcombat loops without duplicate rewards.

Scope / party: Per-character state by default; optional party credit and turn-in rules via QuestDef and E8.M1.

Responsibilities

  • Load and interpret QuestDef; track QuestStepState per character; synchronize party-credit advances per quest_scope_and_party.md.
  • Apply QuestStateTransition rules for advance, abandon, fail, and complete.
  • Invoke or subscribe to E3.M2 and E5.M1 (or their events) for step completion predicates.

Key contracts

Contract Role
QuestDef Steps, prerequisites, objectives, and branching metadata.
QuestStepState Current step progress and internal flags.
QuestStateTransition Valid transitions and side effects (before E7.M2 reward routing).

Module dependencies

  • E3.M2 — RefinementAndRecipeExecution: craft completion, item hand-ins, refine steps.
  • E5.M1 — CombatRulesEngine: defeat objectives, encounter-linked steps.

Dependents (by design)

See Epic 7 Slice 1 — Quest core and persistence: 35 onboarding quests plus one chain across gather/craft/combat; telemetry quest_start, quest_step_complete, quest_complete, funnel times.

Linear backlog (decomposed)

Full story tables, kickoff defaults, and blockedBy graph: E7M1-prototype-backlog.md.

Slug Linear
E7M1-01 NEO-112
E7M1-02 NEO-113
E7M1-03 NEO-114
E7M1-04 NEO-115
E7M1-05 NEO-116
E7M1-06 NEO-117
E7M1-07 NEO-118
E7M1-08 NEO-119
E7M1-09 NEO-120
E7M1-10 NEO-121
E7M1-11 NEO-122
E7M1-12 NEO-123

Prototype Slice 1 freeze (E7M1-01)

The first shipped quest spine is frozen for prototype tuning until a deliberate migration issue expands the roster.

QuestDef.id displayName prerequisiteQuestIds Steps (summary)
prototype_quest_gather_intro Intro: Salvage Run (none) 1× gather_item: scrap_metal_bulk ×3
prototype_quest_refine_intro Intro: Refine Stock prototype_quest_gather_intro 1× craft_recipe: refine_scrap_standard ×1
prototype_quest_combat_intro Intro: Clear the Pocket (none) 1× encounter_complete: prototype_combat_pocket
prototype_quest_operator_chain Operator Chain prototype_quest_gather_intro, prototype_quest_refine_intro, prototype_quest_combat_intro 4 steps: gather scrap_metal_bulk ×5 → craft refine_scrap_standard → craft make_field_stim_mk0inventory_has_item contract_handoff_token ×1

CI enforcement (NEO-112): scripts/validate_content.py still enforces the four Slice 1 quest ids in the freeze table above (prerequisite graph, objective cross-refs, chain terminal step). Roster allowlist expanded to five quests under E7.M3 (PROTOTYPE_E7M3_QUEST_IDS, NEO-133) — adds prototype_quest_grid_contract. Shared gates: objective cross-refs to frozen item/recipe/encounter catalogs; acyclic prerequisiteQuestIds; operator chain terminal step uses contract_handoff_token from E5.M3 encounter loot.

Server load (NEO-113): Host fail-fast load of content/quests/*_quests.json with the same gates — server README — Quest catalog.

HTTP read model (NEO-115): GET /game/world/quest-definitionsQuestDefinitionsWorldApi + DTOs in Game/Quests/ (NEO-115); server README — Quest definitions (NEO-115); Bruno bruno/neon-sprawl-server/quest-definitions/.

Player quest state store (NEO-116): IPlayerQuestStateStore — in-memory + Postgres (V008__player_quest_progress.sql) per-player rows keyed by (playerId, questId); implicit not_started when missing (NEO-116); server README — Quest progress store (NEO-116).

Quest state operations (NEO-117): QuestStateOperations — accept, step advance, complete with QuestStateReasonCodes; prerequisite gate on accept; idempotent complete at operations layer (NEO-117); server README — Quest state operations (NEO-117).

Quest objective wiring (NEO-118): QuestObjectiveWiring — gather/craft/encounter success hooks + inventory_has_item on accept/step advance/inventory mutations; auto advance/complete via QuestStateOperations (NEO-118); server README — Quest objective wiring (NEO-118).

Per-player quest progress GET (NEO-119): GET /game/players/{id}/quest-progressQuestProgressApi + DTOs; registry + store merge; GET-side inventory_has_item refresh (NEO-119); server README — Per-player quest progress (NEO-119); Bruno bruno/neon-sprawl-server/quest-progress/.

Quest accept POST (NEO-120): POST /game/players/{id}/quests/{questId}/acceptQuestAcceptApi + DTOs; wires QuestStateOperations.TryAccept; structured accepted / reasonCode / optional quest row (NEO-120); server README — Quest accept POST (NEO-120); Bruno accept spine in bruno/neon-sprawl-server/quest-progress/.

Quest telemetry hooks (NEO-121): comment-only quest_start, quest_step_complete, quest_complete, quest_accept_denied hook sites in QuestStateOperations (NEO-121); server README — Quest telemetry hooks (NEO-121).

Client quest HUD (NEO-122): quest_progress_client.gd, quest_definitions_client.gd, QuestProgressLabel / QuestAcceptFeedbackLabel; boot + gather/craft/defeat/accept refresh; Q / Shift+Q accept bindings (NEO-122, NEO-122 manual QA); client README — Quest progress + accept HUD (NEO-122).

Reward policy (Slice 1): Quest completion updates QuestStepState only — no duplicate item/XP grants. Gather/craft/encounter paths keep existing payouts; E7.M2 adds QuestRewardBundle apply in Slice 2.

Risks and telemetry

  • Scripting weight: keep QuestDef data-first; templates in decomposition/tooling path per epic.
  • Double-claim: design for idempotency before E7.M2; lint bundles vs E6.M4 / E3.M5.
  • Epic 7 Slice 1 catalog events (comment-only until E9.M1): quest_start, quest_step_complete, quest_complete, quest_accept_denied — anchored in QuestStateOperations (NEO-121).

Source anchors