NEO-111: add capstone manual QA script and README loop section.
Single-session Godot checklist with flexible defeat order, inventory verification, and Godot-restart idempotency; cross-link from NEO-110.pull/150/head
parent
385cabe883
commit
e900ba992b
|
|
@ -225,6 +225,29 @@ Full capstone checklist: [`docs/manual-qa/NEO-86.md`](../docs/manual-qa/NEO-86.m
|
|||
|
||||
Full checklist: [`docs/manual-qa/NEO-110.md`](../docs/manual-qa/NEO-110.md).
|
||||
|
||||
## End-to-end encounter clear loop (NEO-111)
|
||||
|
||||
Epic 5 Slice 3 capstone — defeat all three prototype NPCs, receive loot + quest token **once**, verify inventory **in Godot** without Bruno.
|
||||
|
||||
**Flow:** fresh server restart → boot encounter HUD **0/3** → defeat ×3 (any order) → progress **1/3 → 2/3 → completed** → loot label + inventory → Godot restart idempotency.
|
||||
|
||||
| Step | Input / trigger | HUD / server outcome |
|
||||
|------|-----------------|----------------------|
|
||||
| Boot | Godot **F5** + fresh server | **`EncounterProgressLabel`** **`not started (0/3)`**; **`Loot: —`**; empty bag |
|
||||
| Engage | **Tab** + **1** on first NPC | Encounter activates on first damaging hit (NEO-106); progress **`1/3`** after defeat |
|
||||
| Second defeat | Lock + cast second NPC | **`2/3`**; loot still **`—`** |
|
||||
| Third defeat | Lock + cast third NPC | **`completed (3/3)`**; **`EncounterCompleteLabel`** lists grants; **`InventoryLabel`** auto-refreshes |
|
||||
| Idempotency | Stop Godot + **F5** (server still running) | Encounter still **`completed`**; inventory counts unchanged |
|
||||
| Re-cast defeated | **Tab** + **1** on defeated NPC | **`ability_cast_denied: target_defeated`**; no duplicate loot or gig XP |
|
||||
|
||||
**Cross-links:** [NEO-106](../docs/plans/NEO-106-implementation-plan.md) combat wiring · [NEO-108](../docs/plans/NEO-108-implementation-plan.md) encounter-progress GET · [NEO-110](../docs/manual-qa/NEO-110.md) HUD components · [NEO-98](../docs/manual-qa/NEO-98.md) NPC combat · [NEO-86](../docs/manual-qa/NEO-86.md) gig XP per defeat.
|
||||
|
||||
**Scripts:** `encounter_progress_client.gd`, `inventory_client.gd`, `ability_cast_client.gd`, `combat_targets_client.gd` — wired from `main.gd`.
|
||||
|
||||
**Preconditions:** **Server restart** before capstone run resets NPC HP, encounter progress, inventory, and gig XP.
|
||||
|
||||
Full capstone checklist: [`docs/manual-qa/NEO-111.md`](../docs/manual-qa/NEO-111.md).
|
||||
|
||||
## Inventory snapshot HUD (NEO-72)
|
||||
|
||||
- **`GET /game/players/{id}/inventory`** — server-authoritative bag (**24** slots) + equipment stub (**1** slot); see [server README — Player inventory](../server/README.md#player-inventory-neo-54-store-neo-55-http).
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ Player casts **`prototype_pulse`** (**25** damage, ~**3 s** cooldown).
|
|||
|
||||
- Defeat order may differ from table — server tracks order-independent subset; count is **`defeatedTargetIds.size()`**.
|
||||
- Capstone baseline prefers **server restart** over mid-session fixture POST.
|
||||
- Full three-NPC loop + idempotency capstone: [NEO-111](NEO-111.md) (when landed).
|
||||
- Full three-NPC loop + idempotency capstone: [NEO-111 manual QA](NEO-111.md).
|
||||
- Component combat regression: [NEO-98 manual QA](NEO-98.md).
|
||||
|
||||
## Acceptance
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
# NEO-111 — Manual QA checklist
|
||||
|
||||
| Field | Value |
|
||||
|-------|-------|
|
||||
| Key | NEO-111 |
|
||||
| Title | E5M3-12: Playable encounter clear capstone (Godot) |
|
||||
| Linear | https://linear.app/neon-sprawl/issue/NEO-111/e5m3-12-playable-encounter-clear-capstone-godot |
|
||||
| Plan | `docs/plans/NEO-111-implementation-plan.md` |
|
||||
| Branch | `NEO-111-playable-encounter-clear-capstone` |
|
||||
|
||||
## Preconditions
|
||||
|
||||
- **Fresh dev player:** stop any running server, then start a new instance so in-memory **`dev-local-1`** NPC HP, encounter progress, inventory, and gig XP reset.
|
||||
- **No Bruno/curl** for this checklist — defeat chain uses Godot **Tab** + **1** only.
|
||||
- NEO-110 encounter HUD, NEO-106 combat wiring, and NEO-108 encounter-progress GET landed on `main`.
|
||||
- **`Economy HUD`** toggle **on** for inventory verification.
|
||||
|
||||
## Archetype reference (defeat order flexible)
|
||||
|
||||
| Archetype | Instance id | Marker | Pulses to defeat |
|
||||
|-----------|-------------|--------|------------------|
|
||||
| Melee | `prototype_npc_melee` | orange west **`(-3, -3)`** | 4 |
|
||||
| Ranged | `prototype_npc_ranged` | purple SE **`(3, 3)`** | 4 |
|
||||
| Elite | `prototype_npc_elite` | gold origin **`(0, 0)`** | 8 |
|
||||
|
||||
Player casts **`prototype_pulse`** (**25** damage, ~**3 s** cooldown). Defeat all three in **any order** — server tracks an order-independent subset.
|
||||
|
||||
## Expected encounter HUD progression
|
||||
|
||||
| After | `EncounterProgressLabel` | `EncounterCompleteLabel` |
|
||||
|-------|--------------------------|---------------------------|
|
||||
| Boot (no engagement) | `prototype_combat_pocket: not started (0/3)` | `Loot: —` |
|
||||
| 1st NPC defeated | `prototype_combat_pocket: 1/3` | `Loot: —` |
|
||||
| 2nd NPC defeated | `prototype_combat_pocket: 2/3` | `Loot: —` |
|
||||
| 3rd NPC defeated | `prototype_combat_pocket: completed (3/3)` | `scrap_metal_bulk ×10` and `contract_handoff_token ×1` (display names when item defs loaded) |
|
||||
| After Godot restart (idempotency) | still **`completed (3/3)`** | unchanged grant lines |
|
||||
|
||||
## Expected inventory after completion
|
||||
|
||||
On a fresh server restart the bag starts empty. After the third defeat, **`InventoryLabel`** should show at least:
|
||||
|
||||
| Item id | Quantity |
|
||||
|---------|----------|
|
||||
| `scrap_metal_bulk` | **10** |
|
||||
| `contract_handoff_token` | **1** |
|
||||
|
||||
Record these quantities before idempotency steps.
|
||||
|
||||
## Expected gig XP after three defeats
|
||||
|
||||
**`GigXpLabel`** should show **`breach: L1 · 75 xp`** (NEO-44: **25** gig XP per defeat × **3**). No further gig XP increase during idempotency steps.
|
||||
|
||||
## Checklist
|
||||
|
||||
### Boot + encounter clear
|
||||
|
||||
1. Start server: `cd server/NeonSprawl.Server && dotnet run`.
|
||||
2. Run Godot main scene (**F5**). Confirm boot lines: **`Encounter: … not started (0/3)`** and **`Loot: —`** on **`EncounterProgressLabel`** / **`EncounterCompleteLabel`** (combat HUD block, below **`PlayerCombatHpLabel`**).
|
||||
3. Defeat **first** prototype NPC (any archetype): walk to marker, **Tab** lock, press **1** until **`Cast: … — defeated!`**. Verify **`EncounterProgressLabel`** shows **`1/3`** (may lag one GET behind cast — wait ~1 s).
|
||||
4. Defeat **second** prototype NPC (either remaining archetype): lock, cast until defeated. Verify **`2/3`**.
|
||||
5. Defeat **third** prototype NPC: lock, cast until defeated (**8** pulses for Elite). Verify **`completed (3/3)`** and **`EncounterCompleteLabel`** lists **`scrap_metal_bulk ×10`** and **`contract_handoff_token ×1`** (or raw ids if defs still loading).
|
||||
6. Open **`Economy HUD`** body: **`InventoryLabel`** shows **`scrap_metal_bulk`** (**10**) and **`contract_handoff_token`** (**1**) without pressing **I** (auto-refresh on completion GET).
|
||||
7. Verify **`GigXpLabel`** shows **`breach: L1 · 75 xp`**.
|
||||
|
||||
### Idempotency
|
||||
|
||||
8. **Record** inventory quantities for **`scrap_metal_bulk`** and **`contract_handoff_token`** from step 6.
|
||||
9. **Godot restart (re-login):** stop Godot run (**Shift+F5** or stop button); **F5** again **without** stopping the server. After boot hydrate, verify **`EncounterProgressLabel`** still **`completed (3/3)`** and **`EncounterCompleteLabel`** grant lines unchanged.
|
||||
10. Verify **`InventoryLabel`** quantities **match step 8** — no duplicate loot.
|
||||
11. Lock a **defeated** NPC (**Tab** at its marker); press **1**. Verify **`CastFeedbackLabel`** shows **`ability_cast_denied: target_defeated`**; encounter HUD and inventory **unchanged** from steps 9–10.
|
||||
12. Verify **`GigXpLabel`** still **`breach: L1 · 75 xp`** — no extra gig XP from idempotency casts.
|
||||
|
||||
### Regression
|
||||
|
||||
13. **`CastFeedbackLabel`** still shows readable deny reasons (NEO-28 / NEO-98).
|
||||
14. Component encounter HUD detail: [NEO-110 manual QA](NEO-110.md). Component NPC combat: [NEO-98 manual QA](NEO-98.md).
|
||||
|
||||
## Notes
|
||||
|
||||
- Defeat order may differ from the archetype table — only **0/3 → 3/3** progression is asserted.
|
||||
- Capstone baseline prefers **server restart** over mid-session fixture POST.
|
||||
- **`POST /game/__dev/combat-targets-fixture`** is **out of scope** for idempotency — it clears encounter progress/completion alongside NPC HP reset ([server README — dev combat-target fixture](../../server/README.md#dev-combat-target-fixture-brunomanual-qa)).
|
||||
- Slice 3 Epic AC: completing **`prototype_combat_pocket`** grants expected items + quest token **once** ([epic_05 Slice 3](../../decomposition/epics/epic_05_pve_combat.md#epic-5-slice-3)).
|
||||
|
||||
## Acceptance
|
||||
|
||||
- [ ] Steps 1–14 completable in one session without Bruno/curl.
|
||||
- [ ] Progress label shows **1/3**, **2/3**, then **completed (3/3)** after three defeats (any order).
|
||||
- [ ] Loot label and inventory show **`scrap_metal_bulk` ×10** + **`contract_handoff_token` ×1**; quantities unchanged after Godot restart + defeated-NPC casts.
|
||||
- [ ] Epic 5 Slice 3 AC satisfied in Godot.
|
||||
Loading…
Reference in New Issue