diff --git a/server/sim/content/kits/ops/chess_char_4_01-rmixer.js b/server/sim/content/kits/ops/chess_char_4_01-rmixer.js index 03e2d796..581eb90f 100644 --- a/server/sim/content/kits/ops/chess_char_4_01-rmixer.js +++ b/server/sim/content/kits/ops/chess_char_4_01-rmixer.js @@ -7,7 +7,6 @@ import { AURA, num, tbb, grid, nationOf, enemiesOnRange, targetsInRange, whileDeployed, reveal, skillActive, isSel, alt, instantKind, withDefaults, } from '../shared/tier4.js'; -import { hypot } from '../../../detmath.js'; /** Is module `id` the active one? (elites; `'none'` / normal chess ⇒ false) */ const moduleIs = (def, id) => !!(def?.raw?.module?.active && def.raw.module.id === id); @@ -31,7 +30,9 @@ export default withDefaults({ return { skills: alt(def, { // 铳骑主考官: the next attack is a triple hit of atk_scale each and reloads `charge` bullet(s) into ONE other - // 拉特兰 operator around him (8 tiles, [ASSUMED] nearest first) whose ammo skill runs + // 拉特兰 operator around him whose ammo skill runs — PRTS 备注 「补弹范围为周围8格,仅选择可补弹的干员为目标,优先选择最后 + // 部署的干员」: the latest deployment first (battle-wide deploySeq: a redeploy is a new deployment). Until 0.2.2 the + // nearest first [ASSUMED] (GitHub #325, PR #329) skchr_rmixer_1: () => ({ kind: instantKind(def), attack: { @@ -40,7 +41,7 @@ export default withDefaults({ const n = num(bb.charge, 1); const cand = battle.alliesInRadius(unit.x, unit.y, 1.5, unit.ownerId) .filter((a) => a !== unit && a.kind === 'op' && nationOf(a) === 'laterano' && a.skill && a.skill.active && a.skill.kind === 'ammo') - .sort((a, b) => hypot(a.x - unit.x, a.y - unit.y) - hypot(b.x - unit.x, b.y - unit.y) || a.id - b.id); + .sort((a, b) => b.deploySeq - a.deploySeq || a.id - b.id); if (!cand[0] || !(n > 0)) return; cand[0].skill.addAmmo(n); battle.fx('reload', { x: cand[0].x, y: cand[0].y, id: cand[0].id, n }); diff --git a/test/content/kits_alt_t4.test.js b/test/content/kits_alt_t4.test.js index a9cb69d7..13ff6751 100644 --- a/test/content/kits_alt_t4.test.js +++ b/test/content/kits_alt_t4.test.js @@ -113,6 +113,30 @@ test('信仰搅拌机 S1 铳骑主考官 (自动触发 ⇒ DEFAULT: hurt SP, fir } }); +test('信仰搅拌机 S1 reloads the latest-deployed 拉特兰 ammo user around him, not the nearest (PRTS 备注; GitHub #325, PR #329)', () => { + for (const redeploy of [false, true]) { + // 隐现 ×2: the orthogonal neighbour deployed first, the diagonal one after it (both on his 8 surrounding tiles) + const h = battle([U('chess_char_4_01_a', 10, 5, 0), U('chess_char_1_01_a', 10, 4, null, null, { uid: 2 }), U('chess_char_1_01_a', 9, 4, null, null, { uid: 3 })]); + h.step(); + const u = h.unit('chess_char_4_01_a'), near = h.unit(2), far = h.unit(3); + if (redeploy) { // a redeploy is the latest deployment + h.b.retreat(near, { reason: 'raid' }); + assert.ok(h.b._deploy(near)); + } + const latest = redeploy ? near : far, other = redeploy ? far : near; + assert.ok(latest.deploySeq > other.deploySeq); + for (const a of [near, far]) { assert.ok(a.skill.activate('test', { free: true })); a.skill.ammoLeft = 5; } + const e = h.spawn('enemy_dummy', { pos: [10, 6] }); + assert.ok(u.skill.activate('test', { free: true })); + h.b.forceAttack(u, [e]); + h.run(0.5); + const reloads = h.eventsOf('fx').filter((x) => x[1] === 'reload'); + assert.ok(reloads.length > 0, 'a reload happened'); + assert.ok(reloads.every((x) => x[4].id === latest.id), `${redeploy ? 'after a redeploy, the redeployed one' : 'the later-deployed diagonal one'} is reloaded`); + checkInvariants(h.b); + } +}); + test('信仰搅拌机 S2 八臂电锯侠: ammo skill, ATK/DEF up; a lethal hit is negated for ammo_cost bullets; with fewer it is still negated, every bullet goes and the skill ends (PRTS 备注)', () => { for (const id of pair('chess_char_4_01_a')) { const bb = D(id, 1).skill.bb;