# Quest scope and party rules 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 “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)