diff --git a/docs/architecture/tech_stack.md b/docs/architecture/tech_stack.md index d628f3d..0432578 100644 --- a/docs/architecture/tech_stack.md +++ b/docs/architecture/tech_stack.md @@ -114,3 +114,4 @@ Revisit this document if: - [`docs/decomposition/modules/contracts.md`](../decomposition/modules/contracts.md) — contract kinds (wire, content, telemetry), repo layout, versioning vs. register “Contract needed” - [`docs/decomposition/modules/client_server_authority.md`](../decomposition/modules/client_server_authority.md) — intents vs authoritative state; movement, camera, combat, economy ownership - [`docs/decomposition/modules/pvp_combat_integration.md`](../decomposition/modules/pvp_combat_integration.md) — E5.M1 combat engine × E6.M1 PvP eligibility (single pipeline, deny reasons) +- [`docs/decomposition/modules/quest_scope_and_party.md`](../decomposition/modules/quest_scope_and_party.md) — quest state per character, party credit, turn-in, instance deferral diff --git a/docs/decomposition/README.md b/docs/decomposition/README.md index 217ca75..0ef09d6 100644 --- a/docs/decomposition/README.md +++ b/docs/decomposition/README.md @@ -9,7 +9,7 @@ This workspace contains detailed planning artifacts derived from the finalized m ## Folder Layout - `epics/` - One file per epic with implementation slices. -- `modules/` - [Contract definitions](modules/contracts.md), [client vs server authority](modules/client_server_authority.md), [PvP × combat engine](modules/pvp_combat_integration.md), [full module dependency register](modules/module_dependency_register.md) (all epic modules), [per-module docs](modules/module_dependency_register.md#per-module-documentation), and interface notes. +- `modules/` - [Contract definitions](modules/contracts.md), [client vs server authority](modules/client_server_authority.md), [PvP × combat engine](modules/pvp_combat_integration.md), [quest scope × party](modules/quest_scope_and_party.md), [full module dependency register](modules/module_dependency_register.md) (all epic modules), [per-module docs](modules/module_dependency_register.md#per-module-documentation), and interface notes. - `milestones/` - Phase-gated implementation tracks and pass/fail checklists. ## Working Rules diff --git a/docs/decomposition/modules/E7_M1_QuestStateMachine.md b/docs/decomposition/modules/E7_M1_QuestStateMachine.md index 6ba6e2b..5b9f225 100644 --- a/docs/decomposition/modules/E7_M1_QuestStateMachine.md +++ b/docs/decomposition/modules/E7_M1_QuestStateMachine.md @@ -13,9 +13,11 @@ 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 gather–craft–combat loops without duplicate rewards. +**Scope / party:** [Per-character state by default](quest_scope_and_party.md#persistence-per-character-by-default); optional [party credit and turn-in rules](quest_scope_and_party.md#quest-modes-content-driven) via `QuestDef` and [E8.M1](E8_M1_PartyAndMatchAssembly.md). + ## Responsibilities -- Load and interpret `QuestDef`; track `QuestStepState` per player (or party scope as designed). +- Load and interpret `QuestDef`; track `QuestStepState` **per character**; synchronize party-credit advances per [quest_scope_and_party.md](quest_scope_and_party.md). - Apply `QuestStateTransition` rules for advance, abandon, fail, and complete. - Invoke or subscribe to [E3.M2](E3_M2_RefinementAndRecipeExecution.md) and [E5.M1](E5_M1_CombatRulesEngine.md) (or their events) for step completion predicates. diff --git a/docs/decomposition/modules/E7_M2_RewardAndUnlockRouter.md b/docs/decomposition/modules/E7_M2_RewardAndUnlockRouter.md index cf9660c..38cde7c 100644 --- a/docs/decomposition/modules/E7_M2_RewardAndUnlockRouter.md +++ b/docs/decomposition/modules/E7_M2_RewardAndUnlockRouter.md @@ -11,7 +11,7 @@ ## Purpose -Route quest and encounter outputs to XP, items, unlocks, and flags with **idempotent** delivery ([E7.M1](E7_M1_QuestStateMachine.md) completion, [E2.M2](E2_M2_XpAwardAndLevelEngine.md), [E3.M3](E3_M3_ItemizationAndInventorySchema.md)). +Route quest and encounter outputs to XP, items, unlocks, and flags with **idempotent** delivery ([E7.M1](E7_M1_QuestStateMachine.md) completion, [E2.M2](E2_M2_XpAwardAndLevelEngine.md), [E3.M3](E3_M3_ItemizationAndInventorySchema.md)). **Party:** [Per-character idempotent grants](quest_scope_and_party.md#rewards-e7m2) when party credit completes multiple characters. ## Responsibilities diff --git a/docs/decomposition/modules/E8_M1_PartyAndMatchAssembly.md b/docs/decomposition/modules/E8_M1_PartyAndMatchAssembly.md index 814d0e6..ef50c14 100644 --- a/docs/decomposition/modules/E8_M1_PartyAndMatchAssembly.md +++ b/docs/decomposition/modules/E8_M1_PartyAndMatchAssembly.md @@ -33,6 +33,7 @@ Party creation, invites, ready-state, and party-scoped hooks for cooperative act - **E5.M4** — GroupCombatScaling. - **E8.M2** — GuildCorpProgressionState. +- **E7.M1** — [QuestStateMachine](E7_M1_QuestStateMachine.md) when `QuestDef` uses party credit or leader-only turn-in ([quest scope](quest_scope_and_party.md)). ## Related implementation slices diff --git a/docs/decomposition/modules/contracts.md b/docs/decomposition/modules/contracts.md index b03bcf8..cc3f169 100644 --- a/docs/decomposition/modules/contracts.md +++ b/docs/decomposition/modules/contracts.md @@ -81,6 +81,7 @@ A module’s register **Status** can move to **Ready** when the contracts it **e - [tech stack](../../architecture/tech_stack.md) — Protobuf vs JSON spike, content validation, client/server split - [Client vs server authority](client_server_authority.md) — intents vs state, E1/E5 defaults, deferred networking choices - [PvP and the combat engine](pvp_combat_integration.md) — E5.M1 gating with E6.M1, deny reasons +- [Quest scope and party rules](quest_scope_and_party.md) — per-character quest state, party credit, turn-in - [Module dependency register](module_dependency_register.md) - [Decomposition README](../README.md) diff --git a/docs/decomposition/modules/module_dependency_register.md b/docs/decomposition/modules/module_dependency_register.md index 6d566bd..5a06862 100644 --- a/docs/decomposition/modules/module_dependency_register.md +++ b/docs/decomposition/modules/module_dependency_register.md @@ -2,7 +2,7 @@ Tracks cross-epic dependencies and contract readiness. Every **Depends On** module ID in this table has its own row (closed graph). -**Contract** means a stable boundary with a defined artifact (Protobuf wire message, JSON Schema content file, telemetry catalog entry, or server-internal type until promoted). See **[What a contract is](contracts.md)** for kinds, repo layout, and versioning. **Authority** (who owns `PositionState`, camera, combat outcomes): **[Client vs server authority](client_server_authority.md)**. **PvP × combat:** **[PvP and the combat engine](pvp_combat_integration.md)**. +**Contract** means a stable boundary with a defined artifact (Protobuf wire message, JSON Schema content file, telemetry catalog entry, or server-internal type until promoted). See **[What a contract is](contracts.md)** for kinds, repo layout, and versioning. **Authority** (who owns `PositionState`, camera, combat outcomes): **[Client vs server authority](client_server_authority.md)**. **PvP × combat:** **[PvP and the combat engine](pvp_combat_integration.md)**. **Quests × party:** **[Quest scope and party rules](quest_scope_and_party.md)**. Fleshed-out scope, contracts, and integration notes live in **per-module documents** (see [Per-module documentation](#per-module-documentation)). @@ -69,6 +69,10 @@ Fleshed-out scope, contracts, and integration notes live in **per-module documen When hostile actions can target **players**, [E5.M1 — CombatRulesEngine](E5_M1_CombatRulesEngine.md) **must** consult [E6.M1 — PvPEligibilityAndFlagState](E6_M1_PvPEligibilityAndFlagState.md) in the same server handling path before applying effects. **PvE-only** milestones may use a **stub** that denies all player-target hostility until PvP is enabled. Shape and deny reasons: **[PvP and the combat engine](pvp_combat_integration.md)**. +### Cross-cutting: quests and party + +Quest state is **per-character** by default; **party credit** and **leader-only turn-in** use [E8.M1 — PartyAndMatchAssembly](E8_M1_PartyAndMatchAssembly.md) when enabled in `QuestDef`. Solo milestones need no party service. Details: **[Quest scope and party rules](quest_scope_and_party.md)**. + ### Epic 7 — Quest / Faction | Module ID | Module Name | Depends On | Contract Needed | Phase Required | Status | diff --git a/docs/decomposition/modules/quest_scope_and_party.md b/docs/decomposition/modules/quest_scope_and_party.md new file mode 100644 index 0000000..f3be842 --- /dev/null +++ b/docs/decomposition/modules/quest_scope_and_party.md @@ -0,0 +1,69 @@ +# Quest scope and party rules (#5) + +This doc fixes **solo vs party** quest behavior: where `QuestStepState` lives, who gets credit, who can turn in, and how open-world vs instanced scope is handled. It complements [E7.M1 — QuestStateMachine](E7_M1_QuestStateMachine.md), [E7.M2 — RewardAndUnlockRouter](E7_M2_RewardAndUnlockRouter.md), and [E8.M1 — PartyAndMatchAssembly](E8_M1_PartyAndMatchAssembly.md). + +--- + +## Persistence: per-character by default + +- **Authoritative state** for a quest is stored **per character** (`QuestStepState` keyed by character / player id, plus quest id and any run id if replays exist). +- There is **no** single shared “party quest row” in the prototype model; party play is expressed by **synchronizing advances** across multiple per-character states when content opts in (see below). + +**Rationale:** Avoids orphan state when members leave the party, keeps abandon/reset rules simple, and matches “classless solo-friendly” progression with optional co-op credit. + +--- + +## Quest modes (content-driven) + +Express in **`QuestDef`** (or equivalent content) — exact field names are for the content schema when added: + +| Mode | Behavior | +|------|----------| +| **Solo (default)** | Objectives and completion use **only** the acting character. No read of [E8.M1](E8_M1_PartyAndMatchAssembly.md) `PartyState`. | +| **Party credit** | When an objective completes, the server evaluates **eligible party members** and advances **each** eligible character’s `QuestStepState` **idem**potently (same step transition, no double-apply). Eligibility rules are data-driven, e.g. in zone, within distance of completer, alive, was in party when step started—minimum set TBD per quest in content. | +| **Leader-only turn-in (optional)** | If set, only the **party leader** (per authoritative `PartyState`) may trigger the final hand-in / complete interaction; otherwise **any** character in completable state may turn in. | + +**Starting / accepting:** Each character **accepts** the quest individually unless content defines a rare “party accepts as one” flow (defer unless needed); prototype can require all intended recipients to accept the same quest id. + +--- + +## Party dependency + +- **Party credit** and **leader-only turn-in** require server-authoritative **party membership** from [E8.M1 — PartyAndMatchAssembly](E8_M1_PartyAndMatchAssembly.md). +- **Milestone ordering:** Solo quests ship without E8.M1. **Party-credit** quests are **gated** until E8.M1 (or a minimal stub that returns “solo only”) exists; document in slice plans. + +--- + +## Rewards: E7.M2 + +- After completion, **rewards are granted per character** with **idempotent** keys (e.g. `(character_id, quest_id, completion_epoch_or_counter)`). +- If **party credit** advanced multiple characters to completion in one logical event, **each** receives their bundle per `QuestRewardBundle` rules (same bundle vs per-role bundles—content choice). + +--- + +## Open world vs instances (prototype) + +- **Prototype default:** Objectives live in **shared zones** ([E4.M1](E4_M1_ZoneGraphAndTravelRules.md)); no separate quest instance id required. +- **Instanced steps (later):** When dungeon / private instance exists, bind objectives to an **`instance_id`** (or shard key) so credit does not leak across instances. Wire when instance module and E4 handoff slices define the authoritative instance handle. + +--- + +## Edge cases (explicit) + +- **Member leaves party mid-quest:** Per-character state **freezes** at last server-advanced step unless `QuestDef` defines abandon-on-leave. No implicit merge of two solo runs into one party run. +- **Disband:** Same as leave for remaining members; leader-only turn-in re-evaluates on next `PartyState` update. + +--- + +## Telemetry + +- Emit `quest_step_complete` / `quest_complete` **per character** credited; optional correlation id linking party-synchronized advances for funnel debugging. + +--- + +## Related docs + +- [E7.M1 — QuestStateMachine](E7_M1_QuestStateMachine.md) +- [E7.M2 — RewardAndUnlockRouter](E7_M2_RewardAndUnlockRouter.md) +- [E8.M1 — PartyAndMatchAssembly](E8_M1_PartyAndMatchAssembly.md) +- [Module dependency register — cross-cutting: quests and party](module_dependency_register.md#cross-cutting-quests-and-party)