Commit Graph
627 Commits
Author SHA1 Message Date
sganggs 3c36cdff48 feedback6: merge R21D — with both slots full, every consumable (博士投影, 盟约之币 …) opens the replace dialog and destroys only the picked item once its effect succeeds (PRTS 卫戍协议/帮助 「达到上限强行佩戴会改为替换装备…并销毁被指定的装备」; GitHub #263, PR #264 by @SpiritedAwayCN, ported); golden as R21D's commit (10 matches: bots using a consumable on a full operator), the merged tree differs from the branch only in R21B's 联防 scenarios 2026-10-07 18:11:53 +08:00
sganggs 8cef750e14 feedback6 R21D: a consume-on-equip item on a full carrier opens the replace dialog and replaces the picked item first (GitHub #263, PR #264); golden: matches 10 of 18 moved (a targeted consumable on a full carrier now destroys the oldest item), the rest unchanged
PRTS 卫戍协议/帮助 §装备: 「达到上限强行佩戴会改为替换装备:指定一件已佩戴装备替换为将要佩戴的装备,并销毁被指定的装备」,
no exception for the 装备时销毁 items. Before: a normal 博士投影 opened no dialog and its kept item pushed the OLDEST
equipped item out (replaceUid ignored); 盟约之币 and the other consumables kept both items.

- server PlayerState.equip (player/items.js): on a full carrier the consume path takes the pick (replaceUid, else the
  oldest) off before onEquip (_takeReplaced), destroys it (onDestroy reason replace) once the effect went through —
  the normal 博士投影 takes the freed slot —, and puts it back at its index when the effect refuses (博士投影 on an elite:
  nothing destroyed)
- client gameLogic equipReplaces: the replace dialog opens for every item on a full carrier, consumables included,
  except an attaching item that completes an item merge and a 博士投影 on an elite; itemAttaches removed
- bots (itemTarget): a consumable whose effect is the same on anyone goes to a carrier with a free slot first (PR #264)
- docs: design/match.md equipment rules, META §2.5, PLAYING 装备 row, research 04

golden (matches only; each traced equip by equip against the parent — the first change of state is a bot's, or the
AI 托管 human seat's, targeted consumable on a full carrier destroying its oldest item): solo-FUNNY-1 (r9 ai_0 随身身份牌),
solo-FUNNY-2 (r9 ai_0 寻呼模块), solo-HARD-2 (r9 ai_0 随身身份牌, r12 简易通讯机), coop2-NORMAL-3 (r9 ai_1 随身身份牌),
coop3-ABYSS-5 (r11 ai_1 随身身份牌), coop4-FUNNY-6 (r4 ai_1 随身身份牌), solo-HARD-9-boosted (r14 ai_0 随身身份牌),
coop2-ABYSS-10-boosted (r13 ai_0 随身身份牌, r14 ai_1 简易通讯机), coop2-NORMAL-14-standins (r9 ai_0 随身身份牌; now won,
14 rounds), coop2-NORMAL-70-diy (r14 h_0 随身身份牌); the bots' free-slot carrier for target-agnostic consumables moves
no scenario by itself; roster / bonds / fields / standins / diy unchanged
2026-10-07 18:03:53 +08:00
sganggs 1e58843fb4 feedback6: merge R21F — enemy flyers hover 1.3 tiles above the road instead of climbing each raised tile (GitHub #277, @FrogThai); enemy animation states from PR #275 by @xcdoge, client part: numbered skill clips, the Stun_1 / Dizzy_* spellings, run cycles (猎狗pro, 深池侦察犬), the rebirths of 巨大的丑东西 and 自在 (data/assets.json regenerated offline: enemies only); golden unchanged 2026-10-07 18:03:47 +08:00
sganggs 76a2db7dd0 feedback6 R21F: enemy animation states, the client part of PR #275 by @xcdoge re-implemented — the resolver gives an enemy every numbered skill clip (anims.skills; the caller's first index stays the primary, operators unchanged, 宴's PREFAB_SPINE_ROLES fix kept), the stun spellings Stun_1 and Dizzy_Begin/Loop/End, a separate run role (Run_Begin/Loop/End); the renderer walks an enemy faster than moveSpeed 1 on its Run cycle (猎狗pro, 深池侦察犬 ×2; [ASSUMED] threshold), swaps an enemy's skill clip on a cast event (UnitView.setSkillSlot; a form in force is kept), and plays the 重生 of 巨大的丑东西 (Revive, then the fleeing 大祭司 Idle_2 / Move_2 / Stun_2) and 自在 (Revive_01); data/assets.json regenerated offline: 18 enemies gain anims.skills, 6 anims.run, 3 a stun clip (巨大的丑东西, 斩胄之剑, 破胄之锤), nothing else; the sim's cast slot (a new event) is not part of it; golden: unchanged 2026-10-07 17:59:11 +08:00
sganggs 53ccf5d8fe feedback6: merge R21G — battle control messages that arrive while the sim loads or catches up (takeover, forced end, a duplicate start, pool, pause) are held and applied in order (PR #266 by @siruimei07, ported); golden unchanged 2026-10-07 17:57:18 +08:00
sganggs d0d59f4012 feedback6: merge R21C — the player's 自选 picks are listed in their bonds' member lists (dimmed until owned, ✕ when banned; a watched teammate's 自选 row opens its operator); golden unchanged 2026-10-07 17:55:35 +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 d84b961c80 feedback6 R21G: a b.start is registered as pending before the sim loads, so a b.end (takeover / forced, the first end counts), a second b.start of the same battle, b.pool and the solo pause that arrive during the load or the silent catch-up are applied to it in order once the Battle exists (they were dropped); a superseded authority is still built, the next prep's clear stops the preparation (PR #266 by @siruimei07, re-implemented on the current runner); docs/design/network.md §14 Client runner + b.end; golden: unchanged 2026-10-07 17:51:26 +08:00
sganggs 14df10a5a3 feedback6 R21F: an enemy flyer hovers FLY_HOVER above the road whatever tile it crosses (GitHub #277: one high-ground / forbidden block on its way lifted it 0.42 / 0.3 tiles and dropped it again like a step) — UnitView.sync keeps every enemy at z 0, operators and summons keep their tile top, the flyer's shadow lies on the tile under it (shadowZ) on the 2D and the 3D board; golden: unchanged 2026-10-07 17:49:51 +08:00
sganggs 41fd3c7e39 feedback6 R21C: the bond popup lists every 自选 pick of the player (m.private.diy, the V and VI slots) in each bond its operator carries — dimmed like an unowned member until a copy is owned (not bought, or not in the shop yet), ✕ like a banned member when all its bonds are off this match (m.private.diyBanned), one row per slot drawn as its normal form with the 「自选」 tag, a tap opening the operator's card; 在场 and the 成员 header count an unowned pick for nothing, the order rule is kept (the owner's report of 2026-10-07 「自选编队的干员在局内对应盟约展开的名单里没有显示出来」); a watched teammate's popup still lists only their 自选 pieces on the field (m.public sends no picks), and such a row now hands the unit's pick to the card (BondPopup onMember → the detail target's diy → resolveDetail) instead of opening the empty 甄选干员 slot's card; golden: unchanged (client) 2026-10-07 17:43:37 +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 783bd30afd feedback6: merge R21A — 突袭 may land on a teammate's half when both halves are occupied (two-helper 联防, Final Assault / Hidden Core pair; the owner's decision of 2026-10-07), Battle.onFieldBoard; DESIGN §26 / §26.1 (docs/history/0.2.1.md); golden as R21A's commit (boss-boss_2/3/4/5/6-pair, hidden-boss_8/10-pair, coop4-ABYSS-7) 2026-10-07 17:14:51 +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
sganggs ac6de8a12d feedback6: the i18n template test reads the app range from APP_VERSION like tools/i18n.mjs appRange (it hard-coded >=0.2.0; 0.2.1-dev writes >=0.2.1) 2026-10-07 16:51:35 +08:00
sganggs ee43fb7c14 feedback6: merge fb5-patch-pkg — from 0.2.1 on every release also ships an update zip (only the files changed since the earlier 0.2.x releases; the server checks the install against MANIFEST.json and deletes the files the new version dropped on its first start; manual download, no auto-update — the owner's decision of 2026-10-07); README English summary: both the update-zip sentence and the Languages line kept 2026-10-07 16:47:27 +08:00
sganggs 1303321407 feedback5: two render tests took 宴's S2 (index 1) from the real manifest as their "skill without an idle clip" — that was the kneeling clip of §25.22.9; they now use her S1 分神 (index 0, the same clips) and check that her S2 plays no skill clip 2026-10-07 14:43:29 +08:00
sganggs 1ca769ba16 feedback5: 阿戈尔's devour block count checked for 水月 (伏击客, base block 0) and converted members (community report of 2026-10-07) — not reproduced: he takes every marked unit's block and blocks with it, the prep card shows it; face to face the second member marks nothing back (PRTS 「不会向…“已将标记付与自身的单位”付与自身标记」); pin tests test/content/feedback5-egir-block.test.js, CHANGELOG 核实后不是问题, §25.22.10; golden unchanged (tests and docs) 2026-10-07 14:32:29 +08:00
sganggs caee1dbed9 feedback5: 宴 stands during 落地斩·破门 — her one unnumbered skill set (Skill_Start / Loop / End) is S1 分神's sit-down rest, and the by-name resolver gave it to S2 too, so she knelt through the opening seconds of every battle (the owner's playtest of 2026-10-07); tools/assets/spine.mjs PREFAB_SPINE_ROLES now also fixes operator models by character id (front and back): 宴's S2 plays her ordinary clips (via 'attack'), S1 keeps the rest; data/assets.json rebuilt offline (only her entries changed); test/feedback5-utage-anims.test.js; CHANGELOG 界面, §25.22.9; golden unchanged (client art only) 2026-10-07 13:28:12 +08:00
sganggs b942ff2e71 feedback5: the boss-field browser test survives the bots' re-draft — its game-time safety net 600 → 1200 s (the Hidden Core b1 board clears at ~511 s, its 催泪瓦斯 copy at ~619 s since GitHub #232 re-drafted seed 22's earlier rounds) and the 奥术 check also counts the heavy-hitter copy (洛洛 + 深靛 = 奥术 2; the bots stopped drafting it); every other check unchanged; golden unchanged (test only) 2026-10-07 13:08:44 +08:00
sganggs 11fd65a5a5 feedback5: merge R19E — every enemy finishes its attack clip after a strike before it moves on (PRTS 状态机: ATTACK → MOVE after the attack ends; the 鸭爵 swap's 流泪小子 no longer walks off on its strike tick, community report and GitHub #214), and the 鸭爵 strategy's swapped-in 流泪小子 hides again 1 s after a block ends instead of 0 s (the owner's decision of 2026-10-07, a deliberate deviation for that copy only); golden as R19E's commits (216 scenarios + solo-HARD-2), the merged tree differs from the branch only in R19G's three 蕾缪安 scenarios 2026-10-07 13:07:21 +08:00
sganggs dd66adfbd1 feedback5 R19E: the 鸭爵 strategy's swapped-in 流泪小子 hides again 1 s after a block ends instead of the official 0 s — a deliberate deviation, the owner's decision of 2026-10-07 (「要不等待个1秒这样再重新隐匿」); a separate commit the integrator can drop; golden: 1 scenario moves (matches solo-HARD-2)
content/enemies/archetypes.js stealth: an enemy spawned with the band's swap tag 'duck' (content/bands/meta.js
duckReplace) gets its 隐匿 back no sooner than DUCK_STEALTH_RESTORE (1 s, content/enemies/helpers.js) after a block ends
— in practice 流泪小子 (enemy_2034_sythef_2), the only one of the four swaps with 隐匿, officially 0 s (PRTS 流泪小子
「隐匿(解除阻挡0秒后恢复)」). The same enemy anywhere else keeps 0 s: the bounty card's 流泪小子 (enemy_2034_sythef), an
untagged spawn; a 3 s 隐匿 stays 3 s; a copy leaked into 联防 keeps its tag and the 1 s. After each strike (its stunned
blocker lets go) it is now revealed through its 0.8 s post-strike stand and 0.2 s of walking.

Measured, 8 seeds each — leaked / HP left / revealed s per battle; W = 3 elite melee in a lane + an elite sniper vs the
R6 wave's ground enemies with one swapped 流泪小子, B = 8 elites on 战场#01 vs the whole R6 wave with one swap: before
the clip fix W 5/8, 42 %, 2.3 / B 8/8, 47 %, 3.2; after it W 5/8, 31 %, 2.6 / B 8/8, 58 %, 2.5; with the 1 s W 4/8,
31 %, 4.0 / B 8/8, 56 %, 5.5. Options for the owner (measured on the fixed engine, not built): 2 s W 4/8, 31 %, 5.4 /
B 8/8, 46 %, 8.5; 3 s (the general 隐匿 rule) W 4/8, 31 %, 6.4 / B 8/8, 39 %, 11.5; a 1.5 s stun on the copy (below its
2 s interval, so its blocker takes it over again) W 4/8, 2 %, 4.0 / B 4/8, 6 %, 5.5; a 1 s stun: knocked out in all 16;
the 1 s delay + a 2 s stun W 4/8, 21 %, 5.1 / B 5/8, 26 %, 8.1. Worse: half speed while 隐匿; a stunned operator that
keeps blocking it (pins that operator for good).

Golden: matches solo-HARD-2 — its bot holds 鸭爵; the swapped 流泪小子 of round 13 is free and revealed for 49 ticks in
its 1 s windows (the round-12 one is never released by a block), so the match parts at round 13 (a victory instead of
a defeat); the other 282 scenarios unchanged.

Tests: test/content/feedback5-duck-restealth.test.js (3; the swap's 1 s and the band path fail on the parent, the 0 s
guard passes on both); enemies_bosses, feedback2-surtr-stealth, feedback1-ducklord, feedback5-attack-clip-rest pass.
Docs: CHANGELOG 0.2.0 有意与官方不同的调整 (and the 核实后不是问题 line points to it), docs/history/0.2.0.md §25.22.6,
docs/PLAYING.md, docs/SIM.md, design/engine.md.
2026-10-07 12:58:06 +08:00
sganggs ef25c03525 feedback5 R19E: an enemy finishes its attack clip after its block ends — the 鸭爵 swap's 流泪小子 no longer walks on the tick its strike stuns its blocker (community report of 2026-10-07 「哭狗瞬间隐匿没有后摇」, GitHub #214 by @FrogThai); golden: 216 scenarios move
ai.js enemyAttack set the post-strike stand only for an unblocked ranged enemy (`!e.blockedBy && radius > 0`), so a
melee enemy released by its own strike walked on that very tick. 流泪小子 (enemy_2034_sythef_2, the strategy's version;
「泪眼汪汪」 / 「哭狗」 in the reports) stuns its blocker with every hit, the stunned blocker lets it go and its 隐匿 is
back 0 s later: on 0255afd it walked off the tick of each strike (four non-attacking walls in a lane: 8 stuns, 19.8 s
隐匿 / 9.0 s revealed, leaked at 28.9 s). PRTS 状态机: an enemy's ATTACK state 「每帧检查异常状态…攻击结束后回退到MOVE状态」
and COMBAT 「逻辑同ATTACK」 — only a character's COMBAT 「检测到不存在阻挡对象时强行切回IDLE状态」 — so an enemy finishes its
attack when its blocker goes. Now every enemy stands for the rest of its clip after a strike (attackStand; a blocked one
never walks, so it shows only when the block ends meanwhile: its blocker stunned or knocked out by that strike, or
gone); a stun / freeze / sleep / 浮空, leaving the field and, new, a displacement (失衡, Battle.displace) end the stand.
流泪小子 now stands 0.8 s (its 1.567 s clip, strike at 0.767), 隐匿, and a blocker whose stun ended often takes it over
again: the same lane 13 stuns, 29.1 s 隐匿 / 12.8 s revealed, leaked at 42.0 s.

Checked and official, unchanged: a stunned operator blocks nothing (gamedata_const ba.stun 「无法移动、阻挡、攻击及使用技能」,
PRTS 异常效果 STUNNED 「无法攻击、释放技能、阻挡敌人类单位」 — the keeps-blocking hypothesis is wrong); 隐匿 back 0 s after a
block (PRTS 流泪小子); moveSpeed 0.8 × the level's moveMultiplier 0.5, interval 2.0 s, stun 3.5 s, MELEE (enemy_database;
PRTS 盟约记录 鸭爵 备注: 4500 HP, 3.5 s stun, 隐匿 kept); the cooldown runs on the walk, so a new blocker sees the swing at
once and the strike after the 0.767 s wind-up; a bot teammate's 鸭爵 swaps into a human's battles, the Final Assault and
the Hidden Core too (「你和队友遭遇的部分敌人」), on the replaced enemy's route.

Golden — traced in lockstep against a copy of the parent: in each of the 199 battle scenarios the first differing tick is
an enemy standing out its clip after a strike where the parent walked on; every moved match has such stands in an
earlier or the same round. roster 41 of 49 (all but -003, -005, -009, -018, -019, -025, -035, -049); bonds 21
(deputShip-low, emptyShip-low / -high, indomShip-low / -high, investShip-low, kazimierzShip-low / -high,
kjeragShip-high, lateranoShip-high, miraShip-high, raidShip-low, sargonShip-high, siracusaShip-low, soloShip-low /
-high, suntShip-low / -high, swiftShip-high, visiShip-low, yanShip-low); fields 13 (all but boss-boss_1-solo,
boss-boss_2-pair / -solo, boss-boss_6-solo, boss-boss_7-pair / -solo, hidden-boss_8-solo, hidden-boss_10-solo,
unite-1); matches 17 (all but solo-HARD-9-boosted); standins 10 of 10; diy 114 of 138 (all but -011, -012, -018, -020,
-025, -027, -029, -031, -033, -047, -053, -077, -080 … -082, -086 … -088, -091 … -093, -098, -108, -123). The
displacement rule alone moves one roster scenario.

Tests: test/sim/feedback5-attack-clip-rest.test.js (5; the four behaviour tests fail on the parent, the data pin passes
on both); test/sim (745), test/content + feedback1-ducklord (2030), test/match (593) pass. Docs: CHANGELOG 0.2.0 规则
(按官方) and 核实后不是问题, docs/history/0.2.0.md §25.22.6, docs/SIM.md, design/engine.md, DATA.md.
2026-10-07 12:56:12 +08:00
sganggs d014b9ff0b feedback5: merge R19D — 5-阿戈尔 revives: the members the battle-start devour knocks out revive by board position once every devour pass is over (community report; replaces §24.3's knock-out order for that batch; scan 「左下到右上」 = columns from the left, bottom first [ASSUMED]); bond HP before the devour and one 5000 物理 (DEF) per mark confirmed official; golden unchanged 2026-10-07 12:46:03 +08:00
sganggs 31cdd9d072 feedback5: merge R19F — 拉普兰德 / 赫默 layers in the 整备区 are official (拉普兰德: only to an active 叙拉古, once per round per copy; 赫默: deployed only, character_target_inboard) — pin tests, PLAYING §6, CHANGELOG 核实后不是问题; golden unchanged 2026-10-07 12:40:00 +08:00
sganggs 2b0dfceabd feedback5 R19D: 5-阿戈尔 revives — the members the battle-start devour knocks out revive once every devour pass is over, by board position (columns from the left, bottom first: the [ASSUMED] reading of the community report's 「左下到右上」), not in knock-out order; later knock-outs take the slots left in time order, uneaten members none (community report relayed 2026-10-07); golden: unchanged
The report's steps 1-2 were verified and hold: the bond HP is on every member before the devour (an elite 深巡,
2904 HP / DEF 655, stands its 4345 from 15 layers on), and each mark is one 5000 物理流失 less DEF (PRTS), so a member
in the middle of a chain is marked by every 阿戈尔 behind it — that is what knocked out the reporter's 蓝蒂 / 小鲨.
Golden unchanged: the corpus's only 5-阿戈尔 battle (bond-egirShip-high, 999 layers) has no devour knock-out.
DESIGN §25.22.5.
2026-10-07 12:32:33 +08:00
sganggs 522f6287bb feedback5 R19F: community report 「小拉和赫默有概率在备战区叠不上叙拉古和远见」 checked, not a bug — 拉普兰德 stacks 叙拉古 from the 整备区 whenever 叙拉古 is active (it counts deployed 叙拉古 only, her bench copy is not one of the three) at her first manual refresh of the round; 赫默's trait has no 「此干员在整备区时也有效」 and the official data marks it deployed-only (conditionkey character_target_inboard); the 临时整备区 is not the 整备区. No code change: pinned by test/match/feedback5-bench-traits.test.js (the official data rule and the report's cases through the match paths), PLAYING.md §6 says where a 特质 works, CHANGELOG 核实后不是问题, DESIGN §25.22.7; golden unchanged 2026-10-07 12:30:58 +08:00
sganggs 6b05295fab feedback5: merge R19G — 蕾缪安's S3 waits with its bullets and locks when nothing is in her range instead of ending (skill text 「打完后结束」, PRTS 卫戍协议/帮助 「通常不会自动关闭技能」; community report); golden as R19G's commit (roster-018, boss-boss_3-pair, coop2-NORMAL-14-standins), the merged tree's golden equals the branch's 2026-10-07 12:29:01 +08:00
sganggs b87848a443 feedback5 R19G: 蕾缪安's S3 no longer ends by itself when nothing is in her range — it keeps its bullets and locks and locks the next enemy that comes; the bombardment follows only when the bullets are spent (community report); golden: 3 scenarios move
Seen (community report 「蕾缪安3技能范围里没人好像会自动结束」, relayed by the owner): with S3 locking, the locked enemy
killed or walking out of her range and nobody else in it, the skill ended at the next lock tick — the shells fell at
once and the bullets left were thrown away (repro on 0255afd: 3 of 5 bullets lost; a walker leaving her range, 1 lost).
Cause: chess_char_6_01-lemuen.js:169 `if (!e) { if (m.lemLocks.length) skill.end('ammo'); return; }`, there since the
initial import with no decision behind it.
Official: 「攻击装有5发弹药,打完后结束(可随时停止技能)」 — an ammo skill ends when its bullets are spent or the player
stops it; PRTS 卫戍协议/帮助 技能操作 「通常不会自动关闭技能」 (only 玛露希尔's 召唤使魔 is closed automatically); the client
(charpack char_4193_lemuen, buff_template_data lemuen_s_3): the S3 lock is an attack that needs a target and the skill
buff switches to the bombardment mode on ON_BUFF_FINISH only.
Now: with nothing to lock the skill waits (bullets and locks kept, the marks following their enemies or staying where
they left), its lock ready, so the next enemy in range (or 通缉) is locked on the next tick; it ends when the bullets are
spent and the shells fall on every mark in lock order as before. The S3 'lock' fx carry `hold`: render/fx/locks.js keeps
those reticles while the shooter's skill bit (UF.SKILL) is on and starts their LOCK_T at the skill's end (they faded 5 s
into a wait otherwise); S2's aim lock keeps its timeout.

Golden — traced on both trees (SkillRuntime start / end, the round's fields, the carried SP); in each the first
divergence is an S3 the parent ended with bullets left and nothing in her range:
- roster-018: the elite 蕾缪安's S3 of 7.63 s ended at 9.63 s with 2 of 6 bullets left; now the 6th goes at 12.00 s
  (first differing snapshot window 0–10 s).
- boss-boss_3-pair: her S3 of 27.8 s ended at 30.3 s with 4 of 9 left; now all 9 by 34.43 s (window 30–40 s); the boss
  now falls at 199.53 s instead of the 200 s cap.
- coop2-NORMAL-14-standins: ai_0's 蕾缪安 in round 11 ended S3 at 17.2 s (6 of 8 left) and 77.97 s (7 of 9); now she
  spends them, enters the 联防 with 25.96 SP instead of 10.27, casts S3 there and kills one more of h_0's leaked enemies:
  h_0 loses 1 LP less (rounds 11–12 LP 18 → 19, 8 → 9; lpLost 30 → 29; ai_0 kills +1).
bonds, standins, diy unchanged.

Tests: test/sim/feedback5-lemuen-s3-wait.test.js (3; the killed target and the walker who leaves fail on the parent),
test/render/fxproj.test.js +1 (a held lock waits while the skill bit is on; fails on the parent renderer).
Docs: CHANGELOG 0.2.0 规则(按官方), docs/history/0.2.0.md §25.22.8 (also notes, unchanged: S2 spends a bullet on every
normal attack where PRTS says only the 通缉 snipe does — left to the owner).
2026-10-07 12:19:55 +08:00
sganggs 818d070668 feedback5: the Japanese game texts keep what the JP client writes like the Chinese — build-i18n's ja test is 'native' (a text identical to the Chinese is the client's own when every Han character of it appears in the client's translated texts: 炎 / 不屈 / 助力 / 速射手 stay, 甄选干员 is still untranslated), so the bonds 炎, 不屈 and 助力 no longer show their English names in a Japanese interface; data/i18n/ja.json rebuilt (97.5 %, bonds 100 %) and zh-TW.json (the UI pack's emote names); the CJK font stack follows <html lang> (Japanese kanji, Traditional Chinese, a Korean face); the lobby's difficulty lines drop the JP bullet ・ too; golden unchanged 2026-10-07 12:11:19 +08:00
sganggs d0fc57ff4c feedback5: merge UI-TW — the Traditional Chinese interface (all msgids converted with OpenCC cn → twp, the official TW terms, a manual pass) and the machine-translation mark (_meta.machineTranslated → the pack index → a note under the language switch in 设置); golden unchanged 2026-10-07 12:07:07 +08:00
sganggs c11ba03da4 fb5 UI-TW: the machine-translation mark — _meta.machineTranslated: true, a new optional manifest field of a language pack (docs/PACKS.md): shared/i18nPacks.js langFields reads it (true or false), shared/packs.js normalizeManifest warns about a value that is not a boolean (read as false; the pack still loads) and packIndexEntry passes it into the index entry like complete (only when true), so the client's registry has it from the index (langMetaOf → registerLangs → langInfo) or from the pack's own _meta without one; 设置 shows a note under the language switch while the CURRENT language's pack has it (ui/lang.js machineTranslationNote, msgid 「当前语言的界面文字为机器翻译,可能不够准确,欢迎在 GitHub 上指正。」 — English in en.json, 目前語言的介面文字為機器翻譯… in zh-TW.json; ja / ko leave it to the integrator); tests: test/i18n-packs.test.js (the field from the manifest through the index to langInfo, the warning, the shipped zh-TW manifest, the note shown / hidden by language), test/ui/i18n.e2e.test.js (the shipped packs' own UI strings read from their files — zh-TW now 開始 — and the 设置 note, none in Chinese); docs/I18N.md says how the zh-TW pack is made (OpenCC twp, the official TW terms, a manual pass; a later msgid the same way) and that the ja / ko strings are machine translations open to corrections (edit public/i18n/<code>.json, node tools/i18n.mjs check <code> --strict) 2026-10-07 11:47:09 +08:00
sganggs 8b780c1b5b feedback5: merge R19A — GitHub #232: a stunned or frozen enemy is blocked by contact where it stands (an operator redeployed beside a frozen 隐匿 enemy blocks it and reveals it; 沉睡 / 浮空 / 恐惧 / 不可阻挡 still refuse); golden as R19A's commit (52 scenarios: roster 15, bonds 5, fields 7, matches 9, diy 16 — each first diverges where a held enemy is blocked by a touching blocker with a free slot), the merged tree's golden equals the branch's 2026-10-07 11:36:02 +08:00
sganggs 93a45f733f feedback5: merge R19C — GitHub #235: the official 「作战结束」 result box (全员无伤! / 生命值减少 −N) and the three battle-over sounds at settlement, PR #112 by @Convey123 ported onto the 0.2.0 layout (test/ui/gameLogic.test.js: both streams' tests kept); golden unchanged 2026-10-07 11:31:55 +08:00
sganggs 9fc7e38a01 fb5-patch-pkg: an update build refuses a stage without node_modules or public/vendor when a base has them (a --no-install build would list every dependency file as removed and break each install it is applied to); the names no update deletes are split off in diffBases (left, named in the summary); test/update-package.test.js (9): the base-folder filters and the refusal 2026-10-07 11:31:36 +08:00
sganggs cefd1e7313 fb5-patch-pkg: every release zip carries MANIFEST.json (size + sha256 of each shipped non-art file, written after npm ci; the full, lite and update zips of a version list the same), and node tools/package.mjs --update --from <base>[,<base>…] builds Stronghold-Protocol-v<version>-update.zip — the full stage built as before, compared file by file with every base (an earlier full zip or its extracted folder; tools/package-update.mjs reads zips itself, zip64 included), shipping each file that is new or differs from at least one base plus MANIFEST.json and UPDATE.json (from, count, bytes, files, removed with each base's bytes); bases must be older, full (not lite or update) and distinct; the update stage gets the refusal and personal-info checks (sha256 values left out of the name scan); test/update-package.test.js (8), test/package.test.js expects MANIFEST.json in the zip 2026-10-07 11:23:55 +08:00
sganggs d6e40c7235 fb5-patch-pkg: the update package's boot step and install check (server/update.js) — before the server starts (runMain: npm start, launch.mjs, the Windows service's run-server.cmd, NSSM, systemd; launch.mjs also before setup) an extracted UPDATE.json is checked: malformed → logged and skipped; the install verified against MANIFEST.json, and a missing or different file the server or browser runs stops the start with the bilingual "download the full package" message (nothing deleted, UPDATE.json kept); else each removed file still holding a base's bytes is deleted (never a changed file, a player's pack, a symlink, a per-machine name or a path outside the install) and UPDATE.json becomes .update-applied.json; doctor gets a MANIFEST.json row; test/update-boot.test.js (10) 2026-10-07 11:23:42 +08:00
sganggs 9123e76509 feedback5 R19A: a stunned or frozen enemy is blocked by contact where it stands — an operator redeployed beside a frozen 隐匿 enemy blocks it and so reveals it (GitHub #232, @ccyl; the repro and the cause by @kukiC); golden: 52 scenarios move
ai.js updateEnemy returned on `stunned && !e.hidden` before the contact check (Battle._checkBlock), and 冻结 / 沉睡 / 浮空
set `stun` too, so a held enemy was never checked: an operator redeployed or deployed beside it, a slot freeing up or a
push / pull into contact with a stun all waited for the status to end (0.1.4 had it too). PRTS 异常效果: STUNNED / FROZEN
stop the enemy's moves and attacks and hold no 不可阻挡 (BLOCK_FREE), which SLEEPING / LEVITATE do; 术语释义 冻结 names no
block; 作战机制 §碰撞体积与位置识别: an operator deployed onto an enemy blocks it, a standing one included. The held branch now
runs the same check before it returns (no move, no attack, as before): _checkBlock still refuses 沉睡 / 浮空 / 恐惧 /
不可阻挡, an enemy held short of contact is blocked only once it walks in (the same point as without the status), and the
3 s 隐匿 window after a block's end is unchanged. A block the held enemy already holds is still not re-checked (a reborn()
重生 keeps its blocker, as in 0.1.4: noted as open in §25.22.1).

Golden — in each scenario the first divergence is a stunned or frozen enemy blocked during its status by an operator or
summon it touched with a free slot (traced one by one with an instrumented copy): roster-003, -014, -015, -016, -017,
-018, -019, -031, -036, -038, -040, -041, -045, -046, -047; bond-indomShip-high, bond-kazimierzShip-high,
bond-raidShip-low, bond-siracusaShip-low, bond-suntShip-low; boss-boss_3-solo, boss-boss_4-pair, boss-boss_7-solo,
hidden-boss_8-pair, hidden-boss_9-pair, hidden-boss_10-pair, unite-2; matches solo-FUNNY-1, solo-NORMAL-2, solo-HARD-2,
solo-ABYSS-1, coop2-NORMAL-3, coop2-HARD-4, coop3-ABYSS-5, coop2-NORMAL-8-serverrun, coop2-NORMAL-70-diy; diy-003, -004,
-026, -034, -035, -056, -057, -065, -066, -070, -071, -094, -095, -101, -102, -103. standins unchanged.

Tests: test/sim/feedback5-frozen-reblock.test.js (9; the four #232 cases and the 晕眩 / 冻结 capacity cases fail on the
parent). Docs: CHANGELOG 0.2.0 规则(按官方), docs/history/0.2.0.md §25.22.1, docs/SIM.md (§1.2 Blocking, stun, freeze),
docs/design/engine.md, docs/PLAYING.md.
2026-10-07 11:22:27 +08:00
sganggs f661a47773 feedback5 R19C: the official 「作战结束」 result box and the three battle-over sounds at settlement (GitHub #235; PR #112 by @Convey123, approved and never merged, ported by hand onto the 0.2.0 modules) — the box says only the viewer's own LP, 「全员无伤!」 or 「生命值减少 −N」; after a 联防 the number is the server's own per-player charge (m.public.uniteResult in the SETTLE view) and 「全员无伤!」 only when nothing got through; no box for spectator seats, eliminated players or the boss rounds; golden: unchanged 2026-10-07 11:21:24 +08:00
sganggs b4d5a72a43 feedback5 R19B: 干员调配 says plainly when its game data did not load — useData counts a /data file that never arrived (404, blocked, bad JSON: 'missing') as settled, so the tab drew an empty roster, the loadout import blamed the file (「这份数据在当前版本没有可用的调配」) and the 干员持有 / 自选编队 imports stored an empty list over the saved one; now missingGameData(tab) (chess.json, plus backups.json for 自选编队) shows DataMissing in place of the roster (which files, saved settings unaffected, reload, then the ad blocker and the network) and importRefusal(kind, ready) refuses every import before anything is parsed or applied, with the same words; three UI strings with English; GitHub #173; golden: unchanged (client only) 2026-10-07 11:13:25 +08:00
sganggs 7d97b80bfd feedback5 R19B: the round-start banner reads 观战中 to an eliminated player and to a spectator seat instead of 资金已到账 — the server pays round income only to the players still in (startRound runs ps.startRound for alivePlayers(), eliminate() zeroes funds and pendingFunds); phaseBanner takes the viewer { alive, spectator } from the match screen (a spectator seat has no row in m.public); the idea from PR #237 (not merged: it sits on the #189 / #191 stack); GitHub #236; golden: unchanged (client text only) 2026-10-07 11:03:28 +08:00
sganggs 13b52450d6 feedback5: the co-op browser test reads phase, funds, price, free refreshes and shop slots in one store snapshot when it checks the R refresh — two page reads could straddle the m.private that answers R and pair the new slots with the old funds, failing "host: refresh cost 6 !== 5" under the full pass's load (1 of 4 in full020c; the same check passes alone, "funds 6 → 5"); golden: unchanged (test only) 2026-10-07 06:28:50 +08:00
sganggs 2802a368c3 feedback5: the boss-field browser test checks 限伤 on a fixed heavy-hitter copy of its four fields (withHeavyHitters: the first player's first five operators become elite 焰影苇草, 洛洛, 深靛, 刺玫, 远牙 with a 维式重锤 on the same tiles, bonds recomputed at 999 — 精准 3, 维多利亚 3, 奥术 2), compared Chrome vs Node like the captured and 催泪瓦斯 copies; since CB3's 受到攻击时 change (5877800a) re-drafted seed 22 the bots' best leader hit is 141845, not ≥ 300000 (the old 663300 / 733317 came from a 维多利亚 + 精准 + 奥术 board the bots no longer draft); the cancel path is unchanged (37e7f002's four captures cancel the same 86 hits with the same digests on 2e83a6b's code); golden: unchanged (test only) 2026-10-07 06:28:50 +08:00
sganggs 2e83a6b977 feedback5: Japanese, Korean and Traditional Chinese ship — the official game texts of the JP / KR / TW clients (data/i18n/ja.json 96.5 %, ko.json 97.4 %, zh-TW.json 91.1 % of 22 114 texts, built with build-i18n --lang from ArknightsAssets/ArknightsGamedata) and minimal UI packs public/i18n/ja.json, ko.json, zh-TW.json (a _meta manifest, no UI strings yet): ja / ko fall back to the English UI, zh-TW to the Simplified Chinese UI (no fallback; numbers in 萬 / 億); the owner's decision of 2026-10-07; UI translations welcome from the community; golden: unchanged (client text only)
- The packs: _meta = type lang, the code, its own and English name (日本語 / Japanese, 한국어 / Korean, 繁體中文 /
  Traditional Chinese), version 0.2.0, app >=0.2.0, authors, credits (the official client data, © Hypergryph (/ Yostar
  for JP and KR), via ArknightsAssets/ArknightsGamedata), fallback ["en"] for ja / ko and [] for zh-TW; formatted as
  `node tools/i18n.mjs template` writes them, so a translator runs it on the shipped file and keeps the manifest.
- Built offline from the tables W5AD downloaded and checked today (jp / kr 51.10.0, tw 51.2.0; copied into
  .cache/gamedata-<code>): coverage as W5AD measured; `build-i18n --lang <code> --check` up to date for en, ja, ko,
  zh-TW. `node tools/i18n.mjs check --all --strict`: 0 errors (en complete; ja / ko / zh-TW 0 of 1022 msgids, fallback).
  `node tools/packs.mjs list` lists the four packs with their game texts; `tools/package.mjs --dry-run --list` ships
  data/i18n and public/i18n of all four and the generated packs/index.json.
- With five languages the menu is a list (ui/lang.js SEGMENTED_MAX 4, W5AD's rule): test/ui/i18n.e2e.test.js reads and
  picks either form, expects the shipped languages, and checks each new pack in the browser (its official game text,
  the fallback UI, <html lang>) — SP_E2E=1: 3 / 3; the title page of the five devices (devices.e2e "title page") still
  fits: 5 / 5.
- Docs: docs/I18N.md (intro, §2, §5 "Shipped packs" with the call for UI translations), docs/PLAYING.md (语言),
  DESIGN §25.20 and the §25 intro's decisions of 2026-10-07.

Gate: non-browser suites 5024 / 5024 (test/i18n*, test/package, client-static 358 / 358), npm run golden ok,
test/golden.test.js 9 / 9, lint 0 errors, check:imports ok, typecheck ok.
2026-10-07 04:16:59 +08:00
sganggs 9738bb829a feedback5: 乌尔比安 knocked out while his S3 has moved him lies and redeploys on his deployment tile, not on the anchor tile — the owner's decision of 2026-10-07 on community report 28 「乌尔比安3技能期间死亡会留在3技能位移后的位置复活,应回到初始部署位复活」, a deliberate deviation from PRTS's "where it fell" for this 【移动】 only; golden: unchanged (the corpus moves him 23 times and knocks him out 6 times, never while moved)
- server/sim/units.js `downAtHome` (false), cleared by every deployment (battle/deploy.js _deploy).
- kits/ops/chess_char_5_05-ulpia.js sets it once the S3 【移动】 has put him on the anchor tile; onEnd clears it when the
  skill ends with him standing (the 【返回】); knocked out, it stays for the body.
- sim/battle/tiles.js _layBody: a unit holding it lies on its home tile (his board placement, where the 从不混淆的方向
  stood) when that tile is in the rect and free — else where it fell [ASSUMED], the PRTS exception's one attempt; the
  timed redeploy, 不屈's and CB1's 复活 (M3茧甲 / 埃芒加德: at once, free) all come back there (restTile), b.snap
  `down` names it. Every other moved operator (a 突袭 jump, other kits' 【移动】) keeps "where it fell".
- Test: test/sim/feedback5-ulpia-revive-home.test.js (3) — knocked out during S3 he lies at home, the anchor tile free,
  and redeploys there; revived at home by M3茧甲; control: after the 【返回】 and for a 突袭 member the PRTS rule holds. The
  first two fail on the parent (he lay and stood up on (10,7)); the third fails there only on the missing field.
- Docs: DESIGN §25.17.3 (the decision, marked as the owner's deviation; the §25 intro's decisions of 2026-10-07),
  docs/SIM.md §1, DESIGN §5 (design/engine.md DP / knocked-out line), docs/PLAYING.md 作战 row.

Gate: non-browser suites 5024 / 5024, npm run golden ok, test/golden.test.js 9 / 9, lint 0 errors, check:imports ok,
typecheck ok.
2026-10-07 04:04:41 +08:00
sganggs 9ca52ba798 feedback5: merge CB1 — community reports (bonds / strategies / items): a pair of colds on an enemy becomes the freeze and leaves no cold (the 谢拉格 wind no longer freezes for good), a 复活 (埃芒加德's 命结之秘, M3茧甲) is a knock-out and an immediate free redeploy where the operator lies (砾's and 瑕光's 被击倒时 / 部署时 layers fire), 佩佩's special refresh is paid, the result card hides the layers of 调和 / 协防干员 / 独行 / 绝技, the 炎佑 keeps off 外勤医疗's slot, 凯瑟琳's 定向投放 offers every shop item; 烛煌's 绝处重燃 before the hammer's lock and the 寻呼模块 / 简易通讯机 tier cap kept as they are (the owner's decisions of 2026-10-07); §25.15 → §25.21 (§25.15 is the shortcuts'); golden: vs feedback5 CB1's own rules — roster-005/009/010/012/014/015/016/018/026/029/031/033/036/040/042/046/047/049, bond-egirShip-high, bond-indomShip-low, bond-kjeragShip-high, bond-maniShip-high, bond-raidShip-low, bond-steadShip-high, bond-suntShip-low, boss-boss_2/3/4/6-pair, hidden-boss_8/9/10-pair, standin-07, matches solo-FUNNY-1, solo-NORMAL-1, solo-HARD-1, solo-ABYSS-1, coop3-ABYSS-5, coop4-FUNNY-6, coop4-ABYSS-7; vs CB1 what feedback5 changed since its base (CB2, CB3, CB4, CB5) plus roster-014
Conflicts resolved by hand:
- server/sim/content/items/battle.js: CB3 had extended `revivedInPlace` (an in-place 复活 restarts a deploy-timed
  skill, item 44); CB1 replaced the in-place revive by PRTS's form — `reviveNow`, a `death` hook that redeploys the
  operator at once, free, where it lies — and removed `revivedInPlace`. CB1's side is kept: its redeploy resets the
  skill, so an `activateOnDeploy` skill starts anew by itself; CB3's tests (test/sim/feedback5-raid-revive.test.js:
  the jump at once after M3茧甲 / 埃芒加德, the window back to full, 砾's fresh barrier) pass on it unchanged. Their
  header, bonds_core's comment, DESIGN §25.17.5 say so.
- docs/SIM.md, docs/design/engine.md: CB1's `fatal` rows (the 复活 are `death` hooks now); the `death` rows also say a
  deploy-timed skill starts anew (§25.17.5).
- data/choices.json: no conflict; `node tools/build-data.mjs --offline` on the merged tree rewrites all 15 data files
  byte-identically, and the JSON compare with feedback5 shows only pools.pool_equip_kathe.maxTier removed (CB1).
- docs/history/0.2.0.md: CB1's section renumbered §25.21 (its §25.15.1–10 and two self-citations; no citation of it
  elsewhere), placed last; the owner's decisions of 2026-10-07 on items 5 and 45 recorded there, in the intro and in the
  two pin tests' headers (feedback5-blaze-hammer, feedback5-cb1-pins).

Golden: solo-FUNNY-1 (outside CB1's list) has 6 埃芒加德 revives and 85 freezes on feedback5's path (instrumented).
roster-014 differs from CB1's own digest by 玛恩纳's 无动于衷: CB3's rule (every enemy damage instance) answers the
萨卡兹枯朽战车's pollution that hits a 卡西米尔 operator in CB1's timeline — with that counter limited to attacks the merged
roster-014 equals CB1's digest exactly (checked).

Gate: non-browser suites 5021 / 5021, npm run golden ok, test/golden.test.js 9 / 9, lint 0 errors, check:imports ok,
typecheck ok.
2026-10-07 03:54:35 +08:00
sganggs d841d6ac22 feedback5: merge CB3 — community reports (operator kits): 砾's normal attack hits twice at 50 % 伤害倍率 (a 频次 enemy loses 2), 乌尔比安's S3 moves only onto his own board (never behind the one-helper 联防 map's red gate nor onto a boss field's other half), the 「受到攻击时」 counters answer every enemy damage instance (菲莱 S2 on 深溟巢涌者's pulse, 星熊, 泡泡, 刺玫, 余, 玛恩纳, 年, 斩业星熊), an in-place 复活 restarts a deploy-timed skill so a 突袭 member jumps at once, 银灰's normal attack plays its own impact (and 雷蛇 / 初雪 / 圣约送葬人 drop a skill mode's sound); five reports pinned; §25.17 between CB2's §25.16 and CB4's §25.18; data/assets.json lists 银灰's impact (p_imp_spear_n.mp3 fetched); golden: vs feedback5 CB3's own rules — roster-002/004/005/008/010/012/016/024/033/044, bond-indomShip-low/high, bond-kazimierzShip-low/high, bond-lateranoShip-low, boss-boss_2-solo, boss-boss_4-pair/-solo, hidden-boss_8-pair/-solo, hidden-boss_9-solo, diy-051, matches solo-FUNNY-2, coop2-NORMAL-3, coop4-ABYSS-7, coop2-ABYSS-10-boosted; vs CB3 exactly what feedback5 changed since its base (CB2, CB4, CB5)
The merge:
- server/sim/battle/players.js: CB3's onOwnBoard hunk is byte-identical to CB4's (git kept one); its comment and
  docs/SIM.md's onOwnBoard row now name 乌尔比安's S3 【移动】 next to the 突袭 landing (DESIGN §25.17.2 / §25.18).
- test/sim/facing-invariance.test.js: CB3's scenario setup (onOwnBoard off on the open field) and the CB4 merge's
  突袭 test (its enemy inside the board) merged cleanly, both kept.
- data/assets.json: CB3 had regenerated it offline without 银灰's entry (his official impact file was not on disk);
  `node tools/fetch-assets.mjs --add-only` (shared public/assets, add-only) downloaded p_imp_spear_n.mp3 — 8.8 KB,
  the only new file (ok 1, skipped 7968; the 117 misses are the known upstream gaps) — and rewrote the manifest.
  Field-wise JSON compare with CB3's manifest: only audio.sfx.units.char_172_svrash = { hit: p_imp_spear_n } plus hash
  and stats (files / bytes / sfxUnits +1); against feedback5: CB3's four operators (银灰 now the spear impact and no
  S3 swing, 雷蛇 / 初雪 / 圣约送葬人 without the skill-mode impact) plus hash / stats. §25.17.6 says so.
- docs/history/0.2.0.md: §25.17 placed in order, the intro's per-stream list and workstream list name CB3.

Golden moves outside CB3's commit list: coop2-NORMAL-3 fields 砾 from round 3 (her double hit) and 刺玫 in rounds 4-7
(instrumented); solo-FUNNY-1 (in CB3's list through the counters) fields no counter operator on feedback5's path, only
砾, whose two half hits change no kill, leak, LP or end stat there, so its digest stays.

Gate: non-browser suites 5003 / 5003, npm run golden ok, test/golden.test.js 9 / 9, lint 0 errors, check:imports ok,
typecheck ok.
2026-10-07 03:41:48 +08:00
sganggs 66cdf493fc feedback5: merge W5AD — language packs as the first type of a generic content pack: a language is a file in the language folder (public/i18n/<code>.json with a _meta manifest, optional data/i18n/<code>.json) or a pack folder (packs/<id>/pack.json); the server lists them live at /packs/index.json, the menu shows every pack, strings fall back pack → base → declared fallback → Chinese, broken placeholders are skipped, plurals follow Intl.PluralRules (zh / en unchanged); tools i18n.mjs template / check, packs.mjs list / index, build-i18n --lang ja|ko|zh-TW; the release zips ship packs/ and packs/index.json; docs/PACKS.md, docs/I18N.md §5; §25.16 for now (renumbered next); golden: unchanged vs feedback5; vs W5AD exactly what feedback5 changed since f1df0d3 (CB5's 18 bot matches, CB2's roster 13 / bonds 7 / fields 6, CB4's roster-016 / 7 boss fields / standin-04/06/08 / diy-028/124)
No conflicts outside docs/history/0.2.0.md; the §25 intro keeps one sentence per stream (W5AD's line that also named
the hotkeys' §25.15 joined to CB4's).

Gate: non-browser suites 4981 / 4981 (test/i18n-packs 12 new, test/package 1 new), npm run golden ok,
test/golden.test.js 9 / 9, lint 0 errors, check:imports ok, typecheck ok, docs-consistency + docs-paths 31 / 31.
2026-10-07 03:27:10 +08:00
sganggs 6ed3aed335 feedback5: merge CB4 — community reports (enemies / bosses): a 突袭 member lands only on its own player's board (never a boss field's hand / 临时整备区 rows nor the other half of a 联防 or boss field), a silenced 萨卡兹枯朽战士 leaves no 污染秽蚀, 萨卡兹穿刺手's acceleration ends with a stun or 束缚 and its first hit after a block adds move speed × 600 as its own instance, 自制投石机 ignores its block when it picks a target (no attack on the 排气格栅's hidden blocker), the briefing types' 7–9 waves, 新硎's 断刃, a freed prisoner in 联防, 鸭爵's 0–2 swaps and the moving leaders' routes pinned, four reports not reproduced; §25.18; golden: vs feedback5 CB4's own rules — roster-016, boss-boss_2/3/4/5/6-pair, hidden-boss_8/10-pair, standin-04/06/08, diy-028, diy-124, matches solo-NORMAL-1, solo-HARD-1, solo-ABYSS-1, coop2-HARD-4, coop4-ABYSS-7, coop2-NORMAL-8-serverrun; vs CB4 exactly what feedback5 changed since its base (CB2's roster 13 / bonds 7 / fields 6, CB5's 18 bot matches)
Merge fix: test/sim/facing-invariance.test.js — the 突袭 rotation check put its enemy on the board's top row (9, 9),
so the facing-RIGHT landing tile it expected, (8, 8), lies above the player's board, where CB4's onOwnBoard rule (the
official 再部署 goes where the player deploys; community reports 40 / 16.3) now refuses it; the member landed on
(10, 8). The enemy stands at (10, 6), inside rows 9–12 / cols 2–10, so all four diagonal tiles are candidates in every
direction and the test checks the facing tie-break as before. It failed on fb5-cb4 itself (the stream did not run the
file). The §25 intro's stream lines joined into one sentence again.

Golden moves outside CB4's commit list are its rules on feedback5's paths (instrumented): solo-HARD-1 and solo-ABYSS-1
now have silenced 枯朽战士 deaths (8 / 15) and 突袭 candidates the own-board filter refuses; coop2-ABYSS-10-boosted,
coop2-NORMAL-3 and coop2-NORMAL-14-standins (in CB4's list) have no silenced 枯朽战士 death on this path, and their
digests are identical with the own-board filter switched off (the refused tiles were never the chosen ones).

Gate: non-browser suites 4968 / 4968, npm run golden ok, test/golden.test.js 9 / 9, lint 0 errors, check:imports ok,
typecheck ok, docs-consistency + docs-paths 31 / 31.
2026-10-07 03:21:57 +08:00
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 3bfe17bd07 feedback5 CB1: item 20 follow-up — bot-smarter's 坎诺特 case no longer assumes the round-7 level-up costs 9
Seed 7's solo bot plays 佩佩 for rounds 1–6; with paid special refreshes (96794c5) it reaches level 3 a round later, so
the 3 → 4 upgrade at round 7 costs 10 instead of 9 and 14 − 10 leaves 4. The test now checks what it means — after the
level-up on the curve the bot spends nothing that takes it under the 5 capital — whatever that price is. No product
change; golden unchanged.
2026-10-07 02:46:59 +08:00