neon-sprawl/docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfi...

14 KiB

E5.M2 — NpcAiAndBehaviorProfiles

Summary

Field Value
Module ID E5.M2
Epic Epic 5 — PvE Combat
Stage target Prototype
Status Ready — Slice 2 backlog E5M2-prototype-backlog.md: E5M2-01 NEO-87 catalog + CI landed · E5M2-02 NEO-88 server load landed · E5M2-03 NEO-89 registry + DI landed · E5M2-04 NEO-90 behavior-definitions GET landed · E5M2-05 NEO-91 NPC instance registry + combat-target migration landed · E5M2-06 NEO-92 aggro rule + threat store landed · E5M2-07 NEO-93 NPC runtime state machine landed · E5M2-08 NEO-94 runtime snapshot GET landed · E5M2-09 NEO-95 NPC attack resolve + player combat HP landed · E5M2-10 NEO-96 NPC runtime telemetry hooks landed · E5M2-11 NEO-97 client telegraph HUD landed · E5M2-12 NEO-98 playable capstone landed
Linear Label E5.M2 · E5M2-prototype-backlog.md E5M2-01 NEO-87 · E5M2-02 NEO-88 · E5M2-03 NEO-89 · E5M2-04 NEO-90 · E5M2-05 NEO-91 · E5M2-06 NEO-92 · E5M2-07 NEO-93 · E5M2-08 NEO-94 · E5M2-09 NEO-95 · E5M2-10 NEO-96 · E5M2-11 NEO-97 · E5M2-12 NEO-98

Purpose

Authority: Client vs server — server owns NPC behavior state, aggro holders, telegraph timing, and NPC→player damage; client displays telegraphs and state from polled snapshots only.

Enemy archetype behavior loops, aggro logic, and telegraph scheduling on top of E5.M1 — CombatRulesEngine. Replaces passive prototype_target_alpha / beta dummies with three fight-back NPC instances for the vision prototype minimum (three archetypes).

Responsibilities

  • Run NpcBehaviorDef; emit TelegraphEvent; apply AggroRule / ThreatState integration with combat state.
  • Lazy NPC tick advance on GET /game/world/npc-runtime-snapshot poll (prototype).
  • Session IPlayerCombatHealthStore for incoming NPC damage (no Postgres in Slice 2).

Key contracts

Contract Role
NpcBehaviorDef Archetype scripts or state machines (content JSON + schema).
TelegraphEvent Telegraph timing for UI and dodge windows.
AggroRule Target selection and leash behavior.
ThreatState Per-NPC aggro holder (playerId or empty).

Module dependencies

  • E5.M1 — CombatRulesEngine (player → NPC damage, combat-target HP, cast funnel).

Dependents (by design)

  • E4.M2 — SpawnEcologyController.
  • E5.M3 — EncounterAndRewardTables.

Epic 5 Slice 2 — NPC archetypes and telegraphs: three archetypes (melee pressure, ranged control, elite mini-boss); telemetry telegraph_fired, npc_state_transition. HTTP read model (NEO-90): GET /game/world/npc-behavior-definitionsNpcBehaviorDefinitionsWorldApi + DTOs in Game/Npc/; Bruno bruno/neon-sprawl-server/npc-behavior-definitions/.

Linear backlog (decomposed)

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

Slug Linear
E5M2-01 NEO-87
E5M2-02 NEO-88
E5M2-03 NEO-89
E5M2-04 NEO-90
E5M2-05 NEO-91
E5M2-06 NEO-92
E5M2-07 NEO-93
E5M2-08 NEO-94
E5M2-09 NEO-95
E5M2-10 NEO-96
E5M2-11 NEO-97
E5M2-12 NEO-98

Prototype Slice 2 freeze (E5M2-01)

The first shipped three-archetype NPC spine under content/npc-behaviors/*.json is frozen for behavior binding, aggro tuning, and telegraph timings until a deliberate migration issue expands the roster.

NpcBehaviorDef.id displayName archetypeKind maxHp aggroRadius leashRadius telegraphWindupSeconds attackDamage attackCooldownSeconds attackAbilityId
prototype_melee_pressure Melee Pressure melee_pressure 100 8.0 16.0 1.5 15 3.0 prototype_npc_melee_strike
prototype_ranged_control Ranged Control ranged_control 80 10.0 20.0 2.0 12 4.0 prototype_npc_ranged_shot
prototype_elite_mini_boss Elite Mini-Boss elite_mini_boss 200 8.0 18.0 2.5 25 5.0 prototype_npc_elite_slam

NPC attack abilities (NEO-98): content/abilities/prototype_npc_abilities.json — telegraph resolve uses ability maxRange + baseDamage, not behavior aggroRadius. Behavior attackDamage remains on the HTTP projection and must match ability baseDamage (CI cross-ref). Strike maxRange (horizontal X/Z): melee 2 m, ranged 10 m, elite 4 m.

Ability id baseDamage maxRange
prototype_npc_melee_strike 15 2.0
prototype_npc_ranged_shot 12 10.0
prototype_npc_elite_slam 25 4.0

NPC instance ids (E5M2-05): prototype_npc_melee, prototype_npc_ranged, prototype_npc_elite — each binds one behavior def + world anchor (replaces prototype_target_alpha / beta).

Rules: Do not rename frozen behavior id values without a migration issue. CI (scripts/validate_content.py) and server startup (NEO-88) enforce exactly these three behavior ids, duplicate-id rejection, and leashRadius > aggroRadius per row. Relaxing or changing that gate belongs in a new Linear issue once the catalog intentionally grows. Catalog + CI plan: NEO-87 implementation plan. INpcBehaviorDefinitionRegistry + DI landed (NEO-89, E5M2-03) — game code and HTTP read models should inject the registry, not NpcBehaviorDefinitionCatalog. Read-only HTTP projection: GET /game/world/npc-behavior-definitions (NEO-90, E5M2-04).

Server load (NEO-88): On host startup, server/NeonSprawl.Server/Game/Npc/ loads content/npc-behaviors/*_npc_behaviors.json with the same validation gates as CI and refuses to listen when the catalog is invalid. Config and discovery: server README — NPC behavior catalog. Plan: NEO-88 implementation plan.

NPC behavior definition registry (NEO-89): INpcBehaviorDefinitionRegistry in server/NeonSprawl.Server/Game/Npc/ wraps the startup-loaded catalog for read-only lookup by stable behavior id (TryGetDefinition), trim/lowercase validation (TryNormalizeKnown), and ordered enumeration (GetDefinitionsInIdOrder). Stable prototype id constants: PrototypeNpcBehaviorRegistry. NEO-91+ (instance registry, runtime tick) should inject the interface rather than NpcBehaviorDefinitionCatalog. Plan: NEO-89 implementation plan.

NPC instance registry (NEO-91): PrototypeNpcRegistry in server/NeonSprawl.Server/Game/Npc/ — instance ids prototype_npc_melee, prototype_npc_ranged, prototype_npc_elite with behavior bindings + world anchors; ICombatEntityHealthStore uses catalog maxHp per instance. Plan: NEO-91 implementation plan. Godot prototype_target_constants.gd migration landed in NEO-91; NEO-97 adds HUD poll clients only.

Threat / aggro store (NEO-92): IThreatStateStore + AggroOperations in server/NeonSprawl.Server/Game/Npc/ — first damaging cast acquires holder; leash break clears holder (move + cast hooks). HTTP projection: aggroHolderPlayerId on GET /game/world/npc-runtime-snapshot (NEO-94). Plan: NEO-92 implementation plan.

NPC runtime state machine (NEO-93): INpcRuntimeStateStore + NpcRuntimeOperations.AdvanceAll in server/NeonSprawl.Server/Game/Npc/ — lazy tick advance for idleaggrotelegraph_windupattack_executerecover; holder sync from IThreatStateStore. HTTP projection: GET /game/world/npc-runtime-snapshot (NEO-94). Plan: NEO-93 implementation plan.

NPC runtime snapshot HTTP (NEO-94): GET /game/world/npc-runtime-snapshot — versioned read-only projection (schemaVersion 1, npcInstances, optional nested activeTelegraph) with lazy AdvanceAll on poll. Plan: NEO-94 implementation plan; server README — NPC runtime snapshot (NEO-94); Bruno bruno/neon-sprawl-server/npc-runtime-snapshot/.

Session player combat HP (NEO-95 / NEO-98): IPlayerCombatHealthStore + NpcAttackOperations.TryResolveTelegraphComplete in server/NeonSprawl.Server/Game/Combat/ — telegraph complete looks up behavior attackAbilityId, applies ability catalog baseDamage when the aggro holder is within that ability's maxRange (horizontal X/Z); out-of-range windups whiff. Behavior row attackDamage is projection + CI cross-ref only (not the resolve source). TryStopOnTargetDefeat on cast accept + AdvanceOne defeated guard clears aggro/runtime when the NPC combat-target row is defeated (NEO-98). GET /game/players/{id}/combat-health read model for client HUD. Plan: NEO-95 implementation plan; NEO-98 implementation plan; server README — Session player combat HP (NEO-95); Bruno bruno/neon-sprawl-server/combat-health/.

NPC runtime telemetry hooks (NEO-96): comment-only telegraph_fired + npc_state_transition hook sites in NpcRuntimeOperations.AdvanceAll (TODO(E9.M1); no ingest). Plan: NEO-96 implementation plan; server README — NPC runtime telemetry hooks (NEO-96).

Client telegraph HUD (NEO-97): Godot poll of npc-runtime-snapshot + combat-health; TelegraphLabel, NpcStateLabel, PlayerCombatHpLabel; combat-active ~1 Hz poll gate. Plan: NEO-97 implementation plan; client README — NPC runtime + telegraph HUD (NEO-97); manual QA NEO-97.

Playable NPC telegraph combat capstone (NEO-98): single-session Godot manual QA covering melee telegraph spine + three-archetype defeat — NEO-98 manual QA; client README — End-to-end NPC telegraph combat loop (NEO-98). Plan: NEO-98 implementation plan. Server integration (capstone QA): prototype_npc_abilities.json, behavior attackAbilityId, range-gated telegraph resolve, defeat clears aggro/runtime. Epic 5 Slice 2 client capstone complete.

NPC behavior definitions HTTP (NEO-90): GET /game/world/npc-behavior-definitions — versioned read-only projection (schemaVersion 1, npcBehaviors) backed by INpcBehaviorDefinitionRegistry. Plan: NEO-90 implementation plan; server README — NPC behavior definitions (NEO-90); Bruno bruno/neon-sprawl-server/npc-behavior-definitions/.

Risks and telemetry

  • Telegraph desync: single npc-runtime-snapshot poll surface; client display-only windup tick-down between polls (reconciled on each GET via npc_runtime_hud_state.gd).
  • Aggro confusion: deterministic first-hit + leash rules; instrument npc_state_transition when E9.M1 lands.

Source anchors