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

10 KiB
Raw Blame History

E5.M1 — CombatRulesEngine

Summary

Field Value
Module ID E5.M1
Epic Epic 5 — PvE Combat
Stage target Prototype
Status In Progress — Slice 1 backlog E5M1-prototype-backlog.md: E5M1-01 NEO-76 ability catalog + CI landed; E5M1-02 NEO-77 server load landed; E5M1-03 NEO-79 registry + hotbar/cast migration landed; E5M1-04 NEO-78 ability-definitions GET landed; E5M1-05 NEO-80 combat entity health store landed; E5M1-06 NEO-81 combat operations + CombatResult landed; E5M1-07 NEO-82 cast POST + wire combatResolution landed; E5M1-08 NEO-83 combat-targets GET landed; E5M1-10 NEO-44 gig XP on defeat landed; E5M1-09+ pending (see dependency register)
Linear Label E5.M1 · E5M1-prototype-backlog.md E5M1-01 NEO-76E5M1-12 NEO-86; gig XP E5M1-10 NEO-44

Purpose

Authority: Client vs server — 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. Combat defeat awards gig XP via IPlayerGigProgressionStore (NEO-44) — not E2.M2 skill XP (progression.md).

PvP: Single engine for PvE and PvP; player-target hostility gates on E6.M1. See PvP and the combat engine.

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).
  • Integrate with targeting/interaction from E1.M3 (target lock, valid target checks).
  • Award gig XP on combat defeat via dedicated gig progression store (NEO-44); do not route default encounter clears through E2.M2 skill XP.

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

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 — Skill XP integration caller for gather/craft/mission paths (not structural child; not combat gig XP).

See Epic 5 Slice 1 — Combat rules MVP: target lock, basic attacks, 46 abilities, cooldowns/resources; telemetry encounter_start, ability_used, player_death, enemy_defeat.

E5M1-04 (NEO-78): GET /game/world/ability-definitionsAbilityDefinitionsWorldApi + DTOs in Game/Combat/ (NEO-78 plan); server README — Ability definitions (NEO-78); Bruno bruno/neon-sprawl-server/ability-definitions/.

E5M1-05 (NEO-80): ICombatEntityHealthStore + InMemoryCombatEntityHealthStore — lazy HP init for PrototypeTargetRegistry dummies at PrototypeCombatConstants.MaxPrototypeTargetHp (100) (NEO-80 plan); server README — Combat entity health (NEO-80).

E5M1-06 (NEO-81): CombatOperations.TryResolve + CombatResult + CombatReasonCodes — deterministic catalog damage, defeated pre-check deny (target_defeated), unknown ability/target validation (NEO-81 plan); server README — Combat engine (NEO-81).

E5M1-07 (NEO-82): AbilityCastApiCombatOperations.TryResolve — nested wire combatResolution on accept, per-ability catalog cooldownSeconds, target_defeated cast deny without cooldown commit (NEO-82 plan); server README — Ability cast (NEO-82); Bruno bruno/neon-sprawl-server/ability-cast/.

E5M1-08 (NEO-83): GET /game/world/combat-targetsCombatTargetsWorldApi + DTOs in Game/Combat/; authoritative HP snapshot from ICombatEntityHealthStore (NEO-83 plan); server README — Combat targets snapshot (NEO-83); Bruno bruno/neon-sprawl-server/combat-targets/.

E5M1-10 (NEO-44): CombatDefeatGigXpGrant on cast accept when targetDefeated25 gig XP to prototype main gig breach via IPlayerGigProgressionStore (not E2.M2 skill XP); GET /game/players/{id}/gig-progression (NEO-44 plan); server README — Gig progression snapshot (NEO-44); Bruno bruno/neon-sprawl-server/gig-progression/.

Linear backlog (decomposed)

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

Slug Linear
E5M1-01 NEO-76
E5M1-02 NEO-77
E5M1-03 NEO-79
E5M1-04 NEO-78
E5M1-05 NEO-80
E5M1-06 NEO-81
E5M1-07 NEO-82
E5M1-08 NEO-83
E5M1-09 NEO-84
E5M1-10 NEO-44
E5M1-11 NEO-85
E5M1-12 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) and server startup (NEO-77) 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, E5M1-03).

Prototype notes (NEO-28)

Epic 1 Slice 3 cast accept/deny on POST /game/players/{id}/ability-cast remains the E1.M4 gate funnel: hotbar/loadout validation (E1.M4), targetId must 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. NEO-82 (E5M1-07): after gates pass, CombatOperations.TryResolve runs; accept returns nested wire combatResolution (damageDealt, targetRemainingHp, targetDefeated, …) and commits per-ability catalog cooldown; target_defeated JSON deny on re-hit at zero HP.

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