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 先兆者).
This commit is contained in:
sganggs committed 2026-10-08 20:21:19 +08:00
1 parent 4128965a9f
commit 895653fc10
4 files changed
+104 -75

No files matched your search

+22
View File
@@ -1098,6 +1098,28 @@ test(`${nm('enemy_1112_emppnt')} / 中枢: every attack is a shell that lands 3
}
});
test(`${nm('enemy_1112_emppnt_2')} / 先兆者: the shell's 1.2 circle takes every ally whose collider touches it — the impact tile and the 8 around it, not the cross (GitHub #364)`, () => {
for (const key of ['enemy_1112_emppnt_2', 'enemy_1112_emppnt']) {
// the enemy on (10, 8) reaches only the wall on (10, 6): the impact; the others stand around it, out of its reach
const h = arena({ units: [
{ chessId: 't_wall', row: 10, col: 6 }, { chessId: 't_wall2', row: 10, col: 5 },
{ chessId: 't_wall3', row: 9, col: 5 }, { chessId: 't_wall4', row: 10, col: 4 },
], captureNoisy: true });
h.step();
const e = put(h, key, [10, 8], { route: 2 });
assert.ok(h.runUntil(() => e.stats.attacks >= 1, 10), 'attacks');
const shell = h.eventsOf('fx').find((ev) => ev[1] === 'bombardShell');
assert.ok(Math.abs(shell[4].r - 1.45) < 1e-9, 'drawn at the reach: 1.2 + the 0.25 collider');
h.run(3.1);
const taken = (id) => h.unit(id).stats.taken;
for (const [id, what] of [['t_wall', 'the impact'], ['t_wall2', 'its orthogonal neighbour (1 away)'], ['t_wall3', 'a diagonal neighbour (√2 away)']]) {
assert.ok(Math.abs(taken(id) - e.s.atk) < 1e-6, `${key}: ${what} takes the shell`);
}
assert.equal(taken('t_wall4'), 0, `${key}: two tiles away stays out`);
checkInvariants(h.b);
}
});
test(`${nm('enemy_10084_hlegle')}: never attacks a flying ally (不会攻击飞行单位) — a ground one in range instead`, () => {
// a flying ally (the 炎佑 is one) deployed after the wall, so the engine's order (latest deployed) would pick it
const h = arena({ units: [{ chessId: 't_wall', row: 10, col: 6 }, { chessId: 't_wall2', row: 10, col: 8 }] });