# E5.M2 — Prototype story backlog (NpcAiAndBehaviorProfiles) Working backlog for **Epic 5 — Slice 2** ([NPC archetypes and telegraphs](../decomposition/epics/epic_05_pve_combat.md#slice-2---npc-archetypes-and-telegraphs)). Decomposition and contracts: [E5.M2 — NpcAiAndBehaviorProfiles](../decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md). **Full-stack policy:** Epics deliver **playable game features**. Every **player-visible** story has a **`client`** Linear issue created in **this same decomposition pass** — not an undocumented follow-up. Reference: [E5M1 (paired server+client)](../plans/E5M1-prototype-backlog.md). **Labels (Linear):** every issue **`E5.M2`**; add **`server`** or **`client`** + **`Story`** as listed. **Precursor (do not re-scope):** [E5.M1](../decomposition/modules/E5_M1_CombatRulesEngine.md) combat spine — ability catalog ([NEO-76](https://linear.app/neon-sprawl/issue/NEO-76)–[NEO-79](https://linear.app/neon-sprawl/issue/NEO-79)), cast + **`CombatResolution`** ([NEO-82](https://linear.app/neon-sprawl/issue/NEO-82)), combat-targets GET ([NEO-83](https://linear.app/neon-sprawl/issue/NEO-83)), client HUD + capstone ([NEO-85](https://linear.app/neon-sprawl/issue/NEO-85), [NEO-86](https://linear.app/neon-sprawl/issue/NEO-86)). **`ThreatState`** / aggro was **stub-only** in Slice 1 — this module owns it. **Upstream (must be landed):** [E5.M1](../decomposition/modules/E5_M1_CombatRulesEngine.md) **Ready**; [E1.M3](../decomposition/modules/E1_M3_InteractionAndTargetingLayer.md) targeting + tab cycle ([NEO-23](https://linear.app/neon-sprawl/issue/NEO-23)–[NEO-26](https://linear.app/neon-sprawl/issue/NEO-26)). **Prototype NPC spine (frozen in E5M2-01):** **three** `NpcBehaviorDef` rows — ids **`prototype_melee_pressure`**, **`prototype_ranged_control`**, **`prototype_elite_mini_boss`** — one per vision archetype (melee pressure, ranged control, elite mini-boss). **Three** combat NPC **instance** ids replace E1.M3/E5.M1 dummies: **`prototype_npc_melee`**, **`prototype_npc_ranged`**, **`prototype_npc_elite`** (each binds a behavior def + world anchor). **Linear issues (created):** attach `docs/plans/NEO-*-implementation-plan.md` on the story branch when work starts. | Slug | Layer | Linear | |------|-------|--------| | E5M2-01 | server | [NEO-87](https://linear.app/neon-sprawl/issue/NEO-87) | | E5M2-02 | server | [NEO-88](https://linear.app/neon-sprawl/issue/NEO-88) | | E5M2-03 | server | [NEO-89](https://linear.app/neon-sprawl/issue/NEO-89) | | E5M2-04 | server | [NEO-90](https://linear.app/neon-sprawl/issue/NEO-90) | | E5M2-05 | server | [NEO-91](https://linear.app/neon-sprawl/issue/NEO-91) | | E5M2-06 | server | [NEO-92](https://linear.app/neon-sprawl/issue/NEO-92) | | E5M2-07 | server | [NEO-93](https://linear.app/neon-sprawl/issue/NEO-93) | | E5M2-08 | server | [NEO-94](https://linear.app/neon-sprawl/issue/NEO-94) | | E5M2-09 | server | [NEO-95](https://linear.app/neon-sprawl/issue/NEO-95) | | E5M2-10 | server | [NEO-96](https://linear.app/neon-sprawl/issue/NEO-96) | | E5M2-11 | client | [NEO-97](https://linear.app/neon-sprawl/issue/NEO-97) | | E5M2-12 | client | [NEO-98](https://linear.app/neon-sprawl/issue/NEO-98) | **Dependency graph in Linear:** E5M2-02 blocked by E5M2-01. E5M2-03 blocked by E5M2-02. E5M2-04 blocked by E5M2-03. E5M2-05 blocked by E5M2-03. E5M2-06 blocked by E5M2-05. E5M2-07 blocked by E5M2-06 and E5M2-03. E5M2-08 blocked by E5M2-07. E5M2-09 blocked by E5M2-08. E5M2-10 blocked by E5M2-07 (may parallel E5M2-09). E5M2-11 blocked by E5M2-08 and E5M2-09. E5M2-12 blocked by E5M2-11. **Board order:** estimates **1–12** matching slug order (E5M2-01 = 1 … E5M2-12 = 12). On the Epic 5 project board, sort by **Estimate** (ascending). --- ## Story order (recommended) | Order | Slug | Layer | Depends on | |-------|------|-------|------------| | 1 | **E5M2-01** | server | E5.M1 Ready | | 2 | **E5M2-02** | server | E5M2-01 | | 3 | **E5M2-03** | server | E5M2-02 | | 4 | **E5M2-04** | server | E5M2-03 | | 5 | **E5M2-05** | server | E5M2-03 | | 6 | **E5M2-06** | server | E5M2-05 | | 7 | **E5M2-07** | server | E5M2-06, E5M2-03 | | 8 | **E5M2-08** | server | E5M2-07 | | 9 | **E5M2-09** | server | E5M2-08 | | 10 | **E5M2-10** | server | E5M2-07 | | 11 | **E5M2-11** | client | E5M2-08, E5M2-09 | | 12 | **E5M2-12** | client | E5M2-11 | **Downstream (separate modules):** [E5.M3](../decomposition/modules/E5_M3_EncounterAndRewardTables.md) encounters + loot; [E4.M2](../decomposition/modules/E4_M2_SpawnEcologyController.md) spawn ecology; [E1.M4](../decomposition/modules/E1_M4_AbilityInputScaffold.md) may consume telegraph deny hints later. --- ## Kickoff decisions (decomposition defaults) | Topic | Decision | Rationale | |-------|----------|-----------| | Archetype count | **3** frozen behavior defs | Vision prototype minimum; epic Slice 2 | | Dummy migration | **Replace** `prototype_target_alpha` / `beta` with **3 NPC instance ids** | Vision asks for 3 enemy archetypes, not passive dummies + NPCs | | NPC instance ids | **`prototype_npc_melee`**, **`prototype_npc_ranged`**, **`prototype_npc_elite`** | Stable prefix; each references a `behaviorDefId` | | Aggro trigger | **First damaging cast** on NPC + **proximity re-aggro** inside `aggroRadius` | Deterministic; no random target swaps | | Leash | **Return idle** when holder player leaves `leashRadius` | Simple anti-kite prototype rule | | ThreatState | **In-memory** per-NPC aggro holder (`playerId` or empty) | E5.M1 stub → real store here | | Player HP | **Session in-memory** **`IPlayerCombatHealthStore`** (100 default); **no Postgres** | NPC pressure readable in Godot without E5.M1 persistence scope | | NPC tick | **Lazy advance** on **`GET …/npc-runtime-snapshot`** poll (client ~1 Hz in combat pocket) | Mirrors cooldown snapshot poll ([NEO-32](https://linear.app/neon-sprawl/issue/NEO-32)) | | Telegraph wire | **`GET /game/world/npc-runtime-snapshot`** v1 — states + active **`TelegraphEvent`** rows | Single poll surface; no client-side windup math | | NPC attacks | **Deterministic** damage from `NpcBehaviorDef.attackDamage` after telegraph resolves | Matches E5.M1 no-RNG combat | | PvP | NPCs **never** acquire player targets blocked by E6 stub | [pvp_combat_integration.md](../decomposition/modules/pvp_combat_integration.md) | | World placement | Static **`PrototypeNpcRegistry`** (successor to target registry anchors) until [E4.M2](../decomposition/modules/E4_M2_SpawnEcologyController.md) | Same static-registry pattern as E5.M1 dummies | | HUD fidelity | Prototype Labels / debug panels (not final art) | NEO-85 / NEO-97 precedent | --- ### E5M2-01 — Prototype NpcBehaviorDef catalog + schemas + CI **Goal:** Lock content shape and CI validation for **three** frozen NPC behavior archetypes before server load. **In scope** - `content/schemas/npc-behavior-def.schema.json`. - `content/npc-behaviors/prototype_npc_behaviors.json` with stable **`id`** values: **`prototype_melee_pressure`**, **`prototype_ranged_control`**, **`prototype_elite_mini_boss`**. - Fields: **`displayName`**, **`archetypeKind`** enum (`melee_pressure` / `ranged_control` / `elite_mini_boss`), **`maxHp`**, **`aggroRadius`**, **`leashRadius`**, **`telegraphWindupSeconds`**, **`attackDamage`**, **`attackCooldownSeconds`**. - `scripts/validate_content.py`: schema validation, duplicate ids, exact three-id allowlist, positive numeric guards. - Designer note in [E5_M2](../decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md) + `content/README.md`. **Out of scope** - Server loader, runtime engine, HTTP, Godot. **Acceptance criteria** - [x] PR gate validates NPC behavior JSON against schema. - [x] Exactly three prototype behavior ids; duplicate `id` fails CI. - [x] Stable id list documented in module doc freeze box. **Landed ([NEO-87](https://linear.app/neon-sprawl/issue/NEO-87)):** [`content/npc-behaviors/prototype_npc_behaviors.json`](../../content/npc-behaviors/prototype_npc_behaviors.json), [`npc-behavior-def.schema.json`](../../content/schemas/npc-behavior-def.schema.json), CI gates in [`validate_content.py`](../../scripts/validate_content.py); plan [NEO-87-implementation-plan.md](NEO-87-implementation-plan.md). --- ### E5M2-02 — Server NPC behavior catalog load (fail-fast) **Goal:** Disk → host: startup load of `content/npc-behaviors/*.json` with CI-parity validation. **In scope** - Loader + catalog types under `server/NeonSprawl.Server/Game/Npc/` (path finalized in plan). - Fail-fast on malformed files, duplicate ids, allowlist mismatch with CI. - Unit tests (AAA) for loader happy path and failure modes. - `server/README.md` section. **Out of scope** - Injectable registry interface (E5M2-03), HTTP projection, runtime tick. **Acceptance criteria** - [x] Host fails startup on invalid NPC behavior JSON (mirror CI rules). - [x] Tests cover at least one happy path and one malformed catalog rejection. **Landed ([NEO-88](https://linear.app/neon-sprawl/issue/NEO-88)):** fail-fast server load of `content/npc-behaviors/*_npc_behaviors.json` at startup — `server/NeonSprawl.Server/Game/Npc/`; plan [NEO-88-implementation-plan.md](NEO-88-implementation-plan.md). --- ### E5M2-03 — Injectable `INpcBehaviorDefinitionRegistry` + DI **Goal:** Replace direct catalog access with injectable registry; wire into host DI. **In scope** - `INpcBehaviorDefinitionRegistry` + implementation backed by E5M2-02 catalog. - `TryNormalizeKnown` / `GetDefinitionsInIdOrder` parity with ability registry patterns. - DI extension method; unit tests (AAA). **Out of scope** - HTTP routes, NPC runtime, client. **Acceptance criteria** - [x] Registry resolves all three frozen behavior ids. - [x] Unknown id normalization fails closed. **Landed ([NEO-89](https://linear.app/neon-sprawl/issue/NEO-89)):** `INpcBehaviorDefinitionRegistry` + `NpcBehaviorDefinitionRegistry` + `PrototypeNpcBehaviorRegistry` in `server/NeonSprawl.Server/Game/Npc/`; plan [NEO-89-implementation-plan.md](NEO-89-implementation-plan.md). --- ### E5M2-04 — GET `/game/world/npc-behavior-definitions` **Goal:** Read-only world projection of behavior defs for client labels and Bruno smokes. **In scope** - `NpcBehaviorDefinitionsWorldApi` + versioned DTOs in `Game/Npc/`. - Integration tests (AAA); Bruno folder `bruno/neon-sprawl-server/npc-behavior-definitions/`. - `server/README.md` route section. **Out of scope** - Runtime state, telegraphs, Godot. **Acceptance criteria** - [x] GET returns all three defs in ascending `id` order with `schemaVersion` **1**. - [x] Bruno happy GET passes in CI Bruno step. **Landed ([NEO-90](https://linear.app/neon-sprawl/issue/NEO-90)):** **`GET /game/world/npc-behavior-definitions`** — `NpcBehaviorDefinitionsWorldApi` + DTOs in `Game/Npc/`; plan [NEO-90-implementation-plan.md](NEO-90-implementation-plan.md); Bruno `bruno/neon-sprawl-server/npc-behavior-definitions/`. --- ### E5M2-05 — Prototype NPC instance registry + combat-target migration **Goal:** Replace passive alpha/beta dummies with **three** NPC combat instances wired into targeting + HP stores. **In scope** - `PrototypeNpcRegistry` (or extend targeting registry with NPC metadata): instance id, `behaviorDefId`, world anchor, shared lock radius convention. - Migrate **`PrototypeTargetRegistry`** / **`ICombatEntityHealthStore`** gates from alpha/beta → three NPC ids; max HP from behavior def. - Update Bruno combat-targets / ability-cast / target-select smokes; server tests. - Document breaking id change + client constant migration requirement in plan. **Out of scope** - Behavior tick, aggro, telegraphs (E5M2-06+). - Godot markers — **client counterpart [NEO-97](#)** updates markers in parallel story after server ids land (blockedBy E5M2-08 for HUD; markers can land in E5M2-11). **Acceptance criteria** - [x] Cast + combat-targets GET operate on three NPC ids only (alpha/beta removed). - [x] Each instance references a valid frozen `behaviorDefId`. - [x] Bruno defeat spine passes for at least one archetype. **Landed ([NEO-91](https://linear.app/neon-sprawl/issue/NEO-91)):** **`PrototypeNpcRegistry`** + combat-target migration — three NPC instance ids replace alpha/beta; per-archetype max HP from behavior catalog; plan [NEO-91-implementation-plan.md](NEO-91-implementation-plan.md). **Client counterpart:** [NEO-97](https://linear.app/neon-sprawl/issue/NEO-97) — archetype markers + telegraph HUD (after runtime snapshot lands). --- ### E5M2-06 — AggroRule engine + `IThreatStateStore` **Goal:** Deterministic aggro: NPC acquires holder on first damaging player cast; clears on leash break. **In scope** - `IThreatStateStore` + in-memory implementation keyed by NPC instance id. - `AggroOperations.TryAcquire` / `TryClearOnLeash` using player **`PositionState`** + registry anchors. - Hook from **`AbilityCastApi`** after successful resolve when **`DamageDealt > 0`** (player → NPC). - Unit + integration tests (AAA). **Out of scope** - NPC attack loop, telegraphs, client HUD. **Acceptance criteria** - [x] First damaging cast on NPC sets aggro holder to casting player id. - [x] Holder clears when player leaves `leashRadius` (deterministic distance check). - [x] Re-aggro inside radius after clear follows same first-hit rule. **Landed ([NEO-92](https://linear.app/neon-sprawl/issue/NEO-92)):** **`IThreatStateStore`** + **`AggroOperations`** — acquire on damaging cast, leash clear on move/cast; plan [NEO-92-implementation-plan.md](NEO-92-implementation-plan.md). --- ### E5M2-07 — NPC behavior state machine + lazy tick advance **Goal:** Server-owned NPC states: **`idle`** → **`aggro`** → **`telegraph_windup`** → **`attack_execute`** → **`recover`** with catalog-driven timings. **In scope** - `NpcRuntimeOperations.AdvanceAll` (or per-id) — engine + DI only in NEO-93; [NEO-94](https://linear.app/neon-sprawl/issue/NEO-94) invokes from **`GET /game/world/npc-runtime-snapshot`** with monotonic clock delta cap. - State transitions emit internal events for telemetry hooks (E5M2-10). - Unit tests with injected clock for deterministic transitions. **Out of scope** - HTTP DTO projection (E5M2-08), player damage (E5M2-09), Godot. **Acceptance criteria** - [x] Aggro'd NPC enters telegraph after `attackCooldownSeconds` elapses from last attack. - [x] Windup duration matches `telegraphWindupSeconds` from behavior def. - [x] Idle NPC with no aggro holder does not telegraph. - [x] Full transition chain **`idle` → `aggro` → `telegraph_windup` → `attack_execute` → `recover`** reachable with holder set (deterministic injected clock). **Landed ([NEO-93](https://linear.app/neon-sprawl/issue/NEO-93)):** **`INpcRuntimeStateStore`** + **`NpcRuntimeOperations.AdvanceAll`** — catalog-driven state machine, lazy tick with delta cap; plan [NEO-93-implementation-plan.md](NEO-93-implementation-plan.md). --- ### E5M2-08 — TelegraphEvent snapshot GET + wire DTOs **Goal:** **`GET /game/world/npc-runtime-snapshot`** returns authoritative NPC runtime rows + active telegraphs for client poll. **In scope** - `NpcRuntimeSnapshotWorldApi` + DTOs: per-NPC **`state`**, **`aggroHolderPlayerId`**, active **`TelegraphEvent`** (`telegraphId`, `npcInstanceId`, `windupRemainingSeconds`, `archetypeKind`, …). - Handler invokes E5M2-07 lazy tick before read. - Integration tests (AAA); Bruno `bruno/neon-sprawl-server/npc-runtime-snapshot/`. - `server/README.md` section. **Out of scope** - Godot poll client (E5M2-11). - Player damage application (E5M2-09). **Acceptance criteria** - [x] Snapshot reflects state transition within one poll generation after aggro. - [x] Active telegraph row appears during windup with decreasing remaining time. - [x] Bruno smoke: lock NPC → damage → poll until telegraph row present. **Landed ([NEO-94](https://linear.app/neon-sprawl/issue/NEO-94)):** **`GET /game/world/npc-runtime-snapshot`** — **`NpcRuntimeSnapshotWorldApi`** + DTOs, lazy **`AdvanceAll`** on poll, nested **`activeTelegraph`**; plan [NEO-94-implementation-plan.md](NEO-94-implementation-plan.md). **Client counterpart:** [NEO-97](https://linear.app/neon-sprawl/issue/NEO-97) — telegraph label + NPC state HUD driven by this GET. --- ### E5M2-09 — NPC attack resolve + session player combat HP **Goal:** When telegraph completes, apply **`attackDamage`** to aggro holder via **`IPlayerCombatHealthStore`**; expose player HP on snapshot or dedicated GET. **In scope** - `IPlayerCombatHealthStore` + in-memory implementation (session-only, lazy init 100 HP). - `NpcAttackOperations.TryResolveTelegraphComplete` invoked from tick advance. - Extend snapshot DTO (or add **`GET /game/players/{id}/combat-health`**) with **`currentHp`** / **`maxHp`** for client HUD. - Integration tests: telegraph complete → player HP decreases deterministically. - Reserved **`player_death`** hook site when HP hits 0 (comment-only, no respawn loop). **Out of scope** - Postgres persistence, healing, player defensive abilities. - Godot HUD — **client counterpart [NEO-97](#)**. **Acceptance criteria** - [x] Elite archetype telegraph → attack deals catalog damage to holder. - [x] Player HP read model matches store after NPC attack. - [x] No client-side damage math required for verification (Bruno or integration tests). **Landed ([NEO-95](https://linear.app/neon-sprawl/issue/NEO-95)):** **`IPlayerCombatHealthStore`** + **`NpcAttackOperations.TryResolveTelegraphComplete`** — telegraph complete applies catalog damage; **`GET /game/players/{id}/combat-health`**; plan [NEO-95-implementation-plan.md](NEO-95-implementation-plan.md). **Client counterpart:** [NEO-97](https://linear.app/neon-sprawl/issue/NEO-97) — player HP + incoming telegraph/attack feedback labels. --- ### E5M2-10 — Slice 2 NPC telemetry hook sites **Goal:** Comment-only **`telegraph_fired`** and **`npc_state_transition`** hook sites in NPC runtime path. **In scope** - TODO(E9.M1) markers at telegraph start and on state transition commit. - `server/README.md` pointer; module doc cross-link. **Out of scope** - Production ingest, Godot. **Acceptance criteria** - [x] Hook names match [epic_05 Slice 2](../decomposition/epics/epic_05_pve_combat.md#slice-2---npc-archetypes-and-telegraphs) vocabulary. - [x] No runtime behavior change beyond comments. **Landed ([NEO-96](https://linear.app/neon-sprawl/issue/NEO-96)):** comment-only **`telegraph_fired`** + **`npc_state_transition`** hook sites in **`NpcRuntimeOperations`**; plan [NEO-96-implementation-plan.md](NEO-96-implementation-plan.md). --- ### E5M2-11 — Client telegraph HUD + NPC archetype markers **Goal:** Godot shows **server-owned** telegraph timing, NPC state, and archetype markers for all three instances. **In scope** - `client/scripts/npc_runtime_client.gd` — poll **`GET /game/world/npc-runtime-snapshot`** (~1 Hz when combat HUD visible). - `client/scripts/npc_archetype_markers.gd` — replace alpha/beta dummy markers with three archetype capsules + labels. - HUD labels: **`TelegraphLabel`**, **`NpcStateLabel`**, **`PlayerCombatHpLabel`** under `UICanvas`. - Update `prototype_target_constants.gd` / tab cycle for three NPC ids (server parity). - GdUnit tests with HTTP doubles ([testing-expectations.md](../../.cursor/rules/testing-expectations.md)). - `docs/manual-qa/NEO-97.md` — **Godot** steps (server + client running). - `client/README.md` NPC / telegraph section. **Out of scope** - Final VFX art; dodge mechanics (prototype shows telegraph only). **Acceptance criteria** - [x] Player-visible telegraph countdown matches server snapshot within one poll frame. - [x] Tab cycle visits three NPC instances in documented order. - [x] Manual QA checklist exercisable without Bruno. **Landed ([NEO-97](https://linear.app/neon-sprawl/issue/NEO-97)):** Godot poll clients + telegraph/NPC state/player HP HUD labels; combat-active ~1 Hz poll gate; plan [NEO-97-implementation-plan.md](NEO-97-implementation-plan.md); manual QA [NEO-97](../manual-qa/NEO-97.md). **Client counterpart:** this issue (**NEO-97**). --- ### E5M2-12 — Playable NPC telegraph combat capstone (Godot) **Goal:** Prove Epic 5 Slice 2 acceptance **in Godot**: aggro a melee NPC, observe telegraph, take damage, defeat all three archetypes — without Bruno. **In scope** - `docs/manual-qa/NEO-98.md` single-session script covering three archetypes. - `client/README.md` end-to-end NPC combat loop section. - Update [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) E5.M2 row when complete. **Out of scope** - Encounters/loot ([E5.M3](../decomposition/modules/E5_M3_EncounterAndRewardTables.md)), spawn ecology ([E4.M2](../decomposition/modules/E4_M2_SpawnEcologyController.md)). **Acceptance criteria** - [ ] Human completes script with server + client; telegraph timing readable before damage. - [ ] Epic 5 Slice 2 AC: telegraph timing matches UI feedback; aggro rules feel deterministic in manual QA. - [ ] Re-read [epic_05 Definition of Done](../decomposition/epics/epic_05_pve_combat.md#definition-of-done) for prototype minimums. **Client counterpart:** this issue (**NEO-98**). --- ## After this backlog - **[E5.M3](../decomposition/modules/E5_M3_EncounterAndRewardTables.md)** Slice 3 — decompose when E5.M2 lands (encounters + loot routing). - Track delivery in Linear; keep `blockedBy` synchronized if scope changes. - For each issue kickoff: `docs/plans/{NEO-XX}-implementation-plan.md` per [story-kickoff](../../.cursor/rules/story-kickoff.md). - Add `docs/manual-qa/{NEO-XX}.md` for player-visible **client** stories when implementation lands. ## Decomposition complete checklist - [x] Every player-visible AC has a **`client`** Linear issue (**NEO-97**, **NEO-98**) - [x] No “optional follow-up” / “future client” without NEO-XX - [x] Capstone client issue exists for playable Godot verification (**NEO-98**) - [x] [documentation_and_implementation_alignment.md](../decomposition/modules/documentation_and_implementation_alignment.md) updated - [x] [module_dependency_register.md](../decomposition/modules/module_dependency_register.md) E5.M2 note updated when issues are created ## Related docs - [E5_M2_NpcAiAndBehaviorProfiles.md](../decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md) - [E5_M1_CombatRulesEngine.md](../decomposition/modules/E5_M1_CombatRulesEngine.md) - [epic_05_pve_combat.md](../decomposition/epics/epic_05_pve_combat.md) - [abilities.md](../game-design/abilities.md) - [pvp_combat_integration.md](../decomposition/modules/pvp_combat_integration.md) - [client_server_authority.md](../decomposition/modules/client_server_authority.md)