Commit Graph
13 Commits
Author SHA1 Message Date
sganggs 47079456be feedback5: merge CB2 — community reports (healers / summons): 刺玫's S2 heals the most injured ally again (the counter's heal alone goes to her protégé), 琳琅诗怀雅 heals herself and her 破财消灾 cost restarts at 5 DP with every deployment, 赫默's S2 casts at full SP so the drone takes the field at once, the countdown summons (医疗探机, 诅咒娃娃, 海嗣 and four 自选 ones) take no damage, are never healed and show the life left on their bar, stacked ground areas stay readable; §25.16 after CB5's §25.19 (renumbered with the later merges); golden: vs feedback5 CB2's own rules — roster-001/002/003/005/008/016/018/027/035/037/045/046/049, bond-deputShip-low/high, bond-suntShip-high, bond-victoriaShip-low/high, bond-visiShip-low/high, boss-boss_1/3/5/7-pair, hidden-boss_9-pair, unite-1, matches solo-FUNNY-2, coop2-HARD-4, coop3-ABYSS-5, coop4-ABYSS-7, coop2-NORMAL-8-serverrun, coop2-ABYSS-10-boosted, coop2-NORMAL-14-standins; vs CB2 exactly CB5's 18 bot matches
Merge fixes (the three tests the trial merge failed):
- test/content/summon_loadout_conflicts.test.js (赫默's drone lifetime per module variant): it asserted "no cast yet"
  after the drone's redeploy time and then cast S2 by hand — with nobody hurt the old DEFAULT rule never cast. S2 now
  casts by itself the tick its SP is full (22 s), which is the official rule (client skill skchr_silent_2: no
  `_trigger`, `_allowNoTarget` 1, `_checkHasTargetBeforeDoCast` 0; CB2 64f8bf9), so the test waits for that cast and
  checks both drones' lifetimes from it. Failed on fb5-cb2 itself (the stream did not run the file).
- test/sim/feedback1f-downed-tile.test.js (F5 rule 3): its "killed" case killed 浊心斯卡蒂's 海嗣 with 1e9 true damage;
  the 海嗣 is a countdown summon now — 无敌 + 禁疗, the official state (PRTS 海嗣 备注 「持有禁疗、无敌」) — so it only
  expires. The killed case takes 缪尔赛思's 流形 (a placed board summon that is attacked and killed and also comes back on
  its tile 25 s later); both cases now also check the summon's return. Failed on fb5-cb2 itself.
- test/golden-standins.test.js (the 补位 match fields at least 3 different stand-ins): already failing on feedback5
  37558f0 — CB5's 调度中心 upgrade card changed the human seat's shop in coop2-NORMAL-14-standins, which then fielded
  only 2 of its 7 not-owned chess (忍冬 → Sharp, 安洁莉娜 → Raidian). tools/golden.mjs MATCH_NOT_OWNED adds 缄默德克萨斯
  and 铃兰 (chess its AI fields now): 4 stand-ins (Sharp from round 4, Misery from 7, 预备干员-辅助 from 9, Raidian in 12);
  the test is unchanged, test/golden/README.md says 9 chess. This moves coop2-NORMAL-14-standins only.
- docs/history/0.2.0.md: the §25 intro's two stream lines joined into one sentence (the merge had cut it).

Golden moves outside CB2's commit list are CB2's rules on the paths CB5 gave the bots: coop2-HARD-4 fields 琳琅诗怀雅
from round 6, coop2-NORMAL-8-serverrun 刺玫 from round 7, coop2-ABYSS-10-boosted 刺玫 from round 2,
coop2-NORMAL-14-standins 刺玫 from round 3 and 琳琅诗怀雅 in rounds 6-7 (instrumented); coop2-NORMAL-3 and coop4-FUNNY-6
(in CB2's list) still field 刺玫 and her S2 heals now reach other allies (36 / 205 heals), but no kill, leak, LP or
end stat changes, so their digests stay.

Gate: non-browser suites 4949 / 4949, npm run golden ok (283 scenarios), test/golden.test.js 9 / 9, lint 0 errors,
check:imports ok, typecheck ok.
2026-10-07 03:10:22 +08:00
sganggs 37558f0d5e feedback5: merge CB5 — community reports (match / UI): module 特性追加 shown after the base trait (text only), a shop upgrade fills its new slot at once, spectators follow the player they picked through every phase (g.watch carries the playerId — PR #189's idea), the boss shows in boss-round prep scouting, the final-boss prep shows the pair together with green avatar frames (PR #191's idea, official colour); §25.19 after the hotkeys' §25.15; golden: the 18 bot matches (the upgrade's new card), battles unchanged 2026-10-07 02:41:19 +08:00
sganggs 97105cbfad feedback5 CB2: DESIGN §25.16 — the community reports of 2026-10-06 of stream CB2 (healers, summons, timers): 12, 18, 33, 34, 26, 14 fixed; 11, 13, 31, 32 answered with the evidence; design/network.md notes the countdown summons' snapshot hp 2026-10-07 02:36:06 +08:00
sganggs b168a78b7e feedback5 CB5: DESIGN §25.19 — the community reports of 2026-10-06 of stream CB5 (match flow and UI): 16.2 (text only), 19, 56, 55, 51 fixed; the overlap with PRs #189 / #191; what the battle-history (22) and hotkey (48) requests would take
docs/history/0.2.0.md: the intro list names §25.19; the subsection in §25's style (seen / official / cause /
now / [ASSUMED] / golden / tests / docs per item).
2026-10-07 02:31:06 +08:00
sganggs f1df0d359d feedback5 WAC: docs for the rebindable shortcuts — PLAYING §11 (the shortcut list and how to change it), README 操作 (Q / X added, the settings named), DESIGN §10 (design/client.md), §25.15, I18N's stale hotkey-line example
Golden unchanged (docs only).
2026-10-07 01:56:25 +08:00
sganggs 714af994fc feedback5: merge W5AA — community reports of 2026-10-06: the 孤岛风云 prisoners leave the gate confined (grey) and change model as their prefabs do, the 4th attack hits freed; a bounty enemy that dies with no operator behind it pays in 联防 too (the helper whose half it fell on); 忍冬's trigger and 枯朽之种's bounty were already fixed (pinned by tests); DESIGN §25.14 after round 18's §25.13; data/enemies.json regenerated offline on the merged code (round 18's model quirks + the prisoners' clips); golden: vs feedback5 exactly W5AA's moves (26 battles, solo-ABYSS-2, coop2-NORMAL-3, coop3-ABYSS-5, solo-HARD-9-boosted), vs W5AA exactly round 18's boss-pool moves 2026-10-06 22:35:10 +08:00
sganggs 2767adccc0 feedback5 WAA: DESIGN §25.14 — the four community reports of 2026-10-06 (two fixed, 忍冬's trigger and 枯朽之种's bounty already answered and pinned)
- docs/history/0.2.0.md §25.14 (also scratchpad draft 0.2.0.aa.md) in the §25 style: the prisoners' models and
  timing (§25.14.1), 忍冬 — her default S3 has cast on its 2-2 running range since §25.5's ACTIVE_RANGE (0.1.4 waited
  for her 1-tile range; §25.14.2), a bounty burned to death (§25.14.3), 枯朽萃聚使徒's seeds — fixed by 0.1.3 §23.25,
  every leaked seed paid the card again in 联防 on v0.1.2 (§25.14.4); the §25 intro list, the owner's decisions, the
  §25.10 table, what stays [ASSUMED] (the 联防 payee) and the open polish (enemy prefabs whose default clips differ
  from the manifest: 猎狗pro, 大鲍勃, 碎骨, “斩胄之剑” / “破胄之锤”).
- test/sim/feedback5-community-pins.test.js pins the two reports this tree already answers (they pass on the parent):
  忍冬 S3 casts with an enemy two tiles ahead and not three, S2 on its 3-12, S1 on her attack; a bounty 使徒's seeds
  carry no bounty and pay nothing, the body pays once, and in 联防 only its own leak carries the card.
- Golden unchanged.
2026-10-06 22:05:47 +08:00
sganggs 66ae86b969 feedback5 WY: flying units hover 1.3 tiles (the client's 0.35 ÷ the standard prefab scale 0.27); the 帝国炮火先兆者 pair is drawn 1.263× taller and 木制瑞印 mirrored, as their official prefabs (from PR #211 by @xcdoge; the owner's decision of 2026-10-06)
Ported by hand from PR #211 by @xcdoge:
- render/units.js: FLY_HOVER 0.32 → 1.3, flat (the official fly offset is one model-independent Vector3(0, 0.35, 0) in
  the client's character space, whose unit is the standard battle-prefab scale 0.27; an official screenshot measures
  1.2–1.4 tiles); enemyModelScaleY multiplies the skeleton's Y scale and the head (bar) height, also in the impostor
  path; a mirrorX model flips on top of the direction flip. The body, its HP bar, damage numbers, projectile hits and
  skill rings ride `hover`, the shadow stays on the ground; one camera drives the units over the 2D and the 3D board.
- tools/build-data.mjs MODEL_STRETCH_Y / MIRRORED_PREFABS → enemies.json modelScaleY / mirrorX; data/enemies.json
  regenerated offline here (the PR's one-line blob was not taken) — JSON compare: only enemy_1112_emppnt /
  enemy_1112_emppnt_2 modelScaleY 1.263 and enemy_1196_msfyin mirrorX true.
- tools/local-extract/enemy_model_offsets.py (optional, host-side prefab reader) and
  docs/research/12-flying-visuals-official.md (without the claim that the owner said 「都要」 on 2026-10-05 — the owner's
  decision of 2026-10-06 is cited; where the quirk enemies appear corrected against 0.2.0's data: 帝国炮火先兆者 is a FLY
  special enemy of the mode, 帝国炮火中枢先兆者 comes with the bounty 战术特训·飞行III, 木制瑞印 is in no wave). No
  screenshot or extracted art committed.

Tests (from PR #211): test/render/unitview.test.js (FLY_HOVER ≈ 0.35 / 0.27; the same lift for every flyer; a flying
view lifts by FLY_HOVER — added here: its body and HP bar ride the lift, its shadow stays on the ground),
test/render/playtest6-enemies.test.js (the data keys; the 1.263 aspect and bar height; the mirrored model's x sign);
both fail without the renderer change; the 425 render unit tests pass. Docs: DATA §9, ASSETS, design client.md,
research 00 / 12, DESIGN §25.13.5 and the §25.10 table.
Golden unchanged (drawing only; the sim reads neither field).
2026-10-06 21:41:49 +08:00
sganggs 4e58481706 feedback5 WY: the Final Assault / Hidden Core leader pool is bloodPoint × the players alive when the fight starts (solo × 1), replacing 「保持固定血量」; 胄's drone share passes 限伤 (from PR #209 by @qingjingshenghuo; the owner's decision of 2026-10-06)
Ported by hand from PR #209 by @qingjingshenghuo (its one-line data/config.json was not taken):
- server/match/gamedata.js bossPoolShareOf (used by GameData.bossPoolShare and by finalAssault.bossPoolHp for a plain
  game-data object): solo × `solo` (1); co-op with `perPlayer` true × `coop` (1) × the players alive at the boss
  round's start (bots and AI 托管 seats count, eliminated / departed seats do not; at most aliveFull 4; a count left
  out = a full team). The fixed pool stays restorable through config: bossHpScale perPlayer false + solo 0.25 (and its
  optional aliveScaling).
- tools/build-data.mjs: the global bossHpScale carries the rule (perPlayer true, solo 1); the modes' entries keep only
  bloodPointKey / unaffectedByEnemyScale. data/config.json regenerated offline — JSON compare: only bossHpScale (global
  and the 9 mode entries) changed.
- The problem #209 documented: a 胄 drone death is 2 % of the pool and 限伤 cancels a hit of ceil ≥ 300000, so the
  hidden 胄 终极 pool at 3 / 4 players (21.6M / 28.8M) would cancel every drone (432000 / 576000). The drone link is
  a share of the pool, no hit: Battle.loseHp takes noHitLimit and the link passes the limit [ASSUMED: the official
  client checks every damage modifier and PRTS calls it 真实伤害, but which max HP it reads is undocumented]; a part's
  传递 and every hit stay under the limit.

Golden (regenerated; why: the pool size):
- fields: boss-boss_1..7-pair/-solo and hidden-boss_8..10-pair/-solo (all 20 boss / hidden scenarios) — a pair
  field's pool × 2 (two players), a solo template's × 4 (solo × 1, was × 0.25); boss-boss_1-pair, boss-boss_1-solo,
  boss-boss_3-pair, boss-boss_3-solo, boss-boss_5-solo, boss-boss_7-pair and hidden-boss_9-solo now end at the
  200 s cap instead of clearing; the two 联防 scenarios are unchanged.
- matches: solo-FUNNY-2, solo-NORMAL-1, solo-HARD-1, solo-HARD-2 now lose the Final Assault (solo leaders have 4× the
  HP: team LP 0 with 93088–176395 of the pool left); solo-FUNNY-1, solo-NORMAL-2, solo-HARD-9-boosted (its Hidden Core
  too), coop2-NORMAL-3, coop4-FUNNY-6, coop2-ABYSS-10-boosted, coop2-NORMAL-70-diy still win with more leader damage
  (pool × players alive; solo-FUNNY-1 / solo-HARD-9-boosted end with 6 / 1 team LP less). Unchanged:
  coop2-NORMAL-8-serverrun and coop2-NORMAL-14-standins (one player left at R14: × 1 as before) and the matches that
  end before R14; roster / bonds / standins / diy unchanged.

Tests: test/match/boss-hp-scaling.test.js (from PR #209, adapted — every leader and difficulty × 1–4 players and solo;
R14 / R15 leave out two departed players; AI 托管 and bots count, an eliminated player does not; config restores the
fixed pool, the opposite of the PR's test; the plain-object fallback agrees; only the leader's HP scales);
test/content/enemies_bosses.test.js (hidden 胄 终极 at 3 / 4 players: the drone share lands, a hit of the same size is
cancelled — fails without the change). Updated on purpose: finalAssault, balance, bosshp, connection, docs-consistency
(the §20.9 record points to §25.13.4; the data carries perPlayer true), sim/playtest6_limits (the drone share lands
past the line), match/playtest6-bosspool (the 5 % knob halved to keep the 2-player pool's size: that test is about the
pool's arithmetic). Docs: PLAYING §7, DATA, META, BALANCE, SIM, design engine.md / network.md, the §20.9 / §20.10
records, research 00 / 01 / 08, the code comments, DESIGN §25.13.4 and the §25.10 table.
2026-10-06 21:41:49 +08:00
sganggs 661f1c074e feedback5 WY: a newly merged elite 拉普兰德 is a new 拉普兰德 — its first manual refresh this round adds +8 even when its copies already fired (GitHub #169; the owner's decision of 2026-10-06)
garrison_123 「<刷新时>若为本回合首次主动刷新…此干员在整备区时也有效」 counts per piece (§21.1). No source says whether a
merge resets the count; since 0.1.1 _mergeChess carried the copies' highest per-piece round count onto the elite
([ASSUMED], conservative), so two white copies that had fired this round made an elite that did not fire again. The
owner decided on 2026-10-06 that a newly merged elite counts as a new 拉普兰德.

server/match/player/acquire.js _mergeChess no longer carries the per-piece round counters (拉普兰德's refresh count,
garrison:SERVER_GAIN_BOND_LAYER_BY_REFRESH_CNT:refreshes, is the only one): the elite starts at 0 like any new piece;
an in-place promotion keeps its count. test/match/feedback1-meta.test.js: the test that locked the old inherit is
updated on purpose (the elite adds +8 on its next refresh, once), and the case "two white copies refreshed this round,
merge, refresh → +8" is new; both fail without the change. Docs: META (counter API, edge cases), PLAYING, the comments
(PlayerState, pieces, effectsMeta, garrisons/meta), DESIGN §25.13.3 and the §25.10 table.
Golden unchanged (no corpus match merges 拉普兰德 after a refresh in the same round).
2026-10-06 21:41:49 +08:00
sganggs 269d7b0bcf feedback5 WY: 华法琳's granted trait stops at the data's 7 / 14 layers per battle, not 12 / 24 (GitHub #175; from PR #192 by @kukiC; the owner's decision of 2026-10-06)
PRTS 卫戍协议:盟约 下半, 3月27日更新#2调整 (revision 439189): 「[Ⅳ阶]华法琳:赋予的特质的叠层上限从 初始12/精锐24
降低至 初始7/精锐14」 — a nerf; the current 参战干员 record says 至多7层 / 14层 and the client blackboard is 7 / 14.
Research 02 Addendum 1 had read the line backwards, so the remake overrode garrison_95's cap to 12 / 24.

Ported from PR #192 by @kukiC: GRANTED_CAP_OVERRIDE is removed from server/sim/content/garrisons/battle.js and from
the client-result layer bound (server/match/fields.js layerAllowanceOf); a granted trait keeps its data cap like a
native one. Tests from the PR: garrisons_battle (updated on purpose: the 7th cast reaches 7 / 14, the 8th adds
nothing), feedback1-gaps (the bound with 华法琳 + 古米), playtest3 (both cards show 7 / 14); the first two fail without
the fix. Docs: research 00 / 01 / 02 corrected (02-bonds.json's note; data/bonds.json regenerated offline — only
miraShip.spec.layerGain changed), history 0.1.1's pointer, DESIGN §25.13.2 and the §25.10 table.
Golden unchanged (no corpus battle casts 8 times in front of 华法琳).
2026-10-06 21:03:56 +08:00
sganggs 463352d9bc feedback5 WY: 拟态物质 with 2 copies owned and none left in the pool gives nothing instead of a random same-bond operator (GitHub #207)
The item text 「若已拥有至少2名该初始干员,则再获得1名该初始干员;否则随机获得1名同盟约初始干员」: the 否则 is the
case of fewer than 2 owned. builtinMeta's use_equip_reward_char_chess returned only when grantChess(base) gave a piece,
so an elite 溯光星源 plus 2 normal copies (all 5 Ⅵ阶 copies) fell through to the same-bond roll (白面鸮 in the report's
seed). Now with 2 owned it asks for the 3rd and stops; the item is still consumed. The bots' carrier choice
(itemTarget) skips 2 copies whose pool is out.

Tests: test/content/items.test.js (the report with the normal and golden item; 2 copies with the pool drained; 2 copies
with copies left still merge), test/match/bot-smarter.test.js (no carrier on a pair whose pool is out); both fail
without the fix. Docs: META built-ins and bot items, research 04 / 06, DESIGN §25.13.1.
Golden unchanged.
2026-10-06 20:55:49 +08:00
sganggs da1f5830ca feedback5 WW: split DESIGN.md into docs/design/ (the current rules) and docs/history/ (the per-release revisions), section numbers kept — a pure move: every ## N. block (heading, text, the --- after it) moves verbatim, each part file only gains a title line and a pointer to the index; docs/DESIGN.md keeps its header and becomes the index (a § → file table). design/overview.md §0 §1 §2 §11 §12, geometry-time.md §3 §4, engine.md §5 §7, match.md §6 §16, network.md §8 §14, client.md §9 §10 §13 §15; history/v2.2-playtest3.md §17, v2.3-playtest4.md §18, v2.4-playtest5.md §19, v2.5-playtest6.md §20, 0.1.1.md §21, 0.1.2.md §22, 0.1.3.md §23, 0.1.4.md §24, 0.2.0.md §25. Round trip: the index header plus the blocks in § order reproduce the pre-split DESIGN.md byte for byte (813 785 bytes, sha256 fe81884c…). Tests: test/helpers/designDocs.js designText() (the split script's splitBlocks / designText) reassembles the text in § order; docs-consistency and feedback1-gaps read it instead of docs/DESIGN.md (every pin unchanged); docs-paths guards the split (each § exactly once in docs/design/ or docs/history/, the index row of every file names its sections, every "DESIGN §N(.M)" cited in the repository is a heading — 779 in 327 files today); package.test keeps docs/design/ and docs/history/ out of the zips; golden unchanged 2026-10-06 19:08:44 +08:00