diff --git a/server/sim/content/kits/tier5.js b/server/sim/content/kits/tier5.js index 1fbf763a..97d2822a 100644 --- a/server/sim/content/kits/tier5.js +++ b/server/sim/content/kits/tier5.js @@ -817,11 +817,12 @@ const KITS = { mods: mods({ hpPct: num(bb.max_hp), atkPct: num(bb.atk) }), onStart({ battle, unit }) { // PRTS 备注 ② — the anchor's target: his own tile while he blocks an enemy (e.g. just after a 突袭 landing), - // else the nearest tile of the skill range (6-1: his own tile and the 6 straight ahead along his direction) with - // an enemy on it, else its farthest tile + // else the nearest tile ahead in the skill range (straight along his direction) with an enemy on it, else the + // farthest one. His own tile is a candidate only while he blocks ("自身所在地块(仅阻挡敌人时)"); not taken: the + // reading of the range's own tile (6-1 starts at [0,0]) as distance 0 for the second rule (a flyer over him) let stop = 0; if (!unit.blocking.some((e) => e.alive && e.blockedBy === unit)) { - for (let d = 0; d <= reach; d++) { + for (let d = 1; d <= reach; d++) { const [r, c] = frontOf(unit.tileR, unit.tileC, unit.dir, d); // the anchor stops at the field edge and in front of a ground obstacle (crates, roadblocks) if (!battle.grid.inRect(r, c) || battle.grid.isObstacle(r, c)) break; diff --git a/test/content/kits_t5.test.js b/test/content/kits_t5.test.js index a40823b2..dbace6bf 100644 --- a/test/content/kits_t5.test.js +++ b/test/content/kits_t5.test.js @@ -235,9 +235,9 @@ test('乌尔比安 S3: anchor 135 % ATK + stun on the first enemy ahead, moves t }); test('乌尔比安 S3 while he blocks (e.g. after a 突袭 landing): the anchor lands on his own tile — no 【移动】, no marker (PRTS 备注; GitHub #33)', () => { - // PRTS 乌尔比安 S3 备注: target = his own tile (only while blocking) > the nearest tile of the skill range (6-1, from his own - // tile on) with an enemy > its farthest tile; the 从不混淆的方向 only when the 【移动】 changes his tile - const run = (near) => { + // PRTS 乌尔比安 S3 备注: target = his own tile (only while blocking) > the nearest tile of the skill range with an enemy > + // its farthest tile; the 从不混淆的方向 only when the 【移动】 changes his tile + const setup = (near) => { const h = makeBattle({ defs: { enemies: { enemy_dummy: dummy(), enemy_fly: dummy('enemy_fly', { motion: 'FLY' }) } }, units: [{ chessId: 'chess_char_5_05_a', row: 9, col: 3 }], @@ -249,21 +249,35 @@ test('乌尔比安 S3 while he blocks (e.g. after a 突袭 landing): the anchor const blocked = e0.blockedBy === u; u.skill.gainSp(1000); assert.ok(h.runUntil(() => u.skill.active, 2), near); - const anchor = fxOf(h, 'anchor')[0]; - assert.deepEqual([anchor[2], anchor[3]], [3, 9], `${near}: the anchor on his own tile`); - assert.equal(tagged(h, 'anchor', e0).length, 1, `${near}: the enemy on his tile is hit`); + return { h, u, e0, far, blocked, anchor: fxOf(h, 'anchor')[0] }; + }; + { // blocking the enemy on his tile: the anchor on his own tile, he stays + const { h, u, e0, far, blocked, anchor } = setup('enemy_dummy'); + assert.ok(blocked, 'he blocks the enemy on his tile'); + assert.deepEqual([anchor[2], anchor[3]], [3, 9], 'the anchor on his own tile'); + assert.equal(tagged(h, 'anchor', e0).length, 1, 'the blocked enemy is hit'); assert.ok(e0.s.flags.stun); - assert.equal(tagged(h, 'anchor', far).length, 0, `${near}: 4 tiles ahead, out of the 1.8 radius`); - assert.deepEqual([u.tileR, u.tileC], [9, 3], `${near}: no 【移动】`); - assert.ok(!h.b.allyUnits.some((x) => x.kind === 'token'), `${near}: no 从不混淆的方向`); + assert.equal(tagged(h, 'anchor', far).length, 0, '4 tiles ahead, out of the 1.8 radius'); + assert.deepEqual([u.tileR, u.tileC], [9, 3], 'no 【移动】'); + assert.ok(!h.b.allyUnits.some((x) => x.kind === 'token'), 'no 从不混淆的方向'); assert.ok(h.runUntil(() => !u.skill.active, 30)); assert.deepEqual([u.tileR, u.tileC], [9, 3]); clean(h); - return blocked; - }; - assert.equal(run('enemy_dummy'), true, 'he blocks the enemy on his tile'); - // not blocking, a flyer over him: his own tile is the nearest tile of the skill range with an enemy (distance 0) - assert.equal(run('enemy_fly'), false, 'a flyer is not blocked'); + } + { // not blocking, a flyer over his tile: his own tile is no candidate (only while blocking) — the anchor flies to the + // enemy 4 tiles ahead and he moves there, as in 0.1.1 + const { h, u, e0, far, blocked, anchor } = setup('enemy_fly'); + assert.ok(!blocked, 'a flyer is not blocked'); + assert.deepEqual([anchor[2], anchor[3]], [7, 9], 'the anchor on the enemy ahead'); + assert.equal(tagged(h, 'anchor', far).length, 1); + assert.equal(tagged(h, 'anchor', e0).length, 0, 'the flyer over his tile is out of the 1.8 radius'); + assert.deepEqual([u.tileR, u.tileC], [9, 7], 'moved onto the anchor tile'); + const marker = h.b.allyUnits.find((x) => x.kind === 'token' && x.alive); + assert.ok(marker && marker.tileR === 9 && marker.tileC === 3, 'the marker on his tile'); + assert.ok(h.runUntil(() => !u.skill.active, 30)); + assert.deepEqual([u.tileR, u.tileC], [9, 3], 'back home'); + clean(h); + } }); test('乌尔比安 T1 本性的坚守 heals per hit taken; T2 血脉的哺养 +HP/ATK per kill (abyssal allies half); elite healing ×1.2', () => {