diff --git a/docs/history/0.2.0.md b/docs/history/0.2.0.md index ce61c9d8..6cd1fb7b 100644 --- a/docs/history/0.2.0.md +++ b/docs/history/0.2.0.md @@ -25,7 +25,11 @@ settled (泥岩's 闭锁; 忍冬, 深靛, 阿) → §25.11; release packaging an with no Spine model) → §25.12; round 18 — 拟态物质 at the copy cap (GitHub #207), 华法琳's 7 / 14 (GitHub #175, PR #192), a merged elite 拉普兰德 as a new one (GitHub #169), the leader pool per player alive (PR #209), the flying lift and two model quirks (PR #211) → §25.13; the community reports of 2026-10-06 (the 孤岛风云 prisoners drawn freed, 忍冬's trigger, a -bounty burned to death by the 活性源石, 枯朽之种 paying a bounty) → §25.14. +bounty burned to death by the 活性源石, 枯朽之种 paying a bounty) → §25.14; the second batch of community reports of +2026-10-06, stream CB5 (match flow and UI: a module's 特性追加 line after the class trait, the new shop slot filled at the +upgrade, an eliminated player following a player through every round, the boss field and its leader in a watcher's boss +prep, the pair together in the boss prep with the official green frames; PRs #189 / #191 reused, not merged; the +battle-history and hotkey requests left to the owner) → §25.19. Decisions of the owner: 2026-10-04 — the server stays on plain `node:http` + `ws`, no web framework (§25.1); 2026-10-05 — the 补位 plan (§25.3); the 自选编队 rules, the collab operators out of the pool, ISW-A refused (§25.4); @@ -1062,3 +1066,118 @@ fixed (W5AA's commits name every golden scenario moved); two were already fixed bounty 使徒 whose seeds leaked sent every seed into 联防 carrying the card — 15 of 16 re-entries paid it again — which is the report; on this tree only the 使徒's own leak carries it. - Golden: unchanged. Pinned: `test/sim/feedback5-community-pins.test.js`. + +### 25.19 Community reports of 2026-10-06, stream CB5: match flow and UI — `ui/loadoutModel.js traitLines`, `player/economy.js _openLevelSlots`, `match/watch.js _followScout`, `match/views.js prepFieldMeta / bossMateView`, `render/app.js syncMates`, `ui/gameLogic/camera.js teamFrameIds` + +CB5 took the items about the match flow and the screens (16.2, 19, 51, 55, 56 of the list; 22 and 48 are features the +owner has not decided — what each would take is at the end). Each was reproduced first (a script, or the real server in +headless Chrome for the screens), checked against the official data, PRTS and the official tutorial pages, then fixed in +one commit with its tests; two open community PRs were reused without merging them (§25.19.6). + +#### 25.19.1 「干员调配界面很多干员的某个模组只有额外特性没有基础特性,不清楚是文本错误还是实际效果也有错」 (item 16.2): text only — the module's added line now follows the class trait — `ui/loadoutModel.js traitLines / fullTraitText`, `ui/detailPanel.js traitText`, `screens/loadout.js ModuleInfo`, `screens/diy.js ModuleRow` + +- **Seen**: 114 of the 164 modules the 干员调配 screen offers (128 of all 184 elite module records) showed under 特性 only + the module's extra line — 隐现's MAR-X read 「攻击空中单位时攻击力提升至110%」 without 「优先攻击空中单位」; 局内数值, the + in-match detail card and the 自选 module row did the same. +- **Official**: a module's trait candidate either rewrites the class trait (`overrideDescripton`) or adds a line after it + (`additionalDescription`); PRTS flags the latter 「特性追加」 on every such module (e.g. 伊芙利特 BLA-X / BLA-Δ, 玛恩纳 + LIB-X, 莫斯提马 SPC-X / SPC-Y). +- **Cause**: the data keeps both lines (`traitOverride.desc` = the class trait or its rewrite, `moduleDesc` = the added + line); the screens showed `moduleDesc` instead of `desc` (since 0.1.2: the review of GitHub #64 in §22 picked the + module line over a cloned record's class trait). The battle was right: for every added-line module the unit keeps the class + trait — the same trait text, targeting, attack shape and trait blackboard as 不装备 (圣约送葬人 REA-Y also rewrites it). +- **Now**: `traitLines` / `fullTraitText`: the class trait (or the rewrite), then the added line; the module card shows + them as 特性 and 特性追加 (en "Added Trait"). +- Golden: unchanged (no sim change). Tests: `test/ui/feedback5-module-trait.test.js` (6; the text cases fail on the + parent, the data and sim pins pass there), `test/ui/loadout-stats.test.js` updated; SP_E2E `loadout.e2e` 9 / 9. + Docs: docs/DATA.md (`trait`, `traitOverride`). + +#### 25.19.2 「升级商店获得新的商店位时用新卡补上,而不是空着」 (item 19): the upgrade opens the new slot with a new card — `player/economy.js _openLevelSlots`, `audit.js` + +- **Seen**: a level-up from 1 to 2 (险境: 3 → 4 operator slots) or 3 to 4 (4 → 5; 标准 5 → 6) showed no new card until the + next refresh or round start (the shop kept its rolled layout; META listed it as an assumption). +- **Official**: the tutorial's 休整期 page (local guide art `autochess_home_4`): 「升级:消耗资金升级调度中心。升级后将出现更多 + 的商品栏位、可调度干员以及新装备」; PRTS 帮助 「消耗资金可以为调度中心升级,从而增加刷新栏位」. +- **Now**: `levelUp` → `_openLevelSlots`: the new level's extra slots are appended to the operator slots at once (the + item slot stays after them), each drawn at the new level; the cards shown stay in place, a bought card stays sold. + `audit.js` checks the count and the kept cards (`matchrun --check`: no violation). +- [ASSUMED]: the new card follows the freeze toggle, as a manual refresh's cards do. +- Golden: matches — all 18 scenarios (every bot levels its shop and now sees, and draws the shop RNG for, the new card at + once); the battle families unchanged. Tests: `test/match/feedback5-shop-levelslots.test.js` (3, all fail on the + parent). Docs: docs/META.md §3 / §7, docs/PLAYING.md. + +#### 25.19.3 「死亡观战时每一回合结束都会被转回自己家」 (item 56): an eliminated player follows a player through every phase reset — `match/watch.js watchPref / _watchTargetOf / _followScout`, `battle/observe.js followedScout` + +- **Seen** (real server, headless Chrome): every round start cleared an eliminated player's watch — in 回合开始 / 机变 / + 休整期 it saw its own empty board, each battle started on the first field; a spectator seat asked for the first player + itself. +- **Official**: research 09 §3.1 — after elimination the client keeps observing (self_dead_dialog KEEP_WATCH, the + server's DeadAutoObDn { obIndex, state, preparation }, FindFirstAvailObTarget). +- **Now**: `Match.watchPref` = the player of the viewer's last manual `g.watch` (a prep scout, a single-player field, or + — new, optional — `g.watch { playerId }` naming the row tapped on a shared 联防 / boss pair field); `_watchTargetOf` = that + player while still in, else the first player still in (seat order, AI seats included). The round start pushes its prep + board (`_followScout`, kept through 机变 and 休整期), both combat modes and the boss fields start on its field, a resync or + a spectator joining in prep gets the board, a followed player who quits hands over at once. The screen adopts the pushed + board like a 前往查看 tap (`followedScout`; PR #189's stale-field fix) and keeps it through the prep phases; 返回自己 asks + the server for nothing (the viewer has no board). +- Golden: unchanged. Tests: `test/match/feedback5-watch-follow.test.js` (9; 8 fail on the parent's server), + `test/match/spectator.test.js` updated. Docs: design/network.md, docs/PLAYING.md. + +#### 25.19.4 「死亡后观战视角看不到场上的关底boss」 (item 55): a watcher of a boss round's prep sees the boss field and its leader — `match/views.js prepFieldMeta`, `screens/game.js` + +- **Seen** (headless Chrome, the guest eliminated at the boss round): in the Final Assault fight the watched boss field + showed the leader (enemy_9013_acstmk at 10,3); in the boss round's prep the guest saw its own empty normal board (camera + 'prep', no leader) and a scout of a teammate was the normal board too — while the players prepare on their half of the + boss field with the leader standing there (§23.18, community report #12). +- **Now**: in a boss round's prep the scout is built on the boss field — `kind: 'boss'`, `BOSS_RECT`, the scouted player's + pieces through `bossFieldPlacement` (rows − 7, the right half mirrored with RIGHT ↔ LEFT), `side`, the leader's spawn in + `nextEnemies` — and framed by the boss-field prep camera of that side, which shows the leader. With §25.19.3 the + eliminated player gets it at the round start; the same run after the fix: field 'boss', camera bossPrep, leader shown. +- Golden: unchanged. Tests: `test/match/feedback5-boss-prep-scout.test.js` (2, fail on the parent); SP_E2E + `test/ui/feedback5-boss-pair.e2e.test.js` (item 55 case). Docs: design/network.md, design/client.md §15. + +#### 25.19.5 「还原原版最终boss战准备阶段:像战斗中那样把会成一组的两个玩家放在一起…同组两个玩家屏幕左边的头像也像原版那样用绿框框起来」 (item 51): the pair together in the boss prep, the official green frames — `match/views.js bossMateView`, `match/messaging.js markPrivate`, `render/app.js syncMates`, `ui/teamPanel.js`, `ui/gameLogic/camera.js teamFrameIds` + +- **Seen**: the own half was already the official one — the right-hand player on the right half with the + right_boss_*_camera_param camera, its layout mirrored col c → 20 − c with RIGHT ↔ LEFT, so its operators face the leader + as before (research 09 §1.2, §15) — but the partner's half stood empty and nothing framed the pair. +- **Official**: every client knows every board (ChangePositionDn { boardStatus }, research 09); the team list frames the + co-op group (the owner's recall; the client's ui/battle `bg_team_border`, a white 100×100 frame with its glow, and the + autochess green of `icon_self`, #4ed8af). +- **Now**: in a boss round's prep `m.private.bossMate { playerId, side, units }` carries the partner's board on its half, + placed as the battle will (bossFieldPlacement); a partner's change marks the player's m.private too (`markPrivate`), so + it follows live; the own prep view draws those units read-only ('m:' views, never picked or dragged) and lights the + whole boss field; a scout of either player shows both halves (`mate`). The team panel frames the pair's two avatars + (`teamFrameIds`: the players still in by seat, two by two, as `prepCamera`; the boss field in the fight) from the round + start through the fight, with the official sprite tinted green (a plain ring without the local art); a lone player, an + eliminated player and a spectator seat get none; 联防 is not framed (not asked). +- [ASSUMED]: the partner's bench is not shown (its board only); the frame's exact official geometry (one frame per avatar). +- Golden: unchanged. Tests: `test/match/feedback5-boss-pair-prep.test.js` (4, fail on the parent), SP_E2E + `test/ui/feedback5-boss-pair.e2e.test.js` (both halves, the mirrored right half, the frames in prep and fight). + Docs: design/client.md §10 / §15, design/network.md, docs/PLAYING.md. + +#### 25.19.6 Overlap with the open community PRs #189 and #191 (not merged; their authors' fixes were pending) + +- PR #189 (watch preference, @2321Robin) — §25.19.3 builds the same chain (a manual watch is the preference; round start, + both combat modes, the boss fields and the resync follow it; the stale-field fix of the adopted scout), on the 0.2.0 + method containers. Differences: the fallback is the first player still in with AI seats included (a lone human with AI + teammates had nobody to follow — the report's case), and a shared field records the `playerId` the row tap sends (the + review's point 2) instead of nothing. +- PR #191 (same-field frames, issue #190) — §25.19.5 frames the pair as the owner asked: green, the official sprite, both + avatars (self included), the boss rounds only; the pairing is read from m.public as the prep camera already does, so no + `bossPairing` field; #191's 联防 frames and the phase banner naming the partner are not built. If the owner still wants + them, they can go on top of this. + +#### 25.19.7 Not built — what the two feature requests would take (the owner has not decided) + +- **22 战绩 / 分队胜率**: the result is already complete (`m.result`: per-player stats, lineup, band, bonds, titles, rounds + passed, victory — `server/match/results.js`). With no accounts the simplest is per browser: append a compact record at + `m.result` to localStorage (capped, e.g. the last 200; only matches of ≥ 2 rounds, as asked), a 战绩 screen in the lobby + (list, win rate per strategy / core bond / mode and difficulty, 导出 / 导入 like the loadout), tests and i18n — no + server change. Server-side history needs persistence and an identity the remake does not have. Decisions: browser-only + or not; what 「分队」 groups by (strategy, core bond, lineup); the sample cap. +- **48 自定义快捷键**: the keys are fixed in `ui/gameLogic/shortcuts.js shortcutFor` (R 刷新, F 冻结, D 升级, Q 撤退, X 出售, + Space 准备 / 暂停, Esc). It would take a 快捷键 section in 设置 (capture a key per action, conflicts refused, 恢复默认), + a sanitised map in the settings (`sanitizeSettings`), `shortcutFor` reading it, every `` hint and tooltip reading it + too, i18n and tests. Decision: whether to allow it at all (the official PC client's keys are fixed as far as the data + shows: `pc_key_holder` hints).