- Stock: fixed trait gifts (缪尔赛思 / 变形者集群 变形同构体, 耶拉 不融冰, 蜜蜡 / 卡涅利安 迅捷作战粮, 诗怀雅 盟约之币) still occupy stock but are granted past the cap; an operator card already shown in the shop or a reward can be taken after the pool runs out and overdraws (GitHub #498, the owner's decision); item buys and item rewards keep the stock check. 洛洛 / 焰尾 sub-pools use the measured weights (PR #497 by @2321Robin; the occupancy idea of PR #496 by @2321Robin re-implemented differently).
- Boss pairs are drawn at random once per match and fixed to battle start; the Hidden Core reuses them; a leaver does not split a full pair (the owner's decision).
- 阿戈尔 in 联防 no longer re-applies the opening devour HP loss or a false revive; Touch's team medic stays for the match after its holder leaves (owner-approved, official lifetime unverified).
- Auto-skill ranges: 司霆惊蛰 S2, 斩业星熊 S3 against air, 予愿安洁莉娜 S3; 自在's post-rebirth invulnerability is also untargetable (#510); Horn / Clementia / catapult / 忍冬 first hit (PR #502 by @Xinglan233); 不融冰 / tear gas trigger on real damage.
- Bond layer-up sound in round start / draft / prep / battle (#482): one channel, a new cue replaces the old, no extra cooldown; a prep update that adds layers and activates a bond plays one cue.
- Client: multi-swing fix (#506), refresh single-flight (PR #507 by @robll-v1), LP tower keeps the settled value with a −N tick (PR #504 by @robll-v1), export with only 潜能 / 练度 changes (PR #503 by @Xinglan233), spectator rosters list DIY members (PR #505 by @Xinglan233), banned members beside bond tooltips (PR #494 by @YuriRestia), recovery action above the away overlay (PR #511 by @RainoutOvO), the /dev/sim-check.html consistency page (PR #492 by @Cloudnyco), Korean (PR #490 by @D-Roote) and English Victoria wording (PR #499 by @YuriRestia).
- golden: 45 of 287 scenarios move against 0.2.4 (roster 17, bonds 3, fields 6, matches 17, standins 2), each attributed in docs/history/0.2.5.md §30.9 / §30.16.
- Shared card pool and item stock as in the official mode (the owner's request, from the 路标档案馆 video and public notes): solo low-tier exceptions, co-op operators x2, shared item stock with special-item exceptions, normal / advanced occupancy 1 / 2, re-check on buy, 机变 exhaustion, release on consume / destroy / elimination; 整备 never exceeds stock; invariant held <= cap.
- 突袭: one taunt-first reselect right after a revive (the owner's rule); ordinary polls and redeploys keep the 0.2.3 rule; a revive on an enemy's tile stays. #475: online boss / hidden-boss Raid may land on the empty half (owner-limited scope).
- 浊心斯卡蒂 S1 x 坚守 no longer bounce redirected damage, and the two shares conserve the hit (idea of PR #464 by @HappyTanuki).
- Operator fixes adapted from PRs by @Xinglan233 (#459 哈洛德 S2 elemental trigger, #460 涤火杰西卡 shield on the four adjacent tiles, #461 家族徽章 first hit after stealth, #462 松果 S2 regrow per deploy); 克莱门莎 S2 splash 1.1 / 100% ATK and air auto-trigger (#467); 白面 copying 歌蕾蒂娅 / 余 skips the three-member condition (#473, the owner's video).
- 香槟炸弹 is not chosen by friendly auras / heals (PR #468 / #476 by @Siornya); 琳琅诗怀雅 coin balance (PR #450 by @IceCodeNew); Touch prep display (PR #451 by @YinqiMargatroid); lobby header (PR #471 by @YuriRestia); Japanese UI terms (PR #448 by @scutkane).
- AI-only boss countdown grace, render-failure cache / recovery without restarting a battle, device units kept on a same-field re-entry, DIY detail / skill previews, large-text result buttons.
- golden: battle families equal 0.2.3 except diy-135 / diy-136 (克莱门莎); all 18 release matches move through the shared pool, every flip named in docs/history/0.2.4.md §29.12; two coverage scenarios added.
Guard lethal stuns against a replacement deployment; keep bard auras running
through stun; require an active Aegir bond for Clementia's strategy; allow
Compass SP to bypass recovery locks; and refresh Hidden Core gun mitigation
against current gun/spring companions. Set multiplayer strategy picks to 50s
and describe renderer fallback without diagnosing unsupported hardware.
Golden moves (full 285-scenario regeneration):
- roster-008: inactive Aegir no longer gains 18 strategy layers.
- boss-boss_4-solo: bard regeneration continues through stun.
- hidden-boss_9-pair: mitigation covers first hits/current companions.
- standin-07: hammer stun cannot follow an immediate revival deployment.
No ending-reason changes. Sources and report-by-report findings: DESIGN 28.25.
Seen (PR #402, measured again on 0.2.2): TICK = 1/30 is not a binary fraction. An attack cooldown counted down from 1 s
stops at 2.1e-16 after thirty steps and the fire check `atkCd > 0` waited a 31st frame; 300 time gains of 1/30 SP add up
to 9.999999999999975 and `sp >= cost` charged a 10-SP skill a frame late. Over the 265 golden battles 30.85 % of the
consecutive attacks on a whole-frame interval came a frame late (control, other intervals: 0.09 %), and 4 157
end-of-tick states sat within 1e-9 under a cost. The engine already took timers within 1e-9 as done (skill timeLeft,
buffs, every() / after(), enemy abilities, nextCastAt, the 失衡 end); these two did not.
Official: PRTS 作战机制/sandbox 「帧对齐机制对攻速的影响」 — one frame = 1/30 s; since 2019-12-24 a non-integer frame count
is rounded (四舍五入); an exact 1 s is 30 frames under any rule.
Now: ai.js attackCountdown(cd, dt) (left within 1e-9 of 0 is 0) for the operators' cooldown (the canAct guard kept) and
the enemies' (not while stunned or hidden; the 0.2.2 失衡 swing cut untouched) — an enemy's whole-frame wind-up is exact
too (0.4 s: 12 frames, 13 before). The same countdown for the two strict `cd -= dt; if (cd > 0)` attack clocks of the
same shape: the 双眼皮 turrets (content/devices.js; BAT 4 s: 121 → 120 frames) and 寒檀's S2 icicles (0.5 s: 16 → 15).
SkillRuntime.gainSp takes SP within 1e-9 of the cost as full for every charge (a tiny negative remainder → 0);
_normalize compares the same way. Left as they are: a non-integer count still ends on the frame that crosses 0
(⌈30 × interval⌉ — the official 四舍五入 is an older, separate difference); the count-up content clocks that restart from
0 (bosses.js self-timers, kit auras — PR #402's list); attack / hurt SP (+1 on an integer cost) unchanged.
Tests: test/sim/tick-tolerance.test.js (new, 7: the PR's four adapted — residue, attackCountdown over bat 0.1–10 s ×
14 ASPD = ⌈30 × interval⌉, 1 s operator every 30 / 3 s ranged enemy every 90, time SP 4/10/16/20/30/50 at exactly 30 × N
gains for one and two charges — plus the 1.2 s / 1.25 s control (36 / 38), the turret at 0 layers (120) and 寒檀's
icicles (15); the four engine tests fail on the parent: 31 / 91, cost 4 at 121, 121, 16). The PR's seven test edits,
re-run: the same 8 assertions failed on the new timing and each edit passes on the parent and on the fix —
feedback2-surtr-stealth (count once no arrow is in flight), kits_alt_t2 拉普兰德 S1 (dummy ATK 300 → 250: 120 × 15 = her
1791 HP by 59.5 s), kits_alt_t6 (medic smoke at half HP; 余 S1 up to the first 燃烧 burst), op_jesca2 (the T6 shield
returns a tick after the cast), op_lmlee (hits before the burst), op_logos (count after the clear), op_narant (the first
attack thrown after the new enemies). node --test (with the golden of the next commit): 5703 tests, 5701 pass, 0 fail,
2 skipped; eslint 0 errors (135 warnings, the parent's 135); typecheck, check:imports, smoke ok.
feedback7 R23-TICK: golden for whole-frame attack intervals and SP costs (PR #402) — 281 of 283 scenarios move: roster 49/49, bonds 46/46, fields 22/22, matches 18/18, standins 10/10, diy 136/138; solo-NORMAL-1 now loses its Final Assault (below)
npm run golden:update on the previous commit. Every family moves because both sides attack on time (more enemy kinds
than operator forms sit on whole-frame intervals: 3 s, 4 s, 1 s …) and time SP charges a frame sooner. Measured over
the 265 battles: whole-frame consecutive attacks a frame late 30.85 % → 0.04 % (control 0.09 % → 0.13 %; 1 s gaps at
30 frames 256 → 3 776 of ~3 800, 3 s at 90 frames 0 → 6 657 of 6 657), SP float-short states 4 157 → 0. Moved battles'
totals: kills 10 647 → 10 625, leaks 12 398 → 12 445, deaths 2 913 → 2 944. Unchanged: diy-040, diy-069.
End results that flip (one frame cascades; the causes as measured with the matches' battles instrumented):
- solo-NORMAL-1: won → lost in round 14 (passed 14 → 13, team LP 8 → 0): the Final Assault on 卢西恩 (pool 390 000) runs
as before for two minutes (his 0.4 s wind-up a frame shorter), then the team's damage on the pool trails — 884 left
when the overtime drain (from 300 game s) takes the last of the 17 LP at 334 s; before, it emptied at 318 s, 8 LP left.
- solo-HARD-1: LP 10 → 12 — round 8 lets one more through (26 → 25; rounds 11–12 even it out) and the Final Assault ends
at 300.6 s, before the overtime drain (304.8 s and 2 LP before).
- solo-NORMAL-2: LP 9 → 25 — round 5 lets one more through (26 → 25, a coin less), the bot's shop path parts from round
6 and its later board (突袭, 232 layers at round 13 against 94) clears rounds 12–13 with no leak (7 + 18 before).
- coop2-NORMAL-3: team LP 63 → 68 — ai_1's round-13 battle leaks 1 instead of 6 (its round-12 leaker now goes to 联防).
- coop2-ABYSS-10-boosted: team LP 583 → 630 — the Final Assault ends at 606.6 s (639.6) and the Hidden Core at 335.9 s
(397.8): 47 LP less of overtime drain.
- coop2-NORMAL-14-standins: team LP 41 → 40 — ai_0's round-13 battle lets one 潜伏者 through (23 → 22).
- roster-016: cleared at 220.3 s → time-out at 230 s (主角阵营角色 leaks instead of falling; kills 101 → 105, leaks 26 → 22).
- roster-041: time-out → cleared at 189.0 s, perfect (the last 粉碎攻坚组长 falls inside the 190 s).
- bond-suntShip-high: cleared at 164.2 s → time-out at 190 s (kills 11 → 13, deaths 4 → 2).
- standin-04: perfect → 10 leaks (deaths 8 → 10; 萨卡兹大剑组长 / 萨卡兹穿刺手 / 澪 get through).
- diy-005 / diy-008 (艾丽妮 / 赫拉格): cleared at 225.3 s → time-out at 230 s (a last 宿主重装士兵 / 深池方阵指挥官 walking).
- diy-127 (白铁 / 酒神): time-out → cleared at 225.8 s (deaths 7 → 13, leaks 57 → 72).
- diy-131 (死芒): perfect → 1 leak (a 掠海漂移体).
The other matches keep their ends (solo-FUNNY-1/2, solo-HARD-2, solo-ABYSS-1/2, coop2-HARD-4, coop3-ABYSS-5,
coop4-FUNNY-6, coop4-ABYSS-7, coop2-NORMAL-8-serverrun, solo-HARD-9-boosted, coop2-NORMAL-70-diy). PR #402's own
0.2.1 table (coop2-NORMAL-14-standins loss → win, solo-HARD-2 / solo-ABYSS-2 earlier exits) was measured before §27 and
does not repeat here.
loadout.e2e 「局内数值 (desktop)…」 failed with 'Node is either not clickable or not an Element' on the 局内数值 精锐 tab
right after picking 信仰搅拌机. pickChess returned as soon as a stats cell was visible — the previous chess's — and the
detail resets its scroll for a new chess after paint (screens/loadout.js), so puppeteer scrolled the tab into view and
the reset then moved it below the viewport before the click (measured: scrollTop 366 → 0, the tab at y 1201 of 1080).
The 0.2.2 detail opens with 潜能与练度 and 特质, so 局内数值 / 模组 sit below the fold and need that scroll. pickChess now
waits for the detail's name and its body back at scrollTop 0. A player is not affected (the reset is the intended
behaviour); the assertions are unchanged.
- Tests (SP_E2E=1): loadout.e2e 11/11.
The 0.2.2 干员调配 is one list: a row carries the skills and the elite's modules, and the detail (now opening with
潜能与练度 and 特质) has its module cards below the fold at 1920 × 1080, where the Client's real-mouse click (no
scrolling) found nothing clickable for `.lo-detail .lo-mod[data-module="none"]`. Both suites now tap the row's
`.lo-q--skill[data-skill="0"]` / `.lo-q--mod[data-module="none"]` and wait for the row (aria-pressed) and the detail
(is-on) to agree before the sync; what they assert is unchanged (m.private.loadout → b.start spec → the local sim
runs S1 without the module; the host's card of the guest's unit reads S1 已调配 / 未装备模组).
loadout-battle's detail card check then met 0.2.2's other change: the card's base ATK carries the player's 练度 — the
default 精英2 Lv.60, ×1.1 (576 for the record's 524, effects.json aceffect_char_4); the unit's def keeps 524.
- Tests (SP_E2E=1): loadout-battle 2/2, teammate-loadout 1/1.