# E5.M1 — CombatRulesEngine ## Summary | Field | Value | |--------|--------| | **Module ID** | E5.M1 | | **Epic** | [Epic 5 — PvE Combat](../epics/epic_05_pve_combat.md) | | **Stage target** | Prototype | | **Status** | In Progress — Slice 1 backlog [E5M1-prototype-backlog.md](../../plans/E5M1-prototype-backlog.md): E5M1-01 [NEO-76](https://linear.app/neon-sprawl/issue/NEO-76) ability catalog + CI landed; E5M1-02 [NEO-77](https://linear.app/neon-sprawl/issue/NEO-77) server load landed; E5M1-03 [NEO-79](https://linear.app/neon-sprawl/issue/NEO-79) registry + hotbar/cast migration landed; E5M1-04+ pending (see [dependency register](module_dependency_register.md)) | | **Linear** | Label **`E5.M1`** · [E5M1-prototype-backlog.md](../../plans/E5M1-prototype-backlog.md) **E5M1-01** [NEO-76](https://linear.app/neon-sprawl/issue/NEO-76) → **E5M1-12** [NEO-86](https://linear.app/neon-sprawl/issue/NEO-86); gig XP **E5M1-10** [NEO-44](https://linear.app/neon-sprawl/issue/NEO-44) | ## Purpose **Authority:** [Client vs server](client_server_authority.md#e5m1-combatrulesengine) — server validates intents and computes all outcomes; never trust client damage/healing/crit/death. Core tab-target combat resolution: valid actions against a locked target, hit resolution, cooldown and resource timing, and threat state as needed for prototype encounters. Presents readable outcomes in fixed isometric view and feeds XP awards through [E2.M2](E2_M2_XpAwardAndLevelEngine.md). **PvP:** Single engine for PvE and PvP; player-target hostility **gates** on [E6.M1](E6_M1_PvPEligibilityAndFlagState.md). See [PvP and the combat engine](pvp_combat_integration.md). ## Responsibilities - Combat state machine for tab-target flow (attacks, abilities per prototype scope). - Validate and apply `CombatAction`; produce `CombatResolution` for UI and logs (include **PvP deny reasons** when player targets are blocked; see [pvp_combat_integration.md](pvp_combat_integration.md)). - Integrate with targeting/interaction from **E1.M3** (target lock, valid target checks). - Award combat XP via E2.M2 integration where specified in slices. ## Key contracts | Contract | Role | |----------|------| | `CombatAction` | Attack, ability, or other combat intent from client/input scaffold. | | `CombatResolution` | Hits, misses, damage, denies with reason codes (no silent failures). | | `ThreatState` | Aggro/threat for NPC and encounter coordination (as scoped). | ## Module dependencies - **E1.M3** — [InteractionAndTargetingLayer](E1_M3_InteractionAndTargetingLayer.md): `TargetState`, selection, and alignment with **E1.M4** ([AbilityInputScaffold](E1_M4_AbilityInputScaffold.md)) for `AbilityCastRequest` wiring. - **E2.M2** — [XpAwardAndLevelEngine](E2_M2_XpAwardAndLevelEngine.md): combat XP grants. ## Dependents (by design) - **E5.M2** — NpcAiAndBehaviorProfiles. - **E5.M3** — EncounterAndRewardTables. - **E1.M4** — AbilityInputScaffold sends `AbilityCastRequest` to combat. - **E7.M1** — QuestStateMachine for combat-related quest steps. - **E2.M2** — Invoked as integration caller for XP (not a structural child). ## Related implementation slices See Epic 5 **Slice 1 — Combat rules MVP**: target lock, basic attacks, 4–6 abilities, cooldowns/resources; telemetry `encounter_start`, `ability_used`, `player_death`, `enemy_defeat`. ## Linear backlog (decomposed) Full story tables, kickoff defaults, and **`blockedBy` graph:** [E5M1-prototype-backlog.md](../../plans/E5M1-prototype-backlog.md). | Slug | Linear | |------|--------| | E5M1-01 | [NEO-76](https://linear.app/neon-sprawl/issue/NEO-76) | | E5M1-02 | [NEO-77](https://linear.app/neon-sprawl/issue/NEO-77) | | E5M1-03 | [NEO-79](https://linear.app/neon-sprawl/issue/NEO-79) | | E5M1-04 | [NEO-78](https://linear.app/neon-sprawl/issue/NEO-78) | | E5M1-05 | [NEO-80](https://linear.app/neon-sprawl/issue/NEO-80) | | E5M1-06 | [NEO-81](https://linear.app/neon-sprawl/issue/NEO-81) | | E5M1-07 | [NEO-82](https://linear.app/neon-sprawl/issue/NEO-82) | | E5M1-08 | [NEO-83](https://linear.app/neon-sprawl/issue/NEO-83) | | E5M1-09 | [NEO-84](https://linear.app/neon-sprawl/issue/NEO-84) | | E5M1-10 | [NEO-44](https://linear.app/neon-sprawl/issue/NEO-44) | | E5M1-11 | [NEO-85](https://linear.app/neon-sprawl/issue/NEO-85) | | E5M1-12 | [NEO-86](https://linear.app/neon-sprawl/issue/NEO-86) | ## Prototype Slice 1 freeze (E5M1-01) The **first shipped four-ability combat spine** under `content/abilities/*.json` is **frozen** for hotbar bindings, cast validation, and combat resolution until a deliberate migration or follow-up issue expands the roster. | `AbilityDef.id` | `displayName` | `baseDamage` | `cooldownSeconds` | `abilityKind` | |-----------------|---------------|--------------|-------------------|---------------| | **`prototype_pulse`** | Prototype Pulse | 25 | 3.0 | `attack` | | **`prototype_guard`** | Prototype Guard | 0 | 6.0 | `utility` | | **`prototype_dash`** | Prototype Dash | 0 | 4.0 | `movement` | | **`prototype_burst`** | Prototype Burst | 40 | 5.0 | `attack` | **Rules:** Do **not** rename these `id` values—change **`displayName`** only, or add a new `id` in a follow-up issue. CI ([`scripts/validate_content.py`](../../../scripts/validate_content.py)) and server startup ([NEO-77](../../plans/NEO-77-implementation-plan.md)) enforce **exactly** these four ids and duplicate-`id` rejection across all ability JSON files. Relaxing or changing that gate belongs in a new Linear issue once the catalog intentionally grows. **`prototype_pulse`** at 25 damage × 4 casts defeats a 100 HP prototype dummy (E5M1 backlog default). **`IAbilityDefinitionRegistry`** + hotbar/cast migration **landed** ([NEO-79](../../plans/NEO-79-implementation-plan.md), E5M1-03). ## Prototype notes (NEO-28) Epic 1 **Slice 3** exercises a minimal cast accept/deny surface on **`POST /game/players/{id}/ability-cast`** before the full engine exists: after hotbar/loadout validation ([E1.M4](E1_M4_AbilityInputScaffold.md)), the server requires **`targetId`** to match the persisted combat lock, resolve in the prototype target registry, and sit within horizontal lock radius against authoritative **`PositionState`**. Deny codes **`invalid_target`** and **`out_of_range`** reuse the same strings as E1.M3 **`TargetState.validity`** for vocabulary alignment. **`accepted: true`** still does not imply damage, cooldown commit, or a full **`CombatResolution`** payload — those remain E5.M1 scope. ## Risks and telemetry - Sluggish or opaque tab-target: prototype readability gate; instrument time-in-combat and deny reasons. - Desync logging via E9.M1 taxonomy when available. ## Source anchors - Master plan: [`neon_sprawl_vision.plan.md`](../../../neon_sprawl_vision.plan.md) — Core Epic Map, Epic 5. - [Module dependency register](module_dependency_register.md)