From ceef54cd230a39bf075e745a58b5d7fe2c9a9bed Mon Sep 17 00:00:00 2001 From: VinPropane Date: Sat, 30 May 2026 16:55:30 -0400 Subject: [PATCH] NEO-98: add implementation plan for NPC telegraph combat capstone --- docs/plans/NEO-98-implementation-plan.md | 160 +++++++++++++++++++++++ 1 file changed, 160 insertions(+) create mode 100644 docs/plans/NEO-98-implementation-plan.md diff --git a/docs/plans/NEO-98-implementation-plan.md b/docs/plans/NEO-98-implementation-plan.md new file mode 100644 index 0000000..f002047 --- /dev/null +++ b/docs/plans/NEO-98-implementation-plan.md @@ -0,0 +1,160 @@ +# NEO-98 — Implementation plan + +## Story reference + +| Field | Value | +|--------|--------| +| **Key** | NEO-98 | +| **Title** | E5M2-12: Playable NPC telegraph combat capstone (Godot) | +| **Linear** | https://linear.app/neon-sprawl/issue/NEO-98/e5m2-12-playable-npc-telegraph-combat-capstone-godot | +| **Module** | [E5.M2 — NpcAiAndBehaviorProfiles](../decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md) · Epic 5 Slice 2 · backlog **E5M2-12** | +| **Branch** | `NEO-98-e5m2-12-playable-npc-telegraph-combat-capstone` | +| **Server deps** | [NEO-92](https://linear.app/neon-sprawl/issue/NEO-92) aggro + leash (**Done**); [NEO-93](https://linear.app/neon-sprawl/issue/NEO-93) runtime state machine (**Done**); [NEO-94](https://linear.app/neon-sprawl/issue/NEO-94) runtime snapshot GET (**Done**); [NEO-95](https://linear.app/neon-sprawl/issue/NEO-95) NPC attack resolve + player combat HP (**Done**) | +| **Client deps** | [NEO-97](https://linear.app/neon-sprawl/issue/NEO-97) telegraph HUD + archetype markers (**Done**); E5.M1 cast + combat-target HUD ([NEO-85](https://linear.app/neon-sprawl/issue/NEO-85), [NEO-86](https://linear.app/neon-sprawl/issue/NEO-86)) (**Done**) | +| **Pattern** | Capstone integration — [NEO-86](https://linear.app/neon-sprawl/issue/NEO-86) docs + manual QA primary; minimal client gap-fill only if capstone QA fails on `main` | +| **Server counterpart** | NEO-92–NEO-95 server spine; Bruno-only verification is not prototype-complete per [full-stack epic decomposition](../../.cursor/rules/full-stack-epic-decomposition.md) | + +## Kickoff clarifications + +| Topic | Question | Agent recommendation | Answer | +|--------|----------|----------------------|--------| +| **Implementation scope** | Docs-only vs client code? | **Docs + manual QA primary**; fix integration gaps only if capstone QA fails on `main` — [NEO-86](NEO-86-implementation-plan.md) precedent. | **User:** docs-primary; client fixes only if QA fails. | +| **Session baseline** | Fresh server vs fixture POST? | **Fresh server restart** before Godot **F5** — resets NPC HP, aggro/runtime rows, and player combat HP (NEO-86 / NEO-97 precedent); zero Bruno/curl in main checklist. | **User:** fresh restart; no Bruno/curl in checklist. | +| **Archetype order** | Order in single-session script? | **Melee → Ranged → Elite** — matches E5M2-12 backlog goal prose (“aggro a melee NPC… defeat all three archetypes”). | **User:** melee → ranged → elite. | +| **Verification depth** | Full telegraph spine per archetype? | **Full telegraph + player HP on Melee**; Ranged + Elite **defeat + telegraph visible** with documented windup/cooldown — keeps one-session script tractable while satisfying Slice 2 AC. | **User:** melee full; ranged/elite light. | +| **NEO-97 relationship** | Supersede component QA? | **NEO-98 supersedes as capstone**; keep [NEO-97](../manual-qa/NEO-97.md) as component-level regression reference (NEO-85 / NEO-86 pattern). | **Adopted** (repo precedent; not asked). | + +## Goal, scope, and out-of-scope + +**Goal:** Prove Epic 5 Slice 2 acceptance **in Godot**: aggro a melee NPC, observe readable telegraph timing before damage, take incoming NPC damage, defeat all three archetypes — without Bruno. + +**In scope (from Linear + [E5M2-12](E5M2-prototype-backlog.md#e5m2-12--playable-npc-telegraph-combat-capstone-godot)):** + +- **`docs/manual-qa/NEO-98.md`**: numbered **single-session** capstone script — fresh dev player, **Melee → Ranged → Elite**, zero Bruno/curl steps in the main checklist. +- **`client/README.md`**: **End-to-end NPC telegraph combat loop** section — integration checklist (boot → lock → cast → telegraph → player HP → defeat ×3); cross-links NEO-92–NEO-97. +- **Module alignment** (on story completion): update [`documentation_and_implementation_alignment.md`](../decomposition/modules/documentation_and_implementation_alignment.md) E5.M2 row + E5M2-12 backlog checkboxes; note Epic 5 Slice 2 client capstone complete. +- **Integration fixes only if capstone QA fails** on current `main` wiring (unexpected deny, HUD refresh gap, poll gate, etc.). + +**Out of scope (from Linear + backlog):** + +- Encounters/loot ([E5.M3](../decomposition/modules/E5_M3_EncounterAndRewardTables.md)), spawn ecology ([E4.M2](../decomposition/modules/E4_M2_SpawnEcologyController.md)). +- Final VFX art, dodge mechanics, player death flow. +- Bruno-only verification as prototype-complete proof. +- New server APIs or behavior catalog changes. + +## Acceptance criteria checklist + +- [ ] Human completes **`docs/manual-qa/NEO-98.md`** with server + client; telegraph timing readable before damage on the melee spine. +- [ ] Epic 5 Slice 2 AC: telegraph timing matches UI feedback; aggro rules feel deterministic in manual QA. +- [ ] All three archetypes defeated in one session; **`CombatTargetHpLabel`** shows defeated for each. +- [ ] Re-read [epic_05 Definition of Done](../decomposition/epics/epic_05_pve_combat.md#definition-of-done) for prototype minimums. + +## Technical approach + +### 1. Capstone manual QA script (`docs/manual-qa/NEO-98.md`) + +**Preconditions:** Stop any running server; start fresh (`dotnet run`) so in-memory **`dev-local-1`** NPC HP, aggro/runtime rows, and player combat HP reset. Godot **F5** with **no** prior curl/Bruno seeding (hotbar **`prototype_pulse`** bind is automatic — NEO-85 dev bootstrap). + +**Frozen catalog math** (from [E5_M2 freeze box](../decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md#prototype-slice-2-freeze-e5m2-01); player casts **`prototype_pulse`** **25** dmg, ~**3 s** cooldown): + +| Archetype | Instance id | Marker | maxHp | Casts to defeat | attackDamage | windup | cooldown | +|-----------|-------------|--------|-------|-----------------|--------------|--------|----------| +| Melee | `prototype_npc_melee` | orange west **`(-3, -3)`** | 100 | **4** | 15 | 1.5 s | 3.0 s | +| Ranged | `prototype_npc_ranged` | purple SE **`(3, 3)`** | 80 | **4** | 12 | 2.0 s | 4.0 s | +| Elite | `prototype_npc_elite` | gold origin **`(0, 0)`** | 200 | **8** | 25 | 2.5 s | 5.0 s | + +**Melee full spine (telegraph + player HP):** + +1. Walk to **Melee** marker; **Tab** lock **`prototype_npc_melee`** — **`Validity: ok`**. +2. Press **1** (damaging cast): **`NpcStateLabel`** → **`aggro`** (~1 Hz poll); **`PlayerCombatHpLabel`** → **`100/100`**. +3. Wait **≥ 4.5 s** from first cast (3.0 s cooldown + 1.5 s windup): **`NpcStateLabel`** → **`telegraph_windup`**; **`TelegraphLabel`** shows countdown (**`Telegraph: Melee … · ~1.x s (melee)`**) ticking between polls. +4. After windup completes: **`PlayerCombatHpLabel`** → **`85/100`** (15 damage). +5. Press **1** three more times (respect cooldown) until **`CombatTargetHpLabel`** → **`0/100 (defeated)`** and cast feedback shows defeat. + +**Ranged light (defeat + telegraph visible):** + +6. Walk to **Ranged** marker; lock **`prototype_npc_ranged`**. +7. First damaging cast → aggro; wait for **`telegraph_windup`** + readable **`TelegraphLabel`** (2.0 s windup after 4.0 s cooldown from first cast). +8. Cast until defeated (**4** pulses); verify deny on re-cast (**`target_defeated`**). + +**Elite light (defeat + telegraph visible):** + +9. Walk to **Elite** marker; lock **`prototype_npc_elite`**. +10. First damaging cast → aggro; wait for **`telegraph_windup`** + readable **`TelegraphLabel`** (2.5 s windup after 5.0 s cooldown). +11. Cast until defeated (**8** pulses); verify deny on re-cast. + +**Regression spot-checks (end of session):** + +- Cast without lock → **`ability_cast_denied: invalid_target`** (NEO-28). +- **`CombatTargetHpLabel`** + cooldown HUD still work (NEO-85 / NEO-32). +- Optional deeper telegraph/HP checks: [NEO-97 manual QA](../manual-qa/NEO-97.md) (elite incoming-threat row). + +**Notes section (not main checklist steps):** + +- Optional mid-session reset (Development host): `POST /game/__dev/combat-targets-fixture` — see [NEO-97](../manual-qa/NEO-97.md) / [server README — dev fixture](../../../server/README.md#dev-combat-target-fixture-brunomanual-qa). +- Capstone baseline prefers **server restart** over fixture POST. + +### 2. README integration checklist + +New **`## End-to-end NPC telegraph combat loop (NEO-98)`** section after [NEO-97 NPC runtime + telegraph HUD](NEO-97-implementation-plan.md) subsection in `client/README.md`: + +- Flow in prose: fresh server → boot hotbar sync → **Melee** lock → cast → telegraph HUD → player HP drop → defeat → repeat **Ranged** + **Elite**. +- Table mirroring capstone steps (lock, telegraph labels, defeat cast counts). +- Cross-links: NEO-92 (aggro), NEO-94 (runtime snapshot), NEO-95 (player combat HP), NEO-97 (HUD poll clients). +- Pointer to **`docs/manual-qa/NEO-98.md`** as authoritative capstone script. +- Note NEO-97 manual QA as component-level regression. + +### 3. Module alignment (implementation batch or story end) + +When acceptance criteria pass: + +- **`documentation_and_implementation_alignment.md`**: E5.M2 — note **NEO-98 landed**, Epic 5 Slice 2 client capstone complete. +- **`E5M2-prototype-backlog.md`**: E5M2-12 acceptance checkboxes + landed note. +- **`E5_M2_NpcAiAndBehaviorProfiles.md`**: E5M2-12 row + capstone cross-link if not already marked. + +### 4. Integration fixes (conditional) + +Run capstone dry-run on **`main`** before doc-only work; if any step fails, fix minimal client bug in this branch and note in plan **Decisions**. Expected path: docs + README only (NEO-97 HUD wiring landed in PR #136). + +## Files to add + +| Path | Purpose | +|------|---------| +| `docs/plans/NEO-98-implementation-plan.md` | This plan. | +| `docs/manual-qa/NEO-98.md` | Capstone single-session manual QA (zero Bruno/curl in main checklist). | + +## Files to modify + +| Path | Rationale | +|------|-----------| +| `client/README.md` | End-to-end NPC telegraph combat loop section; capstone manual QA link; cross-links NEO-92–NEO-97. | +| `docs/decomposition/modules/documentation_and_implementation_alignment.md` | E5.M2 row — NEO-98 landed + Slice 2 client capstone complete (on story completion). | +| `docs/plans/E5M2-prototype-backlog.md` | E5M2-12 acceptance checkboxes + landed note (on story completion). | +| `docs/decomposition/modules/E5_M2_NpcAiAndBehaviorProfiles.md` | E5M2-12 capstone landed note + manual QA link (on story completion). | + +**Conditional (only if capstone QA fails on `main`):** + +| Path | Rationale | +|------|-----------| +| `client/scripts/main.gd` | Minimal HUD / poll / sync fix for failing capstone step. | +| Other client scripts under `client/scripts/` | Only if root cause is outside `main.gd` (document in plan **Decisions**). | + +## Tests + +| Path | Change | +|------|--------| +| *(none expected)* | Capstone is docs + manual QA; NEO-97 GdUnit suites already cover poll clients, windup interpolation, and HUD helpers. | + +**If integration fix adds/changes client behavior:** add or extend the smallest GdUnit test in the matching NEO-97 suite (`npc_combat_hud_refresh_test.gd`, etc.) — AAA layout per [testing-expectations.md](../../.cursor/rules/testing-expectations.md). + +**Manual verification:** [`docs/manual-qa/NEO-98.md`](../manual-qa/NEO-98.md) — server + Godot; melee telegraph spine + three-archetype defeat without curl. + +## Open questions / risks + +| Question or risk | Agent recommendation | Status | +|------------------|----------------------|--------| +| **Capstone dry-run on `main`** | Run melee spine first before writing final QA copy; fix only if QA fails. | **pending** | +| **Session length (elite ×8 casts)** | Document cast counts + cooldown reminders; elite section is defeat + telegraph visibility only (kickoff depth decision). | **adopted** | +| **Player HP drift across three fights** | Script asserts melee **85/100** only; later archetype hits optional in Notes — do not require exact final HP in AC. | **adopted** | +| **Overlap with NEO-97 manual QA** | NEO-98 supersedes as capstone; NEO-97 stays component regression (elite incoming-threat row). | **adopted** | +| **NEO-97 merge dependency** | **NEO-97 merged** to `main` (PR #136) — capstone can proceed. | **adopted** |