Commit Graph
359 Commits
Author SHA1 Message Date
sganggs 0ae2fac2b1 feedback7: merge fb7-unbalance — the official 失衡 (UNBALANCE) after a push / pull (the idea of PR #392 by @xcdoge, re-implemented from PRTS): no walking, attacking or skills while it lasts; pushes by the 推力-位移 time table, pulls by the force window (0.5 / 1 s), static bodies 0.1 s pushed / the window pulled; 弧光锋卫 bleeds 400 / 0.066 s while unbalanced; the client slide uses the same time
- The owner asked to verify the official rule before deciding (research: PRTS 失衡位移机制 / 推与拉 / 游戏数据基础 / 特殊机制,
  the client's Rigidbody2D data); the PR's 0.6387·√tiles formula and fear exemption were not taken.
- Grok review: MERGE AFTER FIXES — two HIGH (static pulls, 弧光锋卫's bleed), skills during the hold, husk 重生, exact
  frames — fixed on the branch (1db84d79).
- Golden union: bond-miraShip-low differs from HEAD (fewer enemy attacks: 169 → 166 events, same kills) though the
  branch alone left it — HEAD's ×1.1 练度 path now displaces an enemy there. Broad node --test 5681 (5679 pass, 0 fail,
  2 skipped); lint 0 errors.
2026-10-08 22:47:33 +08:00
sganggs 1db84d799d feedback7 R22-UNBAL: 失衡 review fixes — a pulled 静态刚体 is held for the pull's window, 弧光锋卫 bleeds 400 every 0.066 s while the state lasts, no enemy skill / blink / scripted move during it, a route APPEAR or a 逐火 重生 ends it, every push row holds its exact frames; golden: 32 move, 8 in outcomes (below)
Branch review of fb7-unbalance (MERGE AFTER FIXES):
1. A 静态刚体 pulled got the 0.1 s floor: _staticForce now knows push from pull — a push's force is instant (推与拉), so
   0.1 s; a pull's lasts its window (pullUnbalance: 1 s, 0.5 s below −1) — PRTS 特殊机制 静态刚体 「在失去施力后立刻」 out,
   「0.1 秒保底」. pull() checks the puller's own block before the static case.
2. 弧光锋卫 (PRTS 天赋 「处于失衡状态时,每0.066s受到400点无来源真实持续伤害」, data unbalanced_bleed): a tick bleed of 400 every
   0.066 s while unbalancedNow holds; the per-tile one-shot from the position jump ([ASSUMED], UNBALANCE_SPEED) is gone.
   A 受力等级 0 push (0.8 s) → 12 hits = 4800 (was 2037), a 急停 pull with no movement (1 s) → 15 = 6000 (was 0), a
   wall-shortened slide keeps the 0.8 s row → 4800.
3. 失衡免疫 「失衡期间无法自主移动、发动攻击、使用技能」: enemies/helpers.js unbalancedNow; canCast(e, sil, battle) refuses while it
   runs (content skills; the boss parts' calls pass the battle), blinkForward returns null, 枯朽之种's dive / blast and the
   铳 / 碎铳之簧 charges wait, 乌顶巨角卢鲁's clash waits for its end. A route APPEAR relocation clears it (a forced state
   switch, 失衡位移机制). Left running on purpose (docs/SIM.md): 水遁忍者's damage check (异常效果 「仍然能正常造成伤害」), passive
   auras and terrain / periodic effects, death / damage-taken triggers, skill cooldowns, 弧光锋卫's bleed itself.
4. husk() (逐火 余烬 重生) clears the state like reborn().
5. The 35/30 row held 36 frames (t0 + 35/30 overshoots in floats): every check compares with 1e-9; the frames are asserted.

Tests: test/sim/unbalance.test.js +6 (exact frames 6 / 12 / 24 / 27 / 32 / 35 with the walk on the next frame; static pull
1 s / 0.5 s, push 0.1 s; 弧光锋卫 4800 / 6000 / 4800; canCast / blinkForward refused, 枯朽之种 held then diving; the elk's clash
after the state; APPEAR and a 逐火 重生 clear it — all six fail on the parent); enemies_bosses (失衡 kit test) and
feedback1d-solvent (BUFF damage) updated to the state bleed. test/sim + test/content + test/render pass. Docs: SIM.md
(push / pull row), PLAYING.md, design/engine.md (helpers, enemy AI), constants / displacement comments.

Golden against the previous commit — outcome moves: roster-010 (歌蕾蒂娅 pulls 妖怪 drones, now held 1 s: killed 44→45,
leaks 58→57), roster-040 (static pulls of 妖怪: killed 28→25, leaks 37→40, deaths 29→30), roster-043 / 044 (山: deaths 14→16 /
14→13), hidden-boss_9-pair (锏: boss HP 3636991→3586929), coop4-ABYSS-7 (ai_2 LP +1 from round 5), diy-115 (黑键: leaks
70→75), diy-116 (黑键: killed 2→3, leaks 121→120) — the static pulls (probe) and the 1e-9 end (a frame shorter where the float
sum overshot: the 35/30 row, some pull windows); other moves (damage / snapshots only): roster-008 / 017 / 039, 9 bonds,
boss-boss_4-pair / boss_6-pair / hidden-boss_10-pair, coop2-NORMAL-14-standins / coop2-NORMAL-3 / solo-ABYSS-1 /
solo-HARD-1 / solo-HARD-9-boosted / solo-NORMAL-1, diy-053 / 085 / 102.
2026-10-08 22:42:26 +08:00
sganggs 0ced21d321 feedback7: merge fb7-loadout — per-operator 潜能 (1–6) and 练度 (未精英化 / 精英1 / 精英2 / 精英2 Lv.60) set in 干员调配, defaults 潜能 6 and 精英2 Lv.60 (the owner's decision of 2026-10-08); PR #301 ported as one aligned list; #398 the skill frame, #400 REA-Y's heal text
- Conflicts (the branch started at ae22335c): the four i18n packs (union of keys), game.js DetailPanel props (ops + the
  voices' voice=true), detailPanel.js resolveDetail (cultOpts + the voices' tap), match/views.js (both helpers),
  docs/PLAYING.md and design/network.md merged line by line against the base. test/match/bosshp.test.js's ATK formula
  now includes the unit's 练度 multiplier (cultMul).
- Grok review: MERGE AFTER FIXES — the note and the module card at the set potential fixed on the branch.
- Golden: every owned operator ×1.1 ATK / DEF / max HP by default — roster 49, bonds 46, fields 22, matches 18, diy 134
  (stand-in battles and prototype picks unchanged). Broad node --test 5666 (0 fail after the bosshp formula; 2 skipped);
  lint 0 errors; typecheck; i18n strict clean (1152 msgids).
2026-10-08 22:35:33 +08:00
sganggs 2de2feee3c feedback7: merge fb7-dobermann — 教鞭 is the official three-choice (PR #353 by @Sukvii, the owner's decision), the Final Assault / Hidden Core pay a 战术特训 card's perfect coins (guarded by b.progress leaksBy), the bots put zero-range heavy guards on the road first (PR #339 by @IceCodeNew, placement only)
- Conflicts (the branch started at ae22335c): spec.js / protocol.js b.progress (resolved from fb7-ui-backlog + leaksBy),
  gameLogic.js / game.js exports (device tips + normalizePersonalChoice), docs/PLAYING.md / design/network.md lines
  merged against the base, META.md (画卷 note + 教鞭), test/docs-consistency.test.js pin (both fields).
- Grok review: MERGE AFTER FIXES — the HIGH (a forged boss result paid the cards) fixed on the branch (66a228c6), the
  META wording (1ab12763).
- Golden: matches 10 (the 杜宾 bot picks and the guard placement); union: coop3-ABYSS-5 differs from HEAD only in ai_2's
  dmgDealt (1238011 → 1186269), no outcome change — HEAD's side had moved it, the new placement applies on that path.
- Broad node --test 5623 (5621 pass, 0 fail, 2 skipped); lint 0 errors; typecheck; i18n strict clean.
2026-10-08 22:11:49 +08:00
sganggs cee3784321 feedback7: merge fb7-late follow-ups — 画卷's copied items always arrive unequipped (PRTS 「获得的装备为未装备状态」; hand, then temp, destroyed with the toast when both are full), 度算浪波 breaks an HP-ratio tie by the latest deployment (PRTS)
- Golden union OK (roster-033 / roster-034 again); broad node --test 5602 (5600 pass, 0 fail, 2 skipped); lint 0 errors.
2026-10-08 22:04:15 +08:00
sganggs 03688c8297 feedback7 R22-LATE: 引星棘刺 S1 度算浪波 breaks an HP-ratio tie by the latest deployment; golden: roster-033, roster-034 move
PRTS 引星棘刺 技能1 度算浪波 备注: 「※优先选择生命比例最低>最晚部署的我方单位(不含装置职业单位)」. The kit took the ally
with the lowest HP ratio but broke a tie by more blocking, then the nearer one, then the unit id. A tie now goes to
the latest deployment (the highest deploySeq: a redeployed operator counts from its new deployment), the id last.
「不含装置职业单位」 was already met: alliesInGrid never returns a device.

Golden: roster-033 (a normal 引星棘刺 with S1) and roster-034 (an elite one) move — at the start every ally is at full
HP, so the first units now land on the latest deployed ally instead of the nearest one (033: killed 64 → 47, leaks
103 → 120; 034: 5_14_b damage taken 14691 → 11676 …).
Tests: test/content/kits_alt_t5.test.js +1 (two allies at 50 %: the later deployment, though farther, gets the unit;
a lower ratio still wins) — fails on the parent; all 引星棘刺 tests pass (9).
2026-10-08 21:57:48 +08:00
sganggs cdf2bd5c88 feedback7 R22-UNBAL: a pushed / pulled enemy is held in the official 失衡 (UNBALANCE) state — no walking, no normal attack — for the push's 位移时间 of its 受力等级 or the pull's force window; a 静态刚体 hit by a force gets the 0.1 s floor; the client's slide takes the same game time (idea from PR #392 by @xcdoge, re-implemented from the sources); golden: 69 scenarios move, 35 with kills / leaks / deaths / boss HP (below)
Seen: the sim moved a displaced enemy at once and it walked / swung again on the next tick; players compared with the
official game (PR #392: 「被推/拉完的敌人会先站住一小会儿再走」). Research (scratchpad report r3): PRTS 失衡位移机制 — a force > 0
puts an enemy in the UNBALANCE state machine with a 0.1 s 失衡硬直 floor, ending when its speed is ≤ 0.1 m/s, on 浮空 or a
forced state change; 异常效果图鉴/失衡免疫 「失衡期间无法自主移动、发动攻击、使用技能」; 异常效果 — not an abnormal status (水遁忍者's
check still runs); 游戏数据基础 推力-位移近似对应表 位移时间 (whole frames at 30 fps); 推与拉 拉力 「作用时间默认为 1 s;若本次受力
等级 < −1,作用时间改为 0.5 s」, 急停 keeps the state to the window's end; 特殊机制 静态刚体 (0.1 s 保底); 术语释义 浮空.

Now: constants.js PUSH_UNBALANCE {−2: 0.2, −1: 0.4, 0: 0.8, 1: 0.9, 2: 32/30, 3: 35/30}, PULL_UNBALANCE 1 /
PULL_UNBALANCE_WEAK 0.5, UNBALANCE_MIN 0.1. battle/displacement.js: push() holds for its level's row (the −2 correction
included), kept when the 特效 column or a wall shortens the slide [ASSUMED for the wall], the 0.1 s floor when a wall
stops it at the first step [ASSUMED]; pull() holds for its window whatever the travel (≤ −3: none; an enemy the puller
blocks: still no pull [ASSUMED, unchanged]); a 静态刚体 (data staticBody, not 失衡免疫 noDisplace) hit by force level
≥ −2 gets 0.1 s and no movement (_staticForce); _unbalance sets enemy.unbalanceUntil (a longer running one kept) and ends
the attack clip's stand. ai.js updateEnemy: no walking (恐惧 / 诱导 too — PR #392's fear exemption is not taken), no new
normal attack, a swing short of its frame cut, 浮空 clears it; a 重生 clears it (archetypes.js reborn). Not a stun: no
status, no immunity, SP and the attack cooldown run. No global skill lock: enemy abilities keep ticking ([ASSUMED] scope).
The move stays instant (the unbalanced() talents keyed off the jump unchanged). The displace fx carries `dur` (game s);
render/units.js slideTo divides it by ctx.animRate (2× default: a 0.8 s push slides 0.4 real s); DISPLACE_SLIDE·√D is
only the fallback for an fx without it. Not taken from #392: UNBALANCE_TRAVEL 0.6387·√tiles / the client's 0.3194 (derived
from the page's μ = 0.5 单位假设, one frame high on every push row, the wrong shape for pulls) and the fear exemption.

Tests: test/sim/unbalance.test.js (8: the push rows and walking after them; no attack in the hold, a feared enemy held;
the −2 correction's 0.2 s; 特效 / wall-shortened rows and the first-step floor; pull windows incl. the 急停 and ≤ −3; 静态刚体
0.1 s without movement, 失衡免疫 never; 浮空 clears; the fx `dur` — the file fails on the parent); test/render/unitview.test.js
(+1: the slide at 2× for a push and a pull, the fallback — fails on the parent); feedback1b-displacement B5 (the drone is
now held 0.1 s per force, never moved). test/sim + test/content + test/render: 3433 pass. Docs: SIM.md (push / pull,
displace, assumptions), PLAYING.md 推开 / 拉拽, research 13 §0 / §5.

Golden — every moved battle has pushes / pulls (probe of the callers) and its enemies are now held; outcome moves:
roster-002 (野鬃: killed 29→33, leaks 15→11), roster-003 (野鬃: deaths 3→7), roster-007 (薄绿: killed 110→118, leaks 53→47),
roster-008 (薄绿: 45→47 / 42→40), roster-010 (歌蕾蒂娅: killed 45→44, leaks 57→58), roster-011 (莫斯提马: 78→79 / 4→3),
roster-031 (钩索师 pulls, tier4: killed 64→72, leaks 12→4, deaths 6→5), roster-041 (钩索师: deaths 5→4), roster-043 (山:
deaths 15→14), roster-044 (山: killed 107→103, leaks 12→16, deaths 15→14); bond-deputShip-low (薄绿: 18→21 killed, leaks
3→0, deaths 1→0), bond-kazimierzShip-high (野鬃: deaths 3→2); boss-boss_3-pair (锏: p2 deaths 3→2), boss-boss_4-pair
(莫斯提马 / 歌蕾蒂娅: killed 11→12, boss HP 7442429→7375628, p2 leaks 2→1, deaths 19→18), boss-boss_6-pair (boss HP
6932482→6865243, p2 deaths 19→17), hidden-boss_8-pair (boss HP 12585770→12585798), hidden-boss_9-pair (锏: boss HP
3630612→3636991); standin-05 / 08 / 10 (预备干员-特种 pulls: killed 5→8 / 42→44 / 28→29, leaks down by 3 / 2 / 1);
diy-101 (傀影: killed 22→21, leaks 92→93), diy-114 / 115 / 116 (黑键: 106→99 & 83→90 / 154→156 & 78→70 / 3→2 & 120→121),
diy-137 (预备干员-特种: 68→79 / 79→68); matches through those battles — coop2-HARD-4, coop2-NORMAL-14-standins,
coop2-NORMAL-3, coop2-NORMAL-70-diy, coop3-ABYSS-5, coop4-ABYSS-7, solo-ABYSS-2 (LP 2→4 at round 10), solo-HARD-2
(ai_0 now survives round 13: eliminated 13 → alive), solo-HARD-9-boosted (LP 399→398), solo-NORMAL-1. Other moves (damage,
heals, snapshots only): roster-009/012/017/019/032/039/040/042/046, 13 bonds, boss-boss_2-pair, hidden-boss_10-pair,
standin-03, diy-053/084/085/102/103/108/109, coop2-ABYSS-10-boosted, solo-ABYSS-1.
2026-10-08 21:54:06 +08:00
sganggs 2492966c4f feedback7: merge fb7-late — #389 / PR #390 画卷 keeps the items to copy across a merge, #385 / PR #387 spectator bond details count the hand like the own popup, #394 / PR #395 Enter during facing selection follows the focus, #281 the attack range drawn on a tapped operator, #388 引星棘刺 S1 DEF stacks, PR #386 谢拉格 寒风 blows bottom-up (owner)
- Golden union OK (roster-033 / roster-034 moved on both sides: #298 and #388); broad node --test 5598 (5596 pass, 0 fail,
  2 skipped); lint 0 errors.
2026-10-08 21:54:03 +08:00
sganggs ac4231846f feedback7 R22-LATE: 画卷 never puts the copied items on the copy — they are gained unequipped into the hand / temp like any item; golden: unchanged
PRTS 卫戍协议:盟约 PRTS盟约记录, 法术编纂集, 画卷 备注: 「选择策略<夕>时可获得<br>使用后销毁,获得的装备为未装备状态」.
Without a promotion the 画卷 handler still equipped every copied item that did not merge (an advanced item, a
变形同构体) onto the copy in the hand (the promotion case was fixed for #389). Now each copied item is only gained
(ctx.grantItem → acquireItem): the hand, overflow temp, and with both full it is destroyed with the usual toast
「整备区已满,获得的装备已销毁」, as for any gained item. A copied normal item that completes a pair still merges at once
(the golden in the hand), and the copy itself still follows the chess gain rules (a full hand and temp refuse the
scroll: HAND_FULL, the scroll kept). Full-hand check: a full hand with 3 free temp slots holds the copy and both
copied advanced items; with 2 free slots the copy and one item fit and the other is destroyed with the toast (before,
both rode on the copy).

Docs: META.md (Arts list), research/04-items.md (画卷 copy). The content test that pinned the old behaviour
(test/content/items.test.js: 变形同构体 "the copy wears it too") now expects it in the hand.
Tests: test/match/scroll-copy-merge.test.js +3 (no promotion, normal and elite targets with advanced items; the full
hand at 3 / 2 free temp slots) — all 3 fail on the parent; every test mentioning 画卷: 177 pass. Golden unchanged.
2026-10-08 21:53:51 +08:00
sganggs 1a67ecc35f feedback7 R22-LATE: 引星棘刺 S1 度算浪波 — two alchemy units on one ally add their DEF (+60 +60), as their heals already did; golden: roster-033, roster-034 move
GitHub #388 (claim 1). Every S1 alchemy unit applied its DEF buff under one shared key ('thorn2:bastion'), so a second
unit over the same ally replaced the first one's buff (two units: DEF +60, not +120; a normal and an elite: +75, not
+135) while both units' heals landed. PRTS 引星棘刺 技能1 备注: 「效果均可叠加」. Each alchemy unit now has its own
DEF buff key (assigned at its first tick), so the buffs add (aggregateMods sums defFlat) and each lapses with its own
unit. S3's 不叠加 debuff is untouched.

Golden: roster-033 (a normal 引星棘刺 with S1, pass 1) and roster-034 (an elite one, pass 1) move — one operator's
consecutive S1 units overlap for a few seconds (6 / 7 s + 3 s 心相 against a 7 / 6 SP cost) and now add their DEF on
an ally both cover (033: killed 46 → 64, leaks 121 → 103; 034: damage taken by 5_13_b 41498 → 14903 …).
Tests: test/content/kits_alt_t5.test.js (+1: normal + elite on one ally = +135, the longer unit's +75 stays alone,
nothing afterwards; fails on the parent with +75).
2026-10-08 21:45:09 +08:00
sganggs 3969e4b012 feedback7: merge fb7-owner-sim (48a2d37e) — #316: 突袭 members jump to 隐匿 ground enemies too and one in range counts as 范围内有敌人 (the owner's decision of 2026-10-08)
- Golden union: coop2-ABYSS-10-boosted and coop2-NORMAL-14-standins differ from HEAD though the commit alone left them —
  HEAD's side had moved both, and on the new paths 隐匿 enemies meet active 突袭 members (14-standins: raidShip on;
  round 10 kills 26 → 27, leaks 3 → 2, team LP 39 → 40; ABYSS-10: a few 阿戈尔 layers, team LP 793 → 795); no outcome
  change.
- Broad node --test 5575 (5574 pass, 0 fail, 1 skipped); lint 0 errors.
2026-10-08 21:31:47 +08:00
sganggs 52f56319ac feedback7: merge fb7-gh-sim — PR #348 (take-the-highest chains), PR #293 (REA-Y in the engine), #329 ports (异客 13 tiles, 歌蕾蒂娅 net radius 1, 搅拌机 latest first, 大帝 uncapped), PR #365 (骨刺 forms + PRTS targeting), #298 (instant non-attack skills recast at most once per attack interval, attacks untouched), #364 (先兆者 shell 3×3), #220 (速射手 air first), 余 skips noStack bonds (owner)
- Conflict: docs/PLAYING.md 技能自动释放 bullet — both insertions kept (the 铁钳号 rule from fb7-owner-sim, the #298
  pacing sentence).
- Grok review: MERGE AFTER FIXES — the HIGH #298 finding (the cast replaced the due attack) fixed on the branch
  (db29acf9: per-skill nextCastAt; golden of #298 alone shrank from 84 scenarios to 2).
- Golden union: 4 matches differ from HEAD though the branch alone left them (coop2-NORMAL-3, coop4-ABYSS-7,
  coop2-NORMAL-8-serverrun, solo-HARD-9-boosted): HEAD's side had moved all four (#333's shop RNG …) and on those new
  bot paths the merged rules apply — the diffs are in-battle layer gains / damage (卡西米尔 50 → 45, 精准 80 → 76,
  叙拉古 176 → 168, kills ±2, solo-HARD-9 LP 397 → 399), no outcome change.
- Broad node --test 5571 (5570 pass, 0 fail, 1 skipped); lint 0 errors; typecheck.
2026-10-08 21:27:04 +08:00
sganggs 48a2d37e9b feedback7 R22-OSIM: 突袭 members jump to 隐匿 ground enemies too, and one in range counts for 「范围内没有敌人」 (the owner's decision, GitHub #316); golden: 5 match scenarios move
GitHub #316 (warpgenius): "Raid operator doesn't deploy to invisible enemy units, it does in official". The owner's
decision of 2026-10-08 from their official play: a 突袭 member considers 隐匿 (unrevealed) ground enemies both as landing
targets and for 「若范围内没有敌人」. Until now raidTargets and the poll used canTargetEnemy / enemiesInKeys, which leave
隐匿 out (the bond text only says 敌人 / 地面敌人).

content/bonds/addon/battle.js: raidGroundEnemy accepts what canTargetEnemy (ground) accepts, plus a 隐匿 ground enemy that
only its 隐匿 keeps out; asleep, untargetable and flying enemies stay excluded (skipEnemy too). raidStealthInRange: a 隐匿
ground enemy on the member's range stops the jump, so a ready member next to one does not hop every poll. The landing
rules are unchanged (the target in range from the landing tile; a melee member's blocking tile first).

Golden: solo-HARD-1, solo-ABYSS-1, coop2-NORMAL-3, coop4-ABYSS-7, coop2-NORMAL-70-diy — their 突袭 members (斯卡蒂, 瑕光,
宴, 伊内丝) now jump to 隐匿 enemies (潜伏者, 隐形弩手组长, …) or stay because one stands in their range.

Tests: test/sim/feedback7-raid-stealth.test.js (4; 2 fail on the parent: the jump to the only landing spot beside a 隐匿
enemy, and staying with one in range while a visible enemy waits elsewhere).
2026-10-08 21:21:44 +08:00
sganggs 31fee55c6c feedback7: merge fb7-fields — PR #337 boss-field portals teleport (route-end portals: hidden 3 s, out of [5,10], leak at the side's door), PR #347 碎铳之簧 chases the full 5 s, #370 耀骑士临光's redeploy reduction floored at 0, #375 the water-map patrol takes the official upper road
- Grok review: MERGE AFTER FIXES — the end-portal wait (0 s → 3 s, the data's modal crossing) fixed on the branch
  (1205336a). solo-NORMAL-1 still fails the Hidden Core (explained in the branch commits).
- Golden union OK; broad node --test 5517 (5516 pass, 0 fail, 1 skipped); lint 0 errors.
2026-10-08 21:20:37 +08:00
sganggs f5595a7a31 feedback7: merge fb7-owner-sim — community reports via the owner: 白铁's 铁钳号 opens only the skills that act on it (圣约送葬人 spends and stacks), 伊内丝 S3 after a 突袭 jump, 引星棘刺 alchemy units as HP regen (不屈者 / 禁疗), 不可对空 effects spare flying allies (炎佑), 望's 跟子 at battle start, 香槟炸弹 unhealable / no HP loss (owner decision) and not set off by unrevealed 隐匿 or sleeping enemies
- Grok review: MERGE AFTER FIXES — the HIGH finding (skills opened on the device but spending nothing) fixed on the branch
  (69d791f9: skills.js allyTargetsOk, per-kit allyTargets flags).
- Golden union OK; broad node --test 5500 (5499 pass, 0 fail, 1 skipped); lint 0 errors.
2026-10-08 21:14:27 +08:00
Xinglan233 19c7b26850 feedback7 R22-LATE: a 画卷 copy that completes a three-copy merge copies the target's equipment again; golden: unchanged
GitHub #389 / PR #390 by @Xinglan233 (this commit is substantially the PR: the snapshot and its test file, ported).
onArt read target.items after grantChess; a gain that completes a merge runs _mergeChess first, which consumes the
target and empties its items, so the copy loop ran on an empty list (two base 维式重锤 never became the +25% one).
The item ids are now recorded before the gain.

Added on top of the PR: after a promotion the copied items are never equipped onto the elite (an already-advanced
item used to go straight back onto it via equipDirect). The promotion unequips the copies (PRTS 帮助 自动卸除 on
合并) and the 画卷 note says the obtained equipment arrives unequipped, so they wait in the hand; a copied normal item
merges with the returned original as before. The non-promotion path is unchanged.

Tests: test/match/scroll-copy-merge.test.js (8; 4 fail on the parent, the advanced-item case also fails with the
PR's snapshot alone). Golden unchanged (no scenario casts 画卷 into a promotion).
2026-10-08 21:04:58 +08:00
sganggs 69d791f9c6 feedback7 R22-OSIM: a skill that 白铁's 铁钳号 opens now acts on it — 蕾缪安 S3 / 艾丽妮 S3 / 陈 S2 / 引星棘刺 S2 spend on it, skills that pick enemies only stay closed; golden: unchanged
Grok's review of the 铁钳号 change (HIGH): the device opened every non-heal skill, but kits that pick their victims
with enemiesInKeys only were spent on nothing — 蕾缪安 S3 went active with 0 locks, 艾丽妮 S3 and 陈 S2 struck nothing,
引星棘刺 S2 threw at the empty far tile. Audit: every skill of every chess (loadouts) and of the 自选 pool, placed with
only the device in range; of the 351 skills the device opened, 67 never touched it.

- skills.js `allyTargetsOk`: the device counts for a skill's start only if the skill acts on it — SkillSpec
  `allyTargets` (true / false) from the kit, else [ASSUMED] a skill acting through the unit's own attacks (timed and
  still attacking, or a cast that is the next attack) on a unit that attacks. An onStart-only cast or a no-attack timed
  skill picks enemies itself and waits for one (德克萨斯 S2 剑雨, 锡人 S1/S2, 铃兰 S3 … about 50 skills).
- Spend on the device (allyTargets: true; its kit cancels the hits, its 受击回复 counts): 蕾缪安 S3 locks it and spends
  her bullets (ammoUsed, so the per-bullet layers come) and shells it; 艾丽妮 S3 strikes it; 陈 S2 draws on it after
  every enemy; 引星棘刺 S2 throws onto it and its pulses hit it. queries.js allyTargetsInRadius for their areas.
- Explicitly closed ([ASSUMED], allyTargets: false): 普罗旺斯 S2 (never shoots above 80 % HP), 卡涅利安 S1 (charged: no
  attack), 山 S2 (blocked enemies), 余 S2 / S3, 迷迭香 S3 (blocked only), 荒芜拉普兰德 S1 / S2 (drone locks), 淬羽赫默 S1–S3
  and 遥 S1–S3 (heal attacks), 机械师 S3, 珊比 S2 / S3, 陈 S3 / 艾丽妮 S2 (their guards already refused).
- 雪猎's empty-magazine cast back to enemies only (its S2 does not act on the device).
Re-audit: 281 skills open on the device alone and all act on it (蕾缪安 S3 through her locks); none of those that
acted on it before stopped. Docs: SIM.md, design/engine.md, PLAYING.md.

Tests: test/content/feedback7-allytarget-kits.test.js (5; all fail on the parent).
2026-10-08 20:53:24 +08:00
sganggs cf98f4c3f8 feedback7: merge fb7-render — #382 赤刃明霄陈 S3 sword-qi drawn (sim chen3Wave fx), #381 enemy attack recovery held in interpolation, #380 push / pull slide (corpse stays where pushed; same-step kills finish the slide), #384 eye masks, 香槟炸弹 HP bar hidden, #246 an unwound attack plays its whole clip
- Conflicts with the merged fb7-hud (both added display-only snapshot lists): server/sim/battle/events.js, types/core.js,
  public/js/render/interp.js, docs/SIM.md, docs/design/network.md — union of ammo / wolves / neg and stand / standCut.
- Grok review: MERGE AFTER FIXES — the HIGH finding (same-step push kill) fixed on the branch (7a33bc7e).
- Golden: diy-073 / diy-074 (fx counts only; union OK); broad node --test 5442 (5441 pass, 0 fail, 1 skipped); lint 0
  errors; typecheck.
2026-10-08 20:51:11 +08:00
Sukvii 56a7b918a9 feedback7 dober: 教鞭 is the official personal choice of three 战术特训 cards again, not a random one (PR #353 by @Sukvii, the owner's decision of 2026-10-08); golden: coop2-NORMAL-8-serverrun and coop2-ABYSS-10-boosted move
Seen: the Art 教鞭 (杜宾's strategy) drew three 战术特训 cards and added a random one — a documented simplification (docs/META.md
§2.5: a personal choice would need its own phase, protocol message, timer and AI takeover). Official: act2autochess
choice_event hunter_band_1 is a PERSONAL_CHOOSE; PRTS 下半 记录 §法术 教鞭 "使用后销毁,于3个战术特训的悬赏任务中选择一项". The
owner decided on 2026-10-08 to follow it. Taken from PR #353 (code and tests by @Sukvii), ported to the split 0.2.2 modules.
Now: ctx.offerBountyChoice -> Match.offerBountyChoice keeps up to three different mode-eligible cards (15 of 20 in 标准 /
险境, 20 in 绝境 / 终极; one meta-rng shuffle) in PlayerState.personalChoice, m.private only (same cards after a
reconnect); g.choice { idx, choiceId } confirms it (Match.pickPersonalChoice: owner, id, round, index; a request without
a choiceId is still the public draft, a stale id never falls through to it). No new phase or timer: Ready is refused while
it is open, the prep's deadline picks at random before the temp pieces and Ready, a bot or a 托管 seat picks with the bounty
scorer (botPickCard, the bots' seeded rng; at the prep's start, after the cast, before Ready; the scheduler's fallback
picks at random if a step fails). The client reuses ChoiceOverlay (personal: no order, no turns, the prep's countdown) over
a locked prep, the Ready reasons, the mock harness; six UI strings in en / ja / ko / zh-TW. An eliminated player's offer
goes with it; invariants.js flags an offer outside its owner's own open prep.
Not taken from the PR: its §25.24 in the released docs/history/0.2.0.md (the 0.2.2 section is the integrator's), its edits
of the Ready toggle beyond the personal-choice case, its tail placement of the i18n keys.
Golden: coop2-NORMAL-8-serverrun (ai_0 杜宾 casts 教鞭 from R2 on and now scores the three cards: teamLp 39 -> 34, virtualMs
121400 -> 118400, rng shop 511 -> 483 / bots 18063 -> 18070 / meta 112 -> 103) and coop2-ABYSS-10-boosted (ai_1 杜宾: virtualMs
121650 -> 124650, shop 590 -> 589 / bots 22075 -> 22096 / meta 141 -> 154); both first differ in round 2, every other scenario
and family is unchanged; node tools/golden.mjs --twice is identical.
Tests: items.test.js (three distinct cards, the tapped one applied once, nothing before the confirm, a refused cast keeps
the Art / count / rng / uid, an eliminated player's offer), economy.test.js (Ready refused, the deadline picks before
endPrep, solo prep untimed), connection.test.js (two players' offers, reconnect, foreign / duplicate / old ids, an offline
player's pick at the deadline), bot.test.js (托管 takeover incl. the failing-step fallback), bot-smarter.test.js (the scorer's
pick, deterministic per seed, no rng draw when nothing is pending), followups.test.js (R14 / R15), draft.test.js,
unitStats.test.js (protocol), hardening.test.js (invariant), gameLogic / playtest3 / playtest4 (view model, Ready reason,
ChoiceView, actions), mock.e2e.test.js and playtest2.real.e2e.test.js (browser, SP_E2E=1).
2026-10-08 20:45:54 +08:00
sganggs ec0a2fc669 feedback7 R22-LOADOUT: the battle takes each operator's potential and 练度 from its spec entry; golden: unchanged
A PlayerBattleInput operator entry may carry `potential` (潜能 1–6) and `cultivate` (练度 0–3, the 自持有 bonus) —
the player's 干员调配 settings (the owner's decision of 2026-10-08). Specs without them field what 0.2.1 fielded, so
no golden scenario moves here; the match states both next.

- shared/loadoutRecord.js: a resolved loadout carries `potential`; loadoutRecord composes the record at it first
  (shared/potential.js atPotential), then the skill / module as before.
- server/sim/simdata.js: getChess(id, { …, potential }), getDiy(slot, pick, potential) (an owned 自选 pick's form at it;
  a prototype has none — `diyProto` on its record, shared/diy.js), getToken / getDiyToken compose the owner variant at
  the owner's potential (talents; a 自选 summon's deploy limit / holding / count); the per-battle loadout view keeps it
  per unit; DataSource.cultivateMul reads the effects.json CHAR_MAP record's char_attribute_mul.
- battle/players.js: `potential` composes the def (never a stand-in's); `cultivate` sets unit.cultMul — ×ATK / ×DEF /
  ×max HP in the unit's Πmul (units.js), a multiplier of its own, never summed with the 直接乘算 percentages (PRTS
  盟约记录 「…与自持有干员的属性加成独立」); a stand-in, a prototype 自选 pick and a summon take none [ASSUMED for summons].
- spec.js keeps both only when well-formed (never on a stand-in or a summon); content/index.js passes the potential to
  the loadout sync; the kits that read a summon variant raw (content/tokens.js ownVariant, summoner.js tokenStat,
  多萝西, 麦克尼斯特) compose it at the owner's potential; UnitInfo carries `potential` (below 6) / `cultivate`;
  unitStatsEntry counts the 练度 in the unit's own numbers (no green delta for it on the card).
- Docs: SIM.md §2 (Πmul), §9 (UnitInfo), §12.
- Tests: test/sim/potential-battle.test.js (new, 6): a unit at each potential (刺玫 413 / 17 / 70 s and 8 % at 潜能1;
  the elite on 不装备), the four 练度 tiers and their product with a +20 % ATK bonus, HP at deployment and the card's
  numbers, stand-in / prototype take neither and an owned 自选 pick both, Mon3tr / 望's 棋子 / “小自在” at the owner's
  potential, the spec round trip (kept, dropped, the JSON spec gives the same result digest), two players with the same
  chess at different settings on one field; test/sim/loadout.test.js expects the resolved loadout's new fields.
2026-10-08 20:38:08 +08:00
sganggs 38d4c3e4b5 feedback7 R22-GHSIM: 余 【文火慢炖】 adds no layers to a bond without layers (noStack: 绝技, 独行, 调和, 协防干员) — with one such bond the only one active, nothing is added (the owner's decision of 2026-10-08); golden: unchanged
The owner's decision (relayed 2026-10-08) overrides PRTS 下半/PRTS盟约记录 「部分盟约不会显示叠加层数,但是叠加层数的特质/策略/
装备等效果仍然对其生效」 for this strategy. bands/meta.js round_start_bond_check_gain_layer skips every bonds.json noStack bond;
the 「仅激活了1个盟约」 count stays the sentence's (every active bond), so: 独行 / 绝技 alone → nothing; 独行 + one layered
bond → the layered one +12 (count2), 独行 none. Repro: 独行 alone got 36, 绝技 alone 36, 独行 + 炎 got 12 each.

Only 余: 协防 (bonds/addon/meta.js deputShip, 「使所有已激活的盟约层数+N」) and 华法琳 【重点监护】
(prep_finish_char_bond_add_layer, a random operator's bonds, 无需激活) each pick their own bonds and call addLayers; they
share no helper with 余 beyond the generic Player.addLayers sink, which every layer gain uses — left unchanged, so both
still add to noStack bonds as PRTS says. Docs: PLAYING.md 层数. Golden: unchanged (no corpus 余 at round 8 with such a bond).
2026-10-08 20:34:51 +08:00
sganggs 7e09c63da8 feedback7 R22-LOADOUT: the data carries every potential (潜能 1–6), not only full potential; golden: unchanged
Potential becomes a per-player setting (the owner's decision of 2026-10-08: 「调配干员里自己设置吧,默认满潜满加成」;
official: 调度手册 「卫戍协议中干员潜能由自身已持有干员潜能决定」). 0.2.1 baked full potential into the data (§26.14).

- tools/build-data.mjs runs the chess / backups / tokens builders once per potential rank (ctx.potRank, 0–5) and keeps
  the full-potential build annotated with what each lower rank changes: `potDown` { rank: { dotted.path: value } } on
  chess records, backups.json forms and token variants (stats, statsBase; 望's 棋子 deployLimit / deckStack, 多萝西's
  共振装置 count), and chained talent entries (`potMin` / `potBelow`: the candidates by requiredPotentialRank, the
  fields a lower rank changes) in talents / talentsBase / modules[].talentChanges / variant talents. A self-check proves
  shared/potential.js atRank rebuilds every rank exactly; the unit-form parity runs at every rank.
- shared/potential.js (new): atPotential / atRank, talentAtRank, stripPotential, and the 练度 helpers used next
  (cultivateMul from the effects.json CHAR_MAP records aceffect_char_1…4, cultivationOf, cultivatedStats).
- composeTalents / composeUnitRecord return potential-resolved lists (no chains): a composed record is built at one
  potential (its form resolved first).
- JSON compare: the new chess / backups / tokens minus the annotations equal the old files byte for byte; every other
  data file identical; data/i18n/* rebuilt (the chained talent texts translated at the old rates: en 95.4 %, ja 95.2 %,
  ko 95.2 %, zh-TW 90 %). Data 5.21 → 5.51 MB.
- Docs: DATA.md §2.3 (new), §2, §7, §14, §16, §18; research/03-operators.md; kits/README.md.
- Tests: test/potential.test.js (new, 7): every chess and 自选 form at every potential = the raw keyframes plus the
  potential steps up to it, every talent = the last candidate with requiredPotentialRank ≤ the rank, 刺玫 at each
  potential, summons at the owner's potential (Mon3tr 3 s / 1200, 望's 棋子 6 / 7, “小自在” 15), the 练度 table =
  cultivateEffectList; data.test.js compares the composed talents without annotations.
2026-10-08 20:29:06 +08:00
sganggs 895653fc10 feedback7 R22-GHSIM: the 帝国炮火先兆者 shells hit every ally whose collider touches their 1.2 circle — the impact tile and the 8 around it, not just the cross (GitHub #364); golden: roster-001, roster-019, diy-020 move
Seen (#364, FrogThai): the 中枢先兆者's shell hit the target and its orthogonal neighbours only — repro: a diagonal
neighbour (√2 ≈ 1.414 from the impact) took nothing, as did a tile two away; the reporter saw the 3×3 in the official game.

Official: PRTS 天赋 of both 先兆者 (one shared kit) 「弹道对半径1.2范围内的所有我方单位造成攻击力100%的无来源物理伤害(此弹道
不会强制击中主目标,碰撞无视迷彩)」. The landing is a 碰撞; PRTS 作战机制 §碰撞体积 (docs/SIM.md, constants.js): collider tests are
the common way and an ally's collider is a 0.25 circle — the rule the engine already applies to ranged enemies' reach.

Now (content/enemies/fly.js kitShell): an ally is hit when its collider touches the 1.2 circle — centre distance ≤ 1.45
(SHELL_REACH = SHELL_RADIUS + ALLY_COLLIDER_RADIUS): the impact tile and the 8 around it, never two tiles away. The
telegraph and the blast are drawn at that reach. [ASSUMED] for this shell (its text names the 碰撞); other content zones
keep their point radius as before. Golden: the three battles with a 先兆者 whose shells land beside a diagonal operator
(roster-001 中枢先兆者, roster-019 and diy-020 先兆者).
2026-10-08 20:21:19 +08:00
sganggs e733171b13 feedback7 R22-OSIM: 香槟炸弹 no longer goes off on an unrevealed 隐匿 enemy (nor a sleeping one) — it selects like the other contact traps; golden: bond-yanShip-high, coop2-HARD-4 move
Community report relayed by the owner: 「有人反馈香槟炸到没有破隐的隐匿敌人了」. Reproduced: a 隐匿 walker crossing
琳琅诗怀雅's bombs set them off (both kits checked hidden / flying / untargetable only). The rule: PRTS 作战机制 §隐匿
"隐匿效果使得获得该效果的单位无法被任何敌方的能力索敌选中…要选中隐匿的目标,则该单位自身需拥有无视隐匿的效果"; 异常效果 lists
隐匿 and 无敌 among the 无法选择 effects (沉睡 = "无敌且无法行动", gamedata_const ba.sleep). Neither the 香槟炸弹 page nor
琳琅诗怀雅's S2 carries a 无视隐匿 / 无视可选性 note, and the other contact traps of the sim (多萝西's 共振装置, 望's 棋子)
already select through canTargetEnemy.

Now both kits go off on a ground enemy canTargetEnemy accepts (tokens.js CHAMPAGNE_TRIGGER): a 隐匿 enemy sets one off
once it is revealed (反隐) or blocked (its 隐匿 lifts), a sleeping one once it wakes (until now the bomb was spent on it
for no damage). Placement is unchanged (it already aimed at selectable enemies only).

Golden: bond-yanShip-high and coop2-HARD-4 (bombs under 隐匿 enemies of rounds 10–11 — 隐形弩手组长, 访问团强攻冠军,
重弩突袭者 — and sleeping ones of round 7 — 宿主士兵, 粉碎攻坚手 — now wait).

Tests: test/content/feedback7-champagne-stealth.test.js (2; both fail on the parent).
2026-10-08 20:15:17 +08:00
sganggs 5f98baecc1 feedback7 R22-OSIM: 琳琅诗怀雅's 香槟炸弹 holds 禁疗, loses no HP and never leaves because of its HP (the owner's decision D2); golden: bond-yanShip-high, coop2-HARD-4 move
The owner's decision D2 of 2026-10-08, a deliberate deviation: PRTS 香槟炸弹 gives it 1000 HP and the note
"即使自身生命值未满,模型下方也不会显示生命值槽" (officially it can lose HP), and it had no 无敌 / 禁疗. Now
(tokens.js champagneHold, installed by the token kit and by 琳琅诗怀雅's own bomb):
- 禁疗: no heal reaches it, no healer picks it (flags noHeal + healFree, no status icon);
- no HP loss: every damage to it is cancelled in its `hit` / `elementHit` hooks (活性源石, 污染秽蚀, …) and a 流失
  is given back before the knock-out check, so it never leaves because of its HP;
- its 见面礼 is unchanged: the first ground enemy that touches it, then it is gone. No 无敌 flag (that would put a
  badge over it); the client side (its hidden HP bar) belongs to the render stream.

Golden: bond-yanShip-high (a healer of that team spent 27 heals — 5040 HP — on a bomb standing on 活性源石; now it
attacks nothing there) and coop2-HARD-4 (ai_1's bombs from round 6 on stood on 活性源石 / 污染秽蚀; their longer life
changes later rounds' layers).

Tests: test/content/feedback7-champagne-hold.test.js (3; 2 fail on the parent, the 见面礼 guard passes on both).
2026-10-08 20:07:06 +08:00
sganggs f14b3a062f feedback7 R22-FIELDS: 耀骑士临光's 卡西米尔 redeploy reduction (garrison 144) has no 5 % floor — the multiplier clamps at 0 like every other redeploy multiplier, so a knock-out timer can reach 0 s (GitHub #370); golden: unchanged
GitHub #370 (FrogThai): 「耀骑士临光特性赋予身前干员减再部署有上限,最多减至5秒」. Cause: content/garrisons/battle.js
applyReader, act1autochess_gar_eff_respawnTimeByBond, wrote redeployMul = max(0.05, 1 + respawn_time × steps), so the
timer stopped at 5 % of the base time — from 192 卡西米尔 layers for 144_a (raw 0.04) and from 96 for 144_b. Measured on
a 100 s base (notes repro-370.mjs): 144_a 192 / 300 layers → 5.00 s / 5.00 s, 144_b 96 / 192 / 300 → 5.00 s each.
Official: data/garrisons.json garrison_144_a bb { divide_num 3, respawn_time −0.015 } 「每叠加3层,本干员再部署时间-1.5%」,
144_b −0.03 「-3%」 — no minimum key; PRTS 耀骑士临光 has no 卫戍 note on a minimum. Now max(0, …) as items/battle.js,
bands, the 协防 bond and svrash; deploy.js already clamps the timer at 0: 144_a 192 / 300 layers → 4.00 s / 0 s,
144_b 96 / 192 / 300 → 4.00 s / 0 s / 0 s. A 0 s timer brings the operator back on the next tick, no error (notes
probe-370-redeploy.mjs). The ASPD part (garrison 159 / 160) is untouched. Patch from the Grok triage
(scratch-i1b/370.patch), the test extended with 96 layers and the 0 s return.

Tests: test/content/garrisons_battle.test.js 26/26 — the new #370 test (144_a / 144_b at 9, 96, 192, 300 layers: the
multiplier, the knock-out timer, the 0 s return) fails on the parent.
2026-10-08 19:56:44 +08:00
sganggs 5a045731f1 feedback7 R22-OSIM: 望's placed 棋子 drop their 铸子 跟子 at the battle start (undeployable ground first, 上 > 右 > 下 > 左); a deployment on a 跟子's tile removes it; S3's overflow follows the same order; golden: unchanged
Community report relayed by the owner: 望的天赋以及3技能增强的天赋提供的额外棋子是可以出现(官方好像有出现的前后左右先后
顺序的规则)在不可部署地块的. The placement rule was already PRTS 望 铸子 备注's ("有敌人的>没有敌人的;不可部署地块>可部
署地面地块>可部署高台地块…相同优先级时按棋子上>右>下>左"), but only a 棋子's return dropped a 跟子: the battle-start
deployment of the pieces the player placed — their 手动部署 in this mode (PRTS 卫戍协议/帮助: a placement in 休整 fires
no deployment effect; the piece deploys when the combat starts) — dropped none, so no extra piece appeared, a lone 棋子
never connected and never set off. Now:
- the stone kit's deploy hook drops one 跟子 when `ctx.initial` (a return still drops its own in scheduleReturn);
- "跟子所在格进行部署(或进行类似部署的行为)时,该跟子会随之消失": any ally deploying on a 跟子's tile removes it (the
  battle start deploys one piece after another, so a 跟子 may first land on a piece still to come);
- S3's overflow (备注 "采用相同的位置选择优先顺序"): enemy tiles first, then the tile class, then her target order /
  distance / tile [ASSUMED ties] — an enemy on undeployable floor now comes before one on the road.
Her stock rule (the owner's decision of 2026-10-06) is unchanged; a 跟子 takes no stock.

Tests: test/content/op_wang.test.js — the four tests that encoded "the battle start drops no 跟子" updated, a removal
case and an S3 order test added (10; 5 fail on the parent).
2026-10-08 19:36:35 +08:00
sganggs 977215e14d feedback7 R22-OSIM: enemy effects PRTS marks 不可对空 no longer hit the flying 炎佑 (death blasts, 水遁忍者's vortex, 鼎沸, 祈祷邀约, the 胄 blades); golden: unchanged
Community report relayed by the owner: 炎祐好像吃到了不该吃到的地面伤害. 炎佑 is a flying ally (PRTS “炎佑”
行动方式 飞行). The ground terrain (活性源石), 烹泉 / 沏虹, 庞贝 and 集团军重型火炮 already skipped it, but these
不可对空 effects (PRTS, read for every enemy of data/enemies.json) went through areaAllies / fieldAllies /
targetsNear, which exclude 起飞 allies only:
- 死亡爆炸 of 高能源石虫 / 冰爆源石虫 / 卷心籽 (archetypes deathBoom: `noAir`, on by default; 寒冷 too);
- 水遁忍者 漩涡形态 "每秒对半径1.0范围内的所有我方单位造成…(无视迷彩,不可对空)";
- 鼎沸 "攻击范围内的所有我方单位每秒受到…法术持续伤害与…灼燃损伤(不可对空)";
- “萨科塔昂首” 祈祷邀约 "令全场我方单位(不可对空,无视迷彩)获得15s【受邀祈祷】攻击速度-30";
- “斩胄之剑” / “破胄之锤” "普通攻击对攻击范围内的所有我方单位造成…物理普通伤害,不可对空" (its target rule too).
A ground enemy's normal attack and the 不可对空-free effects still reach it (PRTS: enemies that hit air target it).

Tests: test/content/feedback7-yanyou-noair.test.js (8; all fail on the parent).
2026-10-08 19:36:35 +08:00
sganggs 42caca3be8 feedback7 R22-OSIM: 引星棘刺's S1 / S2 alchemy units restore HP as 生命回复速度, so 不屈者 and 禁疗 operators recover too; golden: 12 scenarios move (each fields 引星棘刺)
Community report relayed by the owner: 炼金师分支干员的炼金单元无法给不屈者等禁疗的干员提供生命恢复. The
alchemist branch is 锡人 and 引星棘刺. 锡人 S2's recovery was already an hpRegen buff (PRTS 锡人 备注:
"生命恢复的提供方式为增加目标的“生命回复速度”属性,不受治疗加成和禁疗影响"). 引星棘刺 S1 度算浪波 ("每秒回复相当于
攻击力…的生命值") and S2 解构涌潮 ("友方单位每秒恢复相当于攻击力…的生命") carry the same wording and blackboard key
(hp_recovery_per_sec_ratio[_chr]) but called battle.heal, which 不屈者 (no heal from others) and 禁疗 refuse.
Both are now an hpRegen buff per alchemy unit, set at each 1 s pulse until the next (锡人's pattern): the
same amount per second, not scaled by heal bonuses, credited to the target's own regen; S2 skips 孤立
units like every ally effect. Her PRTS page has no 备注 on this; the classification rests on 锡人 and the report.

Golden: roster-014, roster-015, roster-033, roster-034, bond-maniShip-high, bond-soloShip-high,
boss-boss_2-pair, boss-boss_4-pair, boss-boss_6-pair, hidden-boss_8-pair, hidden-boss_10-pair (引星棘刺 on
the board, S2 by default) and coop2-NORMAL-14-standins (h_0 fields her from round 11): her allies' HP
now rises over each second instead of in one lump, and the heal stats move from her to them.

Tests: test/content/feedback7-thorn2-regen.test.js (2; both fail on the parent); the S1 case of
kits_alt_t5 asserts the regen buff instead of a heal of hers.
2026-10-08 19:36:35 +08:00
sganggs 37e45e362e feedback7 R22-OSIM: 白铁's 铁钳号·原型机 counts like an enemy for a non-heal skill's automatic start; golden: unchanged
Community report relayed by the owner: 圣约送葬人 hitting 白铁's device spent no bullet and gained no layer.
Our attacks already selected the device (Battle.setAllyTarget, damage cancelled), but every skill start
condition counted enemies only, so her MANUAL ammo skill (DEFAULT) never opened. The owner's rule of
2026-10-08: a registered ally target in range counts like an enemy for a non-heal skill's auto start.

- skills.js `_allyTargetIn`: DEFAULT (about to attack, the initial range; SEARCH / ACTIVE_RANGE through
  it), CUSTOM_RANGE, SKILL_RANGE, GDGLOW_SKILL_2 (anywhere) and the content trigger ranges. Heal skills
  never count it (禁疗). It stays out of enemiesInKeys / canTargetEnemy.
- 雪猎's empty-magazine S2 cast counts it too; allyTargetsInKeys takes a Set of tile keys.
- 白铁™多功能平台 stays no target. Kits whose own selectors pick enemies (陈 S3, 艾丽妮 S2 guards,
  蕾缪安 S3 locks) are unchanged.

Tests: test/sim/feedback7-allytarget-cast.test.js (4; 3 fail on the parent).
2026-10-08 19:36:35 +08:00
Sukvii c250ff66f4 feedback7 R22-GHSIM: 假想敌:骨刺 targets as PRTS writes — its normal attack ignores its block (by priority, not the blocker first), never a flying unit, and its 3 hidden targets come from its normal attack's reach (PR #365 by @Sukvii, sim part, each line checked against PRTS); golden: roster-018 moves
The sim lines are the PR's (content/enemies/invisible.js kitBoneSpike: profile blockFree and canTarget, the hidden
selection over rangeRadius + the ally collider), so the contributor is the author of this commit; the maintainer side
checked each rule, kept the engine's single target when the hidden list is empty, and wrote the tests.

Official: PRTS 假想敌:骨刺, 级别0 天赋 (on the page since 2025-11, PRTS editors): 「自身普通攻击索敌不受阻挡影响」 「不会攻击
飞行单位,隐匿(解除阻挡0秒后恢复)」 「隐匿期间可同时攻击3个目标」; enemy_database's level description 「隐匿;隐匿状态下同时攻击
3个目标。」 (the handbook line keeps 「数个目标」) — the 3 is no longer [ASSUMED]. blockFree works as for 自制投石机 (a 隐匿 /
迷彩 blocker is no target); canTarget as the engine's other 不会攻击飞行单位 enemies; the hidden 3 are picked among the
allies its normal attack could hit (ai.js attackTargets: rangeRadius + ALLY_COLLIDER_RADIUS, PRTS 作战机制 碰撞体积) — they
were picked within the bare 2.0. Stealth back 0 s after a block was already so.

Golden: roster-018 — the 骨刺 in it lands one more attack (on 异客; dmg 2434 → 2771), the same move PR #365 reported.
2026-10-08 19:28:53 +08:00
IceCodeNewandConvey123 8ae891f1f3 feedback7 R22-HUD: the HP bar shows the ammo skill's rounds as yellow cells (隐现 S2: 14), 伺夜's 狼影 left as diamonds and 斩业星熊's 我执 pool as a red bar — one snapshot change for PR #303 and #378 by @IceCodeNew and PR #383 by @Convey123; golden: unchanged
The three PRs patched the same snapshot and HUD lines (Grok's review: do not merge three diffs), so this is one design
built from their code and tests; IceCodeNew is the commit author (#303, #378), Convey123 co-author (#383).

- b.snap gains three optional, display-only lists beside the unchanged 9-field tuples (snapshot.js ammoView / wolfView /
  negView, called from battle/events.js snapshot(); a living, deployed, visible ally, only when it has one):
  ammo [[id, rounds left, magazine]] (whole rounds; the magazine is the activation's real total that unitTuple's SP
  fraction runs on, extras and refills included), wolves [[id, 狼影 left, talent maximum]] (mem.shadows of the new
  mem.wolfCapacity, set by tokens.js wolfPack and the managed vigil kit), neg [[id, fill]] (unit.negFill(), a function
  op-hsgma2.js sets: the pool is read when the snapshot is taken, no per-tick sync). UnitInfo.ammoSkill (an ally whose
  skill is an ammo magazine) is known from the first appearance: fx events run before the frame's sample, so the aura
  cannot wait for the first ammo row.
- render/interp.js keeps the lists per snapshot (malformed rows / unknown ids dropped) and sample() hands them out from the
  older snapshot like flags (they step with the skill flag); render/units.js draws them: the ammo magazine replaces the
  SP bar (a cell per round, thin cuts, exact fill, no cuts under 2 px a cell), a row of diamonds under the bars for the
  wolves (the element gauge row moves below), the red bar over the drained HP bar for the pool. An ammo skill draws no
  standing aura (rings.js _aura; the activation burst stays).
- PR #378's wolf-head avatars are NOT taken: the count is data (the talent text 至多3只, mem.shadows), the HUD art of the
  official counter is in no game data we have, so the pips are plain diamonds [ASSUMED look]. The PRs' own tests are
  folded in and extended (test/sim/hud-readouts.test.js, test/render/hud-readouts.test.js, op_hsgma2.test.js).
- Docs: network.md, SIM.md §9, client.md, PLAYING.md, types/core.js.
- Golden: unchanged (283 scenarios; the canon hashes units / down / elem only, no sim state moved).
- Tests: 4 + 14 new + 1 in op_hsgma2 (12), all fail on the parent; 344 related tests pass; lint 0 errors, typecheck,
  check:imports, docs tests.

Co-authored-by: Convey123 <Convey123@users.noreply.github.com>
2026-10-08 19:22:08 +08:00
sganggs ca671f2fd0 feedback7 R22-GHSIM: 大帝 加急调派 stacks without a cap — the 21st deployment and every later one still halve the next redeploy (GitHub #328, PR #329 by @IceCodeNew, re-implemented); golden: unchanged
PRTS 卫戍协议:盟约 下半 and its PRTS盟约记录: 「我方干员每次部署后再部署时间减少50%」 with the note 「※该策略效果可无限
叠加」; the data's buff (act1autochess_band16_buff, respawn_time −0.5) names no cap. The per-deployment ×0.5 stack was
capped at 20 (since the initial import, no source); maxStacks is now unbounded, the multiplicative stack itself is
unchanged (the "each deployment" reading was [ASSUMED] cumulative — the 无限叠加 note backs it). Golden: unchanged (no
corpus battle deploys one operator more than 20 times under 大帝).
2026-10-08 19:16:34 +08:00
sganggs 7e8b435f7c feedback7 R22-GHSIM: 信仰搅拌机 S1 reloads the latest-deployed 拉特兰 ammo user on his 8 surrounding tiles, not the nearest (GitHub #325, PR #329 by @IceCodeNew, re-implemented); golden: unchanged
PRTS 信仰搅拌机 S1 备注: 「补弹范围为周围8格,仅选择可补弹的干员为目标,优先选择最后部署的干员」. The candidates (his own
拉特兰 operators within 1.5 tiles — the 8 surrounding tiles — whose ammo skill runs) are now sorted by the battle-wide
deploySeq, latest first (a redeploy is a new deployment), ties by unit id; until now by distance [ASSUMED]. The unused
detmath hypot import goes. Golden: unchanged (no corpus battle has two such candidates in a different order).
2026-10-08 19:13:30 +08:00
CXUtk f2aec39e93 feedback7 R22-FIELDS: the Hidden Core 铳's 碎铳之簧 chase the casting gun for the whole 5 s of 末日布道 instead of stopping on arrival; each gun keeps its data timer, the later call takes the springs (PR #347 by @CXUtk, its pair stagger and lock not taken); golden: hidden-boss_9-pair, hidden-boss_9-solo, coop2-ABYSS-10-boosted
PR #347 by @CXUtk, applied with changes. Kept: 追逐模式 lasts the gain's whole 5 s — PRTS 假想敌:铳 末日布道 "令全场的
“碎铳之簧”获得5秒增益…增益期间切换为追逐模式", “碎铳之簧” 追逐模式 "持续追踪令其进入该形态的场上的假想敌:铳移动" (no
arrival clause, unlike the 铳's own 冲锋模式, which ends "到达目标所在位置后"); data skill 2: cooldown 45, initCooldown 20,
dog_duration 5, move_speed 8. kitSpring no longer ends the chase when it reaches the gun or comes within 1 tile; with no
gun left on the field the spring holds still until the gain ends (until 0.2.1 that ended the chase at once).
Not taken (the maintainer's decision on the Grok triage): the second gun's half-cooldown first-call delay and the cond
that refused a call while any spring was chasing — neither is in the data, and the lock contradicts the handbook's
「持续召唤场上所有“碎铳之簧”向自身移动」 (a call takes every spring to its caster). Both guns keep their data timers, so on a
pair field the mirrored gun's call, a tick after the first, retargets the springs for a new 5 s.

Measured (notes repro-347.mjs): a spring 0.2 tile from the gun chased 0.03 s, one 5 tiles away 2.97 s; now 5.03 s both.

Tests: test/content/hidden-gun-pursuit.test.js (new, 5; the arena harness and two tests are the PR's): the full 5 s
next to a moving gun and with no gun left fail on the parent; the pair timing (20 s after each gun's spawn, then every
45 s, the two calls a tick apart), a mid-chase call retargeting the springs for a new 5 s and the solo timing guard
against the stagger / lock. test/sim/feedback1e-healers.test.js E2 audit: the fields whose leaders / parts a healer must
block run 200 s instead of 120 — on the solo 铳 field the springs now first meet a healer at 145 s (at 21 s until now).

Golden (on top of the portal commit):
- fields hidden-boss_9-pair: the springs spend 5 s invulnerable per call, so they take less (actrpa 855522 → 722451,
  actrpb 798033 → 660498, actrpc 1384683 → 1168947) and pass less on; leader left 3511007 → 3747749; p2's deaths
  7 → 12 (longer tramples); still 8 / 8 kills, no leak.
- fields hidden-boss_9-solo: leader left 1932856 → 2011732; the springs take less; 隐德来希's candles (5601_entlec, an
  enemy-side summon) 6 → 8.
- matches coop2-ABYSS-10-boosted (hidden boss_9): still cleared at 800 LP; the seats' leader damage shifts
  (7523075 / 6369365 → 6992346 / 6900614).
2026-10-08 19:13:21 +08:00
sganggs b2510524b0 feedback7 R22-GHSIM: 歌蕾蒂娅 S3's skill-end 捕网 pulls the enemies within 1 tile of the tornado, not 1.5 — the tornado keeps 1.5 (GitHub #324, PR #329 by @IceCodeNew, re-implemented); golden: fields boss-boss_4-pair moves
PRTS 歌蕾蒂娅 S3 备注: 「龙卷风半径1.5」 and 「技能结束时的拖拽为捕网,捕网半径为1,无伤害」. The kit reused the tornado's
radius for the final pull (its 1.5 was marked [ASSUMED]; PRTS now backs it). The slow and the pulses keep 1.5; only the
skill-end pull (to her front, as before) uses 1. Golden: boss-boss_4-pair fields 歌蕾蒂娅 — fewer enemies are dragged to
her front at the skill end, the fight runs differently (11 kills instead of 14, one leak).
2026-10-08 19:10:37 +08:00
sganggs a0cd6826e5 feedback7 R22-GHSIM: 异客 S3's 雷暴 covers range x-1 — the 13-tile diamond — around the tile of the target's centre, not a 1.5-tile circle around its position (GitHub #322, PR #329 by @IceCodeNew, re-implemented); golden: roster-016/018/048, fields boss-boss_1/3/5-pair + hidden-boss_9-pair, matches solo-HARD-1, solo-ABYSS-1, coop2-HARD-4, coop2-ABYSS-10-boosted, coop2-NORMAL-70-diy move
PRTS 异客 S3 备注: 「开启技能时选择技能范围内的目标,以其判定中心所在格为中心生成一个x-1的雷暴区域」; range_table x-1 is the
13-tile diamond (|Δrow| + |Δcol| ≤ 2); x-3 (|技能范围|) stays the search range. The storm's tile is the rounding of the
target's centre (body.js posKey), fixed for its 4 s; a strike picks among the enemies she can select whose body is on
those tiles (enemiesInKeys, as her other range checks); each strike still chains on its own bounce radius. The fx ring is
drawn at radius 2 (visual only). Until now: [ASSUMED] radius 1.5 around the target's exact position — an enemy two tiles
straight off the target's tile was never struck, one at (+1.55, +1.05) off the tile centre was.

Re-implemented from the PR's claim (its golden files were not taken). Golden: every moved scenario fields 异客 casting
S3 — the zone holds other enemies and the random pick draws from another list.
2026-10-08 19:03:55 +08:00
LimitlessHPPK 5a50f7b5fa feedback7 R22-GHSIM: the module trait line 「攻击范围内存在N名及以上敌人时攻击速度+X」 (REA-Y: 圣约送葬人, 隐德来希) is applied by the engine instead of the two kits — on and off on the tick the count changes; a scan of every chess, 补位 and 自选 loadout shows no other operator gains it (PR #293 by @LimitlessHPPK); golden: unchanged
The contributor's code (server/sim/content/traitMods.js, the battle/players.js _setupUnit wiring after kit.install, the
crowdAspd removal from shared/tier5.js and the two kits, test/sim/trait_attack_speed.test.js), applied from PR #293, so
they are the author of this commit. Maintainer additions: the coverage lock also scans the 补位 stand-ins (266) and every
legal 自选 combination (pool operator × slot form × skill × non-other-mode module) — none gains the rule; 黑键 / 维伊
MSC-Y 「拥有已储存的攻击能量时,攻击速度+30」 (their 自选 kits own it) is listed as kit-owned instead of 'unknown'; the
comment's history note named a commit this repository does not have, and its line-number references are now names;
docs/ARCHITECTURE.md and kits/README.md name the file.

Official: battle_equip_table uniequip_003_excu2 (display trait + hidden talent attack_speed 12, trigger_cnt[equip] 2) and
uniequip_003_etlchi (trait attack_speed 12, cnt 2), both 「攻击范围内存在2名及以上敌人时攻击速度+12」; 仇白's
uniequip_003_qiubai carries the same sentence on her named talent, which her kit keeps reading (not seen by the engine).

Before: shared/tier5.js crowdAspd polled every 0.2 s and gave a 0.3 s buff — measured +12 0.167 s after the second enemy
arrived and 0.267 s after it died (scratchpad repro); now one tick each. Golden: unchanged (no sampled snapshot moves).
2026-10-08 18:56:12 +08:00
Convey123 ffa538c39d feedback7 R22-RENDER: 赤刃明霄陈 S3's sword wave is drawn along its path — the sim sends its position as a chen3Wave fx every 0.12 s, the client draws a 'qi' blade (PR #382 by @Convey123, owner item 12); golden: diy-073 / diy-074 events.fx and fx.chen3Wave only
The 赤霄·天喟 wave is a kit-managed probe (it turns corners and lives as long as the skill), not a snapshot
projectile, and the sim emitted one `dash` at the cast and a `slash` per hit — nothing along the way, so the client
drew no wave. op-chen3.js now emits fx('chen3Wave', { x, y, fromX, fromY, dr, dc, id }) every WAVE_FX_EVERY (0.12 s;
4 ticks), the trail restarting at a corner; render/fx registers chen3Wave → 'qi' (pt: drawn at the event, never on
her) and draws a streak plus a crescent head turned the way it travels. The look is a procedural stand-in, not the
official particle prefab.

Substantially @Convey123's code (PR #382), authored as theirs. Changed on review: the head is projected after
streak() — streak() reuses the effect system's projection scratch, so the PR drew the crescent on the trail's start,
one event behind the wave — and the trail, head and heading share one height; an unused test variable dropped.

Golden: diy-073 (5_diy*=chen3 S3 in two slots) events.fx 508 → 1558, fx.chen3Wave → 1050; diy-074 (6_diy*=chen3 S3)
events.fx 272 → 872, fx.chen3Wave → 600. HP, kills, damage, hooks and snapshot hashes unchanged: battle.fx only
records an event.

Tests: test/content/op_chen3.test.js (+1: the events, their cadence, id, direction, trail start, silence after the
skill) 12/12; test/render/fxchen3wave.test.js (new, 6: the archetype, drawn at the wave not at her, the head on the
wave and turned with it, a sweep joining into one trail, junk input, nothing left after) 6/6; boardart 15/15.
2026-10-08 18:48:53 +08:00
Cloudnyco ae22335cfe feedback7: the battle sim uses engine-independent math — Chrome, Firefox, Safari and the server agree bit for bit (PR #373 by @Cloudnyco)
- server/sim/detmath.js: hypot (sqrt of the squares, rescaled outside 2^±500), powi (integer powers in double-double,
  one rounding), sin / cos (fdlibm 5.3) and atan2 (fdlibm / FreeBSD msun) built only from correctly rounded IEEE
  operations; the sim's Math.hypot / sin / cos / atan2 / pow calls go through it (65 files); eslint.config.js forbids
  the approximated Math functions under server/sim and test/sim/detmath.test.js scans for them.
- sin / cos / atan2 are the algorithms V8 runs in Node, so the server's results stay; only hypot differs from V8's.
  Golden: 2 moved — diy-027 (a hypot distance, damage +80) and coop3-ABYSS-5 (a later card pick from round 9, same end).
- Applied unchanged after review (Grok static review: MERGE; the diff read in full: no network, no new dependency).
- Tests: broad node --test 5155 / 5155 with the new file tracked (detmath 7 / 7, package 10 / 10); lint 0 errors,
  typecheck, check:imports.
2026-10-08 18:35:55 +08:00
sganggs b05845f507 feedback6: merge R21P — every operator at full potential (潜能 6; GitHub #252, PR #255 by @SpiritedAwayCN, the owner's decision of 2026-10-07)
- tools/build-data.mjs applies every potentialRanks attribute step (COST, RESPAWN_TIME, ATK, MAX_HP, DEF,
  MAGIC_RESISTANCE, ATTACK_SPEED) to the chess, elites, 补位 and 自选 units and picks talent / trait / module-talent
  candidates up to requiredPotentialRank 5; summons take the owner's potential for their talents, not its stat steps.
  data/chess.json, backups.json, tokens.json and the en / ja / ko / zh-TW data translations rebuilt; op-wang.js reads
  her stock cap (8 at full potential). 刺玫 435 ATK / cost 15, 砾 16 s, 至简 70 s.
- No conflicts outside the golden files (regenerated). Golden vs HEAD: roster 49, bonds 46, fields 22, matches 18,
  diy 133 (standins and diy-012 / diy-135…138 unchanged: no potential ranks or never hit). Union check against the
  branch and the merge base: every scenario only the branch moved equals the branch, except roster-048 and
  solo-ABYSS-2: at full potential a 频次 器物 is reached there (roster-048: one more enemy dies instead of leaking, 86 → 87
  units), so R21H's hit count (data × hpMul ÷ supplyHpMul) applies where it did not before — with only that rule put back
  (archetypes.js times as at the merge base) both equal the branch exactly.
- Tests: broad node --test 5147 / 5147; lint 0 errors.
2026-10-07 18:48:38 +08:00
sganggs 806a047717 feedback6 R21P: every operator fights at full potential (潜能 6) — the owner's decision of 2026-10-07 (GitHub #252, PR #255; no host slider): tools/build-data.mjs OPERATOR_POTENTIAL adds every character_table potentialRanks attribute step (部署费用 / 再部署时间 / ATK / HP / DEF / RES / ASPD, all ADDITION, before rounding) to every chess (normal and elite), 补位 and 自选 unit form and picks talent / trait / module-talent candidates up to requiredPotentialRank 5 (「天赋效果增强」); a summon picks its talent candidates at its owner's potential (their requiredPotentialRank mirrors the owner's — PRTS 凯尔希: Mon3tr 3.5 s / 1400) and takes none of the owner's attribute steps; the 原型干员 stand-ins have no potential ranks (unchanged). 刺玫 413 / 17 → 435 / 15 as in the tournament video, 砾 18 → 16 s, 至简 80 → 70 s. data/chess.json (256 records), backups.json (the 71 owned picks, 8 summons), tokens.json (5 summons) and the data translations en / ja / ko / zh-TW rebuilt — only potential-driven fields (JSON-compared); the 干员调配 局内数值 and detail cards read the records. op-wang.js reads her stock cap 「最多拥有8(+1)枚」 through the potential step (the pattern fell back to 7: she sat at the cap from the start). Docs: DATA §2 / §18 / tokens, PLAYING (detail card), research 03, kits README, shared/diy.js / standIn.js, the 71 自选 kit headers and the kit comments that quoted potential-0 numbers. Tests: test/full-potential.test.js (new, fails on the parent); data.test.js re-derivation adds the potential steps (+ respawnTime); every test that hard-coded a potential-0 number carries the full-potential one (from the data and the test's own formula; no check loosened); golden: moves almost everywhere — roster 49/49, bonds 46/46, fields 22/22, matches 18/18, diy 133/138 (each battle parts on a stat: roster-001 / roster-020 at tick 1 on 角峰's HP (生命上限+250), bond-arcaneShip-high at 4.73 s and diy-001 at 3.70 s on an enemy's HP from a higher ATK; diy-110 / 111 also by 望's cap; the matches through those battles); unchanged: standins 10/10 and diy-135…138 (no potential ranks), diy-012 (twelve 夜莺 never hit, never redeployed) 2026-10-07 18:35:39 +08:00
sganggs a9fe794c3f feedback6: merge R21H — 器物 (频次) enemies take the 攻坚 HP share and not 补给线's (the data's exclusion list names exactly the 14 器物), leader summons take the round's enemy scaling (PR #272 by @CXUtk, re-implemented from the data); tools/golden.mjs keeps R21H's roundMods import and drops uniteStageId (removed by R21B); golden regenerated on the merge — vs the parent exactly R21H's 74 scenarios, vs the branch only the other streams' moves 2026-10-07 18:21:01 +08:00
sganggs 3f918c9f03 feedback6: merge fb6-small-fixes (see its commits) 2026-10-07 18:16:10 +08:00
sganggs e33ee3db8f feedback6 R21H: the round's enemy effects reach the 频次 器物 and the leaders' mid-fight summons (PR #272, 感谢 @CXUtk); golden: 74 moved
器物 (the 14 hit-count keys): hits = data × the spawn's hpMul ÷ supplyHpMul, rounded as before (setHits) — 攻坚装备 / II / III
leave out only 炎佑, 补给线 / 补给线II also exactly these 14 keys (activity_table aceffect_enemy_2 / 2_2 enemy_exclude,
data/effects.json); until now setHits(def.maxHp) overwrote the round's HP (青铜镜 30 hits at every difficulty). build-data
writes enemyScale[r].supplyHp = 1.2^(kHp − kAtk) · extra (the HP-only 补给线II steps and 补给线's 1.08; co-op 终极 R5–R15
only — the rebuild changed config.json alone), gamedata returns it as supplyHpMul and the wave / 悬赏 mods carry it
(waves.js roundMods; a 频次 enemy's death spawn inherits it). Not taken from the PR: its 1.08 / 1.2 back-calculation (it
counted the 补给线II steps as 攻坚装备) and its fractional-HP ceiling. Leader summons (死亡集群's 妖怪, 刺胄之弹,
“裂管之音”/“断弦之音”, 不祥幻影): the boss / hidden field carries the round's scale as flags.enemyScale (bossRounds.js,
golden fields, tools/balance.mjs) and bosses.js summonMods gives them HP / ATK / speed (死亡集群's summon.hp_ratio on
top; 刺胄之弹 / 余音 hit counts follow their HP); the leader's pool stays exempt; 王权号令's invulnerable equipment
unchanged; 炎佑 is an ally token, never scaled (no change). Unchanged and open: the 逐火 / 再生 husk counts (talent
prop_max_hp).

Golden — 器物 counts: roster 37 (002 003 004 005 007–020 022 023 025 026 029–034 036–041 043 045 049: each holds a 器物
extra spawn / 频次 wave / death spawn), bond-soloShip-high, diy 9 (036 040 056 062 068 073 091 114 115), boss-boss_6-solo
(俗心's 小说卷轴 escorts); matches 16 (all but solo-ABYSS-2 and coop2-NORMAL-70-diy: 频次 rounds / 悬赏 and the Final
Assault summons). Summons: boss-boss_1-pair/solo, hidden-boss_8-pair/solo (妖怪, 刺胄之弹), boss-boss_3-pair/solo,
hidden-boss_10-pair/solo (余音), boss-boss_5-pair/solo (不祥幻影). standins unchanged.
2026-10-07 18:05:42 +08:00
sganggs ce2bd75b49 feedback6 R21E: a refresh runs the 刷新时 特质 of the chess that stood on the board / in the hand when it happened (EffectDispatcher.dispatch takes them before its first handler; each still runs where it stands now, one that left is skipped): the 拉普兰德 贾维 grants on every 6th refresh — or the elite that gift completes — fired in the very refresh that granted her and spent her 「本回合首次主动刷新」; now her first is the next manual refresh; round counters are still not copied on a merge (a merged elite is a new 拉普兰德, §25.13.3); the part of PR #196 0.2.0 lacked, re-implemented; golden: unchanged 2026-10-07 18:02:48 +08:00
sganggs c623550f29 feedback6 R21E: the 外勤医疗 Touch casts 恳切福音 on an injured ally inside its 5-2 (ACTIVE_RANGE in touchKit — the larger-range rule the Touch 补位 already runs by its data; the map character's record keeps DEFAULT), and the Touch / 预备干员-医疗 card is an operator card (干员 · 医疗 · 远程位, 特性, skill row with SP / duration, talents from the tokens.json record — it took the summon path: 召唤物, base stats only); 恳切福音 gets a line under its text that the boost is strictly below half (PRTS 修正 of 不高于, what touchGospel does; the operator card of the 补位 Touch too: SKILL_TEXT_NOTES); GitHub #260, PR #278; golden: roster-041 (its strategy Touch heals 8438 → 17072, 19 → 27 heal actions, casts unchanged at 2, the same numbers as PR #278; p1 deaths 7 → 4) and matches coop2-NORMAL-14-standins (h_0 plays 外勤医疗: defeat in round 13 → victory, teamLp 16) — both battles with that strategy's Touch, no other scenario moved 2026-10-07 17:54:17 +08:00
sganggs 26c72a6d95 feedback6: merge R21B — 联防 plays on the round's battlefield again, its terrain, crates, water, devices and runes as in 0.1.4 (the owner's report 「联防阶段地形全消失了」 and knowledge of the official mode, GitHub #244's tournament video; 0.2.0's escaped level was the placeholder road every wave-template level carries); the 联防 battle input is byte-identical to 0.1.4's in 20 cases; 乌尔比安's comment keeps both streams' sentences; golden as R21B's commit (unite-1 / unite-2 back to their stages, coop2-NORMAL-3, coop2-HARD-4, coop3-ABYSS-5, coop4-ABYSS-7, coop2-NORMAL-8-serverrun, coop2-NORMAL-14-standins), the merged tree differs from the branch only in R21A's boss pair fields 2026-10-07 17:54:16 +08:00
sganggs 75202776cc feedback6 R21B: 联防 plays on the round's battlefield again — its terrain, crates, water, devices and runes, as in 0.1.4 (the owner's decision of 2026-10-07, 「官服保留地形,改回去」; GitHub #244). 0.2.0's escaped-level map (8a436249, §25.6.4) is withdrawn: that map is the placeholder grid all 39 wave template levels carry, tile for tile; only the 11 stage levels have terrain. match/unitePhase.js _uniteOpts fields this.stageId in both combat modes, unite.js uniteStageId is removed, the client draws the 联防 on the board's stage again (screens/game.js: 0.1.4's ownStage / baseStage, no map switch, nothing to restore on leaving), the dev mock likewise. Kept from 0.2.0: own-board 突袭 / 乌尔比安 S3 landings (onOwnBoard, raidTile untouched), the bounty payee, the 联防 BGM, the SETTLE result box. data/stages.json keeps the two kind 'unite' records (no field uses them; engine tests use them as a plain two-halves road); tools/build-data.mjs comments only, an offline rebuild reproduces data/ byte for byte. The 联防 battle input is byte-identical to v0.1.4's in 20 cases (5 stages × 1 / 2 helpers × both combat modes); GitHub #41 item 3 (野鬃 pushing walkers back across the gate onto the other half) is back with v0.1.4's numbers, none off the map. Tests: test/match/feedback5-unite-map.test.js rewritten (6, all fail on the parent), test/e2e/coop.e2e.mjs checks the 联防 field's drawn stage; docs: DATA §12, META §4, PLAYING §5, design/geometry-time, I18N, the §25.6.4 pointer; golden: fields unite-1 (escaped_single → act1autochess_m02) and unite-2 (escaped_multi → act1autochess_m07), the stages of 0.1.4, and the co-op matches whose 联防 rounds come out differently on the round's map — coop2-NORMAL-3, coop2-HARD-4, coop3-ABYSS-5, coop4-ABYSS-7, coop2-NORMAL-8-serverrun, coop2-NORMAL-14-standins (now a victory) 2026-10-07 17:40:03 +08:00
sganggs cfd3c67281 feedback6 R21A: a 突袭 member may land on a teammate's half when both halves of the field are taken — the two-helper 联防 field and the Final Assault / Hidden Core pair field (the owner's decision of 2026-10-07): Battle.onFieldBoard (onOwnBoard of any player of the battle) read by raidTile only; a lone 联防 helper's empty half, a solo boss field's other half and the hand / 临时整备区 rows stay closed, every other landing rule kept, 乌尔比安's S3 【移动】 keeps onOwnBoard; golden: 8 moved, each parting from the parent at a member's first landing on its teammate's half (checked tick by tick with the parent instrumented) — fields boss-boss_2 / 3 / 4 / 5 / 6-pair and hidden-boss_8 / 10-pair (the right player's 缄默德克萨斯 / 伊内丝 / 仇白 / 耀骑士临光 on the left player's half, 1–7 landings per battle, the first 0.3–39.8 s in), matches coop4-ABYSS-7 (round 6's two-helper 联防: ai_2's 斯卡蒂 on ai_1's half at 52 s; only ai_1 / ai_2 dmgDealt move, 8263 between them); unite-2 unchanged (its two landings stay on their own half)
Tests: test/sim/feedback5-raid-own-board.test.js — the pair field (the right player's member onto the left telin's board tile (2,3), the left player's onto the mirrored right (2,17), the hand rows closed) and the two-helper 联防 (each helper onto the other's half; 乌尔比安 beside a teammate stays on his own) fail on the parent; the solo boss field's hand rows and the lone helper unchanged.
Docs: docs/history/0.2.1.md (new, §26; §26.1 cites the owner's decision and PRTS 卫戍协议/帮助 §联防阶段), the DESIGN index row and versions line, a pointer from §25.18.1, docs/SIM.md (onFieldBoard; onOwnBoard now 乌尔比安's only).
2026-10-07 17:09:39 +08:00