docs(battle-node): README reflects real drafted deck + cosmetics

Player-side fictions (dummy deck, classId=1) removed; the section now
documents which fields are real (deck, leader, cosmetics) vs still hardcoded
(rank, battlePoint, cardMaster, fieldId, seed) with a pointer to the spec's
§Deferred plumbing for each. "Where to extend" table loses the two done
items and gains a row for wiring future modes via IMatchContextBuilder.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
gamer147
2026-06-01 13:00:22 -04:00
parent e3cc745a61
commit 6077844ee8

View File

@@ -83,21 +83,26 @@ There's also a JSON parsing pitfall worth knowing about (and that broke the mull
## v1 scripted opponent — what the client sees
Hardcoded in `ScriptedLifecycle`:
The player half of `Matched` / `BattleStart` reads from a `MatchContext` assembled in
`SVSim.EmulatedEntrypoint/Services/MatchContextBuilder` from the viewer's TK2 run + equipped
cosmetics + config — so the mulligan renders the real drafted deck, drafted class/leader,
and equipped emblem/degree. The opponent half stays scripted in `ScriptedProfiles`:
- **Your deck** is 30 copies of `cardId = 100011010` (a neutral card stable across card-master versions). Your actual TK2 draft is ignored.
- **Your leader** is `classId="1"`, `charaId="1"` regardless of class you drafted.
- **Opponent** is a fixed silhouette: `classId="8"`, KOR sleeve/emblem/degree, viewer id `999999999`.
- **Opponent** is a fixed silhouette: `classId="8"`, JPN sleeve/emblem/degree, viewer id `999999999`.
- **Battle seed** is `17548138L` in both info blocks (the seed is *shared* per battle per the spec).
- **Mulligan** does real card replacement: any idx in your `idxList` is swapped for the next unused deck idx (`1..3` dealt, so `4..30` are pool).
- **Opponent's turn** never actually does anything — we push a single `TurnStart{spin:100}` after your `TurnEnd` so the UI transitions to the opponent-turn display, then sit.
A few player-side fields are still hardcoded pending a follow-up slice — `Rank`, `BattlePoint`,
`cardMasterName`, `fieldId`, and the per-battle RNG seed. See the spec's §Deferred plumbing
table at `docs/superpowers/specs/2026-06-01-battle-node-real-drafted-deck-design.md` for
what each needs.
## Where to extend
| You want to | Touch |
|---|---|
| Use the real drafted deck | `ScriptedLifecycle.BuildMatched` (`selfDeck`) + the `IMatchingBridge` to plumb the viewer's TK2 run state through |
| Show the real drafted class | `ScriptedLifecycle.BuildBattleStart` (`selfInfo.classId/charaId`) — read from the same source |
| Wire a new mode's `do_matching` (rank, free, open-room, …) | Add one `BuildFor<Mode>Async(viewerId, …)` method to `IMatchContextBuilder` reading that mode's deck source; the mode's controller calls `IMatchingBridge.RegisterPendingBattle(vid, ctx)`. No changes to `SVSim.BattleNode`. |
| Add a real AI opponent | Replace the static dispatch in `BattleSession.ComputeResponses` (`TurnEnd → opponent TurnStart` case) with one that drives a decision engine. The `OutboundSequencer` already assigns `playSeq` for whatever you push. |
| Implement recovery | `IBattleSessionStore` already keeps the pending registry. Add a per-battle archive (the `OutboundSequencer.Archive` already retains every assigned-playSeq push) and bind it to the HTTP `/battle/get_recovery_params` endpoint. |
| Validate `battleCode` | Port `NetworkConsistency.GetConsistency` from the client decompilation. Hook into `BattleSession.HandleMsgEventAsync` on `TurnEnd` / `Judge`. |