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.
This commit is contained in:
sganggs committed 2026-10-07 03:21:57 +08:00
commit 6ed3aed335
23 files changed
+1364 -598

No files matched your search

+198 -1
View File
@@ -31,7 +31,10 @@ upgrade, an eliminated player following a player through every round, the boss f
prep, the pair together in the boss prep with the official green frames; PRs #189 / #191 reused, not merged; the
battle-history and hotkey requests left to the owner) → §25.19; the community reports of 2026-10-06, stream CB2 (healers, summons, timers: 刺玫's S2 heals, 琳琅诗怀雅 healing herself and her 破财消灾 cost after a
redeploy, 赫默's drone at full SP, the countdown summons' 无敌 / 禁疗 / timer bar, stacked alchemy zones; the chain heal,
DoT damage, 伺夜's 狼影 and the 吟游者 trait answered) → §25.16.
DoT damage, 伺夜's 狼影 and the 吟游者 trait answered) → §25.16; the community reports of 2026-10-06, stream CB4 (enemies, bosses, waves, movement: the 突袭 landing on the 临时整备区 row and the other half of the
联防 map, a silenced 萨卡兹枯朽战士's death pollution, 萨卡兹穿刺手's speed after a stun and its first hit, 自制投石机 blocked on the 排气格栅; the briefing types'
7–9 waves, 新硎's 断刃, a freed prisoner in 联防 and 鸭爵's two swaps in one wave already answered; the moving leaders' routes
checked; 野鬃, 锏's pulls, 昆图斯's footprint and the leaders' attack rate not reproduced) → §25.18.
Decisions of the owner: 2026-10-04 — the server stays on plain `node:http` + `ws`, no web framework (§25.1);
2026-10-05 — the 补位 plan (§25.3); the 自选编队 rules, the collab operators out of the pool, ISW-A refused (§25.4);
@@ -1308,3 +1311,197 @@ the evidence.
trait is 生命回复速度, which 禁疗 and 无法被友方治疗 do not stop (§25.6.8): 狼群 440 → 532 and 斥罪 1480 → 1618 HP in 3 s
under 魔王 (pinned by `test/content/feedback5-regen.test.js`); 孤立 units stay out (PRTS 孤立). The countdown summons
cannot be refilled since §25.16.5.
### 25.18 Community reports of 2026-10-06, stream CB4: enemies, bosses, waves, movement — `sim/battle/players.js onOwnBoard`, `content/bonds/addon/battle.js raidTile`, `content/enemies/archetypes.js kitPolluted`, `content/enemies/special.js kitRush`, `targeting.js canTargetAlly`
The owner's second collection of community reports (2026-10-06/07) was split over five streams; CB4 took the items about
enemies, bosses, waves and movement (items 6, 10, 16.3, 24, 29, 35, 36, 38, 39, 40, 47, 52, 53, 57 of the list). Each was
reproduced on the 0.2.0 tree with a script first, then checked against the official data (enemy_database,
enemy_handbook_table, activity_table → act2autochess, the level files) and PRTS (备注 included) and the earlier decisions.
The real ones are fixed, one commit each with its golden scenarios named; the rest are answered with the evidence.
Normative text touched: §5.5 (design/engine.md: 自制投石机's exception to "a stealthed ally is attacked only by the enemy
it blocks"); docs/SIM.md (`onOwnBoard`, the 索敌不受阻挡影响 target rule, the silenced 枯朽战士); docs/PLAYING.md (the
briefing types' share of the waves).
#### 25.18.1 「…新约能天使在开了突袭之后蹦到了下方…临时放置溢出的干员和道具的那一栏高台」, 「单人联防时突袭也可以跑到对面的场地上」 (items 40, 16.3): 突袭 lands only on its player's own board — `sim/battle/players.js onOwnBoard`, `content/bonds/addon/battle.js raidTile`
- **Seen**: in a solo leader round a ranged 突袭 member (新约能天使 with the 转职球 and the 突袭手雷) jumped onto the
boss field's 临时整备区 row; in a 联防 with one helper a member jumped onto the right half of the map.
- **Cause**: `raidTile` took any tile of the battle rect its position may stand on (grid.canStand). BOSS_RECT holds rows
0–5, so the boss field's hand row 0 and 临时整备区 row 1 (tile_achand: high ground, buildable ALL) were landing tiles
for a ranged member (reproduced: an enemy on the left telin (1,3) of 战场#01 drew the member onto the hand tile (0,3));
UNITE_RECT spans both halves of the 联防 map (cols 0–20) while a lone helper's board is the left half (escaped_single's
deploy tiles: cols 3–9), and on a pair field a member jumped onto its partner's half.
- **Official**: the bond text 「保留技力立即再部署至一名地面敌人周围」 — a 再部署 goes where its player deploys; the stage data
lists each player's deploy tiles per half (data/stages.json `deployTiles`: normal, bossLeft, bossRight).
- **Now**: `Battle.onOwnBoard(ps, r, c)` — the board region (rows 9–12, cols 2–10) mapped onto the field as `mapTile`
maps the player's pieces (the right-hand helper's +8 columns, the boss rows 2–5, the mirrored right half) — and
`raidTile` takes only those tiles; a target only reachable from elsewhere is skipped (the next candidate is tried, else
the member stays and the next poll looks again, as before).
- [ASSUMED]: none beyond §22.2's landing rule (the official landing tile among the legal ones is not known).
- Golden: 8 scenarios, each a member that used to land on the other half (checked with the parent instrumented):
boss-boss_2 / 3 / 4 / 5 / 6-pair, hidden-boss_8 / 10-pair (members landing on the partner's half, 1–7 per battle) and
the bot match coop2-ABYSS-10-boosted (ai_0's members on the right half of its leader fields). Tests:
`test/sim/feedback5-raid-own-board.test.js` (4 cases; each fails on the parent). Docs: docs/SIM.md (`onOwnBoard`).
#### 25.18.2 「沉默效果没有沉默枯朽战士敌人,枯朽战士敌人被沉默之后死亡依然留下了毒」 (item 10): silenced at its death, 萨卡兹枯朽战士 releases no 污染秽蚀 — `content/enemies/archetypes.js kitPolluted`
- **Seen**: a silenced 萨卡兹枯朽战士 (组长) still left its poison zone when it died (reproduced: 150 HP in 3 s to its
blocker, silenced or not).
- **Official**: PRTS 萨卡兹枯朽战士 天赋 「{{特殊机制|死亡爆炸}}(释放半径2.0,持续8s的【污染秽蚀】)」; PRTS 特殊机制 死亡爆炸
「如无特殊说明,此能力默认可沉默…若不处于沉默状态,将会…释放」. The client agrees: the battle prefab's PollutedDie
ability is a buff of template `projectile_on_killed`, whose ON_OWNER_KILLED checks `CheckAbnormalFlag SILENCED`
(unset) before `EmitProjectile` — the same template as 高能源石虫's blast. Its handbook line alone is NORMAL (高能源石虫's is
SILENCE), so the rule "`sil` = the handbook's SILENCE lines" (content/enemies.js) missed it. An audit of all 243 enemy
prefabs of the local client (every ability's buff templates; those whose ON_OWNER_KILLED checks SILENCED: 11 enemies)
found one more NORMAL line of that kind — 刺胄之弹's blast, a part of 假想敌:胄 (not changed, for later: its blast is
triggered by its arrival); the other nine are SILENCE lines our kits already silence. 萨卡兹枯朽战车's 秽蚀轰击, also
NORMAL, stays unsilenceable (its skill node has `_ignoreSilence` 1).
- **Now**: kitPolluted's death ability is `sil`; the silence test of every authored enemy names the two keys as the
template exceptions.
- [ASSUMED]: none.
- Golden: 5 bot matches, each with silenced 枯朽战士 deaths (14–83 per match, counted instrumented): solo-NORMAL-1,
coop2-NORMAL-3, coop4-ABYSS-7, coop2-NORMAL-8-serverrun, coop2-NORMAL-14-standins. Tests:
`test/content/enemies_bosses.test.js` (the silence rule, the two keys silenced and after a silence ran out; 3 fail on
the parent).
#### 25.18.3 「每局游戏开始展示的敌人类型(折射、飞行等等),实际出现波次在7到9波,而且每个最多三波,其余波次用特异类型填充」 (item 6): already the official schedule — no change
- **Checked**: `setupMatchWaves` (research 08 §2.1, decoded from the client's `RandomEnemyGenerater`): each of the three
briefing types owns 3 of the 15 round slots, SPECIAL (特异) the other 6, shuffled, one type per round. R14 (the leader)
and R15 (the hidden core) take slots too, so the 13 normal rounds of 险境 / 绝境 / 终极 hold 7–9 type waves — 400 seeds
per mode: 7 in 141 matches, 8 in 192, 9 in 67; per type 1–3 — and every other wave is SPECIAL (solo 标准: 8 normal
rounds, 3–7). Exactly what the player describes.
- **Official**: act2autochess `specialEnemyRandomTypeDict` (count 3 per random type, SPECIAL −1), constData
`maxLevelCnt` 15, `specialEnemyNum` 3, `enemyTypeIdentifierToFillRandom` 1 (SPECIAL).
- **Now**: docs/PLAYING.md states it at 确认本局信息 (the report: 「更新日志和机制描述也没写」).
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js` (the 7–9 and the 1–3), `test/match/waves.test.js` (3 of
the 15 slots each).
#### 25.18.4 「敌人新硎提升攻击力的断刃好像无限消耗,实际应当攻击一次消耗一个,具体有几个复核」 (item 53): already fixed in 0.2.0 (§25.6.2, GitHub #107) — no change
- **Checked**: on v0.1.4 新硎's ATK went 2430 → 3510 → 4590 → 5670 and stayed (a layer per attack, none removed) — the
report. On this tree: 4 attacks at 2430 (+80 %), the 4th spends the last 断刃 and ends the bonus, the next swing comes at
once at 1350; killed, max(1, 4 − spent) 铁矛头 (沉沙: +70 %, 铜矛头).
- **Official**: PRTS 天赋 (4 【断刃】, one spent per successful attack); the client's template `enemy_dead_spawn[sfji]`
(battle prefab enemy_1207_sfji_2): ON_OUTPUT_ATK_OR_HEAL — while `cnt` ≥ 1, `cnt` += `cnt_add` (−1) and one blade marker
goes; ON_ABILITY_FINISH — `cnt` ≤ 0 ends the ATK buff and switches to mode 1 (无断刃模式); ON_OWNER_KILLED (not 坠落) —
summons `cnt` (at least 1).
- [ASSUMED]: the client spends a blade per damage output; here every attack spends one, so an attack an operator dodges
spends one too.
- Golden: unchanged. Pinned: `test/content/enemies_bosses.test.js` (the #107 test).
#### 25.18.5 「囚犯敌人的解放状态联防时不应继承」 (item 57): already answered (§25.14.1) — no change
- **Checked**: a leak re-enters 联防 as a new spawn — `planUnite` passes on its key, spawn mods, LP and bounty only, and
`buildUniteWave` spawns it — so `prisoner()` starts it confined (the 禁锢 buff, no form) and only its own attacks there
free it; the client drops every view when a battle starts. The freed look was 普通 / 老练囚犯's red clip set, drawn from
the gate until §25.14.1.
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js` (freed in its own combat, leaked, confined in 联防,
freed at its 4th attack there).
#### 25.18.6 「萨卡兹穿刺手被眩晕或者减速恢复之后移速不会重置(降低),伤害也异常」 (item 36): a stun or 束缚 ends its acceleration; its first hit adds speed × 600 — `content/enemies/special.js kitRush`
- **Seen**: after a stun it walked on at the speed it had built up (it even kept accelerating while stunned: 1 → 1.5 in a
2 s stun); its first hit after a block was one multiplied attack (×(1 + 6 × layers / 25), 2286 at 17 layers), also
after a stun that came in between.
- **Official**: PRTS 天赋 「每0.1秒检测一次:①若受晕眩/束缚影响,停止加速 ②若未被阻挡,开始加速…每0.5秒尝试获得1层移动速度+50%
的增益,最多尝试25次(增益于停止加速时解除…),同时普通攻击附加的Buff会额外造成一次当前移动速度×600的…物理伤害并停止加速」. The
battle prefab agrees: listeners every 0.1 s end `dlancer_t[trigger]` on STUNNED (a) or UNMOVABLE (b) and start it when
not blocked (c); the trigger stacks a MULTIPLIER move-speed layer every 0.5 s, blocked or not; the FirstAttack buff
`dlancer_t_atk` deals `DamageViaAttr` MOVE_SPEED × atk_scale (physical, melee, ignoreForSp) while the trigger exists,
then ends it. A slow (减速) is no reset — the report's slow is the official behaviour; it only lowers the speed while it
lasts, and so the extra damage.
- **Now**: kitRush follows the templates: a 0.1 s listener (晕眩 / 束缚 statuses end the acceleration and drop its layers;
not blocked starts it, from the spawn), a layer every 0.5 s up to 25 tries, the extra damage = its current move speed
× 600 as a second, non-attack physical instance with no 受击回复, ending the acceleration (so a block's first hit only).
Reproduced after the fix: 2 s stun → base speed, a fresh build-up; blocked at 2.375 → 450 + 1500 (2.5 × 600, one more
layer before the hit).
- [ASSUMED]: 冻结, 沉睡 and 浮空 do not stop it (they set FROZEN / SLEEPING / LEVITATE, not the two flags the listeners
read); the client's 0.1 s listener order is folded into one check.
- Golden: 6 scenarios, each with 萨卡兹穿刺手 in it: roster-016, standin-04, standin-08, diy-028, diy-124 and the bot match
coop2-HARD-4 (160 spawned). Tests: `test/content/enemies_bosses.test.js` (3: the layers and the cap, the resets, the
first hit; all fail on the parent).
#### 25.18.7 「玩家的官方原版反馈:「投石车」敌人如果被蒸汽地板上的干员阻挡会不进行攻击」 (item 24): 自制投石机's 索敌不受阻挡影响 — `targeting.js canTargetAlly / sortAllyTargets`, `ai.js attackTargets`, `content/enemies/special.js` (enemy_10162_mnctpt)
- **The enemy and the terrain**: 「投石车」 = 自制投石机 (enemy_10162_mnctpt, ranged 4.0, the 悬赏·特异III bounty); the 「蒸汽
地板」 = 战场#07 (下半)'s 排气格栅 (tile_smog: an operator on it is 隐匿 to enemy ranged attacks).
- **Seen here**: blocked by an operator on the smog, it attacked that operator — every enemy does (the engine's rule: a
blocked enemy attacks its blocker whatever its selectability, PRTS 索敌的概念 「…强行无视对方可选性发动攻击」).
- **Official**: PRTS 自制投石机 天赋 「…索敌不受阻挡影响,且不会因丢失目标而结束攻击」 — the blocker exception does not apply to
it, so a 隐匿 blocker is no target and, with nobody else in its range, it does not attack: the players' report.
- **Now**: the catapult's profile is `blockFree` (spawns.js gives every enemy the field): `attackTargets` takes the
allies in reach as if it were unblocked, `canTargetAlly` refuses a 隐匿 / 迷彩 blocker to it, `sortAllyTargets` puts no
blocker first (仇恨值: taunt, then the latest deployed). Every other enemy keeps attacking a 隐匿 blocker.
- [ASSUMED]: none for the rule. Not changed, for later: its stones' splash radius (PRTS 「目标半径1.5范围」, the data's
`projectile_range` 0.5 × 3; the kit uses 0.5), the 0.3 s between its three stones, and 「不会因丢失目标而结束攻击」.
- Golden: 1 battle — standin-06 (the bounty catapult, blocked by 忍冬, now shot the 斯卡蒂 / 瑕光 pieces by 仇恨值, its
blocker no longer first). Tests: `test/sim/feedback5-catapult-smog.test.js` (3: no attack on a hidden blocker alone, another operator
instead, every other ranged enemy still attacks its hidden blocker; the first two fail on the parent). Docs:
docs/SIM.md.
#### 25.18.8 「鸭爵策略的悬赏现在有时候会一波出现多只,比如多只鸭子」 (item 35): the official 0–2 swaps per wave — no change
- **Checked**: 鸭爵's “神秘顾客” (`round_start_all_player_change_enemy_2`: min 0, max 2, from round 5, the late part of the
wave — minweight 0.6 / maxweight 0.99) swaps 0–2 ground enemies of each player's wave, each into one of 鸭爵, 高普尼克,
流泪小子, 圆仔 at random (bands/meta.js duckReplace, once per player per battle — no second handler). 1000 real waves
(`m._normalOpts`, solo and co-op, rounds 5–12): 0 swaps 388, 1 swap 312, 2 swaps 300, never more; the two of a 2-swap
wave were the same kind in 81 of 300 (two of one kind in ≈ 1 wave in 12, two ducks in ≈ 1 in 50). A pair leader field holds
each player's 0–2 on its own half, and 联防 re-enters every leaker's leaked swaps (both as before).
- **Official**: PRTS 卫戍协议:盟约 下半/PRTS盟约记录 鸭爵 备注 「每回合将有0~2名敌人被替换为上述敌人之一」 — two ducks in one
wave is the official rule.
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js` (≤ 2 per wave, 0 / 1 / 2 and two of a kind all occur,
1 fund each).
#### 25.18.9 「会移动的关底boss在各个地图的移动路线复核下是否正确」 (item 29): checked on every boss field — no change
- **Checked**: the leaders that walk are 铳 (boss_2 / 9) and 卢西恩 (boss_5); the 巨型单位 (胄, 管, 昆图斯, 阿利斯泰尔, 萨米的意志)
are 自缚 (content/bosses.js SELF_BOUND). Their routes are the level files' (level_act1autochess_h07_02 route 6 and act2
h07_05: PATROL_MOVE (3,9) → (2,3) → (5,9), 卢西恩's list four such rounds with a MOVE (5,9) between them), walked with the
official SPFA flow field and looped by `patrolLoop` (back to the first leg instead of the goal). On all 8 boss fields
of the season, solo and pair, 240 s each: every sample on a walkable tile, the targets in the official order, the pair's
mirrored copy on (3,11) → (2,17) → (5,11) (its branch route), 卢西恩 restarting after its 19th checkpoint and never reaching
the goal (its lpr 30).
- Found, not changed: without the match's `waveId` (tests, tools) `templateOf` infers the template from the route list
only and can take another leader's; 卢西恩 then misses its patrol loop and walks to the goal. The match, the server's
headless fields and the browser battles always pass it (BattleSpec `waveId`).
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js`.
#### 25.18.10 「干员野鬃放在红门前两格的时候有概率会把怪顶出地图显示漏怪」 (item 38): not reproduced — no change
- **Checked**: 野鬃 (elite, S2 夹枪冲锋 kept running) two tiles before either red gate, facing it, on 战场#01–#08 against real
waves (912 battles, normal fields; 480 more with the solo leader fields), also on v0.1.4: her pushes (up to 30 a battle)
never left a ground enemy on a tile it cannot walk, and every leak happened at its route's end. `Battle.displace`
moves a ground enemy only over walkable tiles of the battle rect, so it stops on the gate tile at the field's edge;
planLeg then walks it back. What the rule does allow: an enemy she keeps pushing back onto the gate until the time
limit is counted as leaked (时间到仍存活的敌人算漏怪), as in the official game. A recording or the map and round would
settle what the player saw.
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js` (two real waves, three tiles before the gates).
#### 25.18.11 「怪物的重量以及干员的推拉力度还是有点不对,比如锏能拉动10重的关底boss」 (item 39): not reproduced — no change
- **Checked**: a leader (tag boss) is never displaced (`Battle._displaceable`); 锏's S3 pulls with 力度 1 (中力) and, at
its end, 2 (较大力): 受力等级 = 力度 − 重量 ≤ −3 moves nothing (PRTS 推与拉), so no weight ≥ 5 enemy moves either. 40 S3
casts next to each of the 10 leaders (weights 6–10): never moved; 自在 as a bounty (weight 10) not even by 特大力. The
one thing that looks like it: 卢西恩's 不祥幻影 has his model and weight 2, so 锏 does pull it (all the way, 受力等级 0).
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js`.
#### 25.18.12 「昆图斯占地少最左边和最右边两排,似乎变成3x3了」 (item 47): not reproduced — no change
- **Checked**: 昆图斯's hit area is PRTS' 「受击判定区域为长4.95宽2.95的长方形,向上偏移1.0」 (tools/build-data.mjs HIT_AREAS):
standing on (3,10) it occupies cols 8–12 × rows 3–5 (body.js bodyKeys); an operator whose range reaches only its
leftmost column (艾丝黛尔 on (3,7)) attacks it; the Final Assault prep lights the same 15 tiles in red on both boards
(headless screenshots of the render demo's Final Assault prep; render/pick.js hitTiles = bodyKeys, pinned by
`test/render/feedback3-leader-prep.test.js`). Its model is drawn at the official prefab scale.
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js`.
#### 25.18.13 「最终boss跟原版相比攻击欲望感觉低了,不怎么打人,复核」 (item 52): every leader attacks at its data interval — no change
- **Checked**: solo leader fields with eight walls on the board, 150 s: 胄 38 normal attacks (interval 4 s), 昆图斯 43 (3.5 s,
two targets each), 阿利斯泰尔 19 (8.2 s), 萨米的意志 25 (6 s) — each at its official interval from its first target on —,
their skills at their cooldowns; v0.1.4 gives the same counts (only the first strike now comes at the damage frame,
§25.7.2). 铳 opens at the PRTS minimum attack speed 20 (22.5 s) and gains +80 per attack on the same target (5 times),
so a fight that keeps switching its target sees few of its attacks; 管's normal attacks strike its 余音, not operators;
卢西恩 attacks only its blocker and blinks past it. A leader and a situation from the reporter would show what differs.
- Golden: unchanged. Pinned: `test/sim/feedback5-cb4-pins.test.js` (the four interval leaders at ≥ max − 1 attacks).