feedback2 WC: 乌尔比安 S3 throws the anchor onto his own tile while he blocks, so he stays put and leaves no marker (PRTS note; GitHub #33 item 2)
This commit is contained in:
1 parent
215d52efe3
commit
7383419009
2 files changed
+52
-12
No files matched your search
@@ -763,8 +763,9 @@ const KITS = {
|
|||||||
|
|
||||||
// ---------------------------------------------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------------------------------------------
|
||||||
// 乌尔比安 — S3 必须开辟的通路 (25 s, CUSTOM_RANGE row ahead): max HP/ATK +, throws an anchor forward that stops on the
|
// 乌尔比安 — S3 必须开辟的通路 (25 s, CUSTOM_RANGE row ahead): max HP/ATK +, throws an anchor forward that stops on the
|
||||||
// first enemy or at max distance: 135 % ATK phys + 6 s stun around it (projectile_range); moves onto the anchor tile when
|
// first enemy or at max distance — on his own tile while he blocks: 135 % ATK phys + 6 s stun around it
|
||||||
// deployable (a 从不混淆的方向 marker keeps his tile) and returns at skill end.
|
// (projectile_range); moves onto the anchor tile when deployable and not his own (a 从不混淆的方向 marker keeps his tile)
|
||||||
|
// and returns at skill end.
|
||||||
// T1 本性的坚守: heal 100 (160 below 50 %) on every hit taken. T2 血脉的哺养: per kill +120 max HP / +30 ATK (×9),
|
// T1 本性的坚守: heal 100 (160 below 50 %) on every hit taken. T2 血脉的哺养: per kill +120 max HP / +30 ATK (×9),
|
||||||
// other Abyssal Hunters +50 %. Module (elite): healing received ×1.2.
|
// other Abyssal Hunters +50 %. Module (elite): healing received ×1.2.
|
||||||
// S1 必须促成的接触 (instant): the anchor lands on the best enemy of the skill range (beyond his own range, unblocked
|
// S1 必须促成的接触 (instant): the anchor lands on the best enemy of the skill range (beyond his own range, unblocked
|
||||||
@@ -815,23 +816,30 @@ const KITS = {
|
|||||||
kind: 'duration',
|
kind: 'duration',
|
||||||
mods: mods({ hpPct: num(bb.max_hp), atkPct: num(bb.atk) }),
|
mods: mods({ hpPct: num(bb.max_hp), atkPct: num(bb.atk) }),
|
||||||
onStart({ battle, unit }) {
|
onStart({ battle, unit }) {
|
||||||
// the anchor flies straight ahead along his direction
|
// PRTS 备注 ② — the anchor's target: his own tile while he blocks an enemy (e.g. just after a 突袭 landing),
|
||||||
let stop = null;
|
// else the nearest tile of the skill range (6-1: his own tile and the 6 straight ahead along his direction) with
|
||||||
for (let d = 1; d <= reach; d++) {
|
// an enemy on it, else its farthest tile
|
||||||
const [r, c] = frontOf(unit.tileR, unit.tileC, unit.dir, d);
|
let stop = 0;
|
||||||
// the anchor stops at the field edge and in front of a ground obstacle (crates, roadblocks)
|
if (!unit.blocking.some((e) => e.alive && e.blockedBy === unit)) {
|
||||||
if (!battle.grid.inRect(r, c) || battle.grid.isObstacle(r, c)) break;
|
for (let d = 0; d <= reach; d++) {
|
||||||
stop = d;
|
const [r, c] = frontOf(unit.tileR, unit.tileC, unit.dir, d);
|
||||||
if (battle.enemiesInKeys([r * COLS + c], unit, { canHitFly: true }).length) break;
|
// 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;
|
||||||
|
stop = d;
|
||||||
|
if (battle.enemiesInKeys([r * COLS + c], unit, { canHitFly: true }).length) break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
const [sr, sc] = frontOf(unit.tileR, unit.tileC, unit.dir, stop ?? 0);
|
const [sr, sc] = frontOf(unit.tileR, unit.tileC, unit.dir, stop);
|
||||||
const fromX = unit.x, fromY = unit.y;
|
const fromX = unit.x, fromY = unit.y;
|
||||||
battle.fx('anchor', { x: sc, y: sr, id: unit.id, fromX, fromY, r: radius });
|
battle.fx('anchor', { x: sc, y: sr, id: unit.id, fromX, fromY, r: radius });
|
||||||
for (const e of battle.foesInRadius(sc, sr, radius)) {
|
for (const e of battle.foesInRadius(sc, sr, radius)) {
|
||||||
battle.dealDamage(unit, e, { amount: unit.s.atk * num(bb.atk_scale), type: 'phys', isSkill: true, tags: ['skill', 'anchor'] });
|
battle.dealDamage(unit, e, { amount: unit.s.atk * num(bb.atk_scale), type: 'phys', isSkill: true, tags: ['skill', 'anchor'] });
|
||||||
if (e.alive) battle.applyStatus(e, 'stun', { duration: num(bb.stun), source: unit });
|
if (e.alive) battle.applyStatus(e, 'stun', { duration: num(bb.stun), source: unit });
|
||||||
}
|
}
|
||||||
if (stop == null || !unit.alive) return;
|
// ③ 【移动】 — only a change of tile moves him and leaves the 从不混淆的方向 ("若目标地块不为当前地块,会在原地部署"): an
|
||||||
|
// anchor on his own tile leaves him where he stands, no marker, nothing to return from [ASSUMED: the "tile one
|
||||||
|
// beyond the landing" is not tried when the landing is his own tile]
|
||||||
|
if (stop === 0 || !unit.alive) return;
|
||||||
// PRTS 备注: landing tile > the tile one beyond it > his own tile (a deployable, free, unreserved melee tile)
|
// PRTS 备注: landing tile > the tile one beyond it > his own tile (a deployable, free, unreserved melee tile)
|
||||||
const ok = ([r, c]) => (r !== unit.tileR || c !== unit.tileC) && battle.grid.inRect(r, c) && battle.grid.canStand(r, c) && !battle.grid.isObstacle(r, c) && !battle.isReservedTile(r, c);
|
const ok = ([r, c]) => (r !== unit.tileR || c !== unit.tileC) && battle.grid.inRect(r, c) && battle.grid.canStand(r, c) && !battle.grid.isObstacle(r, c) && !battle.isReservedTile(r, c);
|
||||||
const dest = [[sr, sc], frontOf(unit.tileR, unit.tileC, unit.dir, stop + 1)].find(ok);
|
const dest = [[sr, sc], frontOf(unit.tileR, unit.tileC, unit.dir, stop + 1)].find(ok);
|
||||||
|
|||||||
@@ -234,6 +234,38 @@ test('乌尔比安 S3: anchor 135 % ATK + stun on the first enemy ahead, moves t
|
|||||||
clean(h);
|
clean(h);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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) => {
|
||||||
|
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 }],
|
||||||
|
enemies: [{ key: near, pos: [9, 3] }, { key: 'enemy_dummy', pos: [9, 7] }], hooks: ['damaged'], captureNoisy: true, autoFinish: false, timeLimit: 120,
|
||||||
|
});
|
||||||
|
const u = h.unit('chess_char_5_05_a');
|
||||||
|
h.step();
|
||||||
|
const [e0, far] = h.b.enemies;
|
||||||
|
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`);
|
||||||
|
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.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');
|
||||||
|
});
|
||||||
|
|
||||||
test('乌尔比安 T1 本性的坚守 heals per hit taken; T2 血脉的哺养 +HP/ATK per kill (abyssal allies half); elite healing ×1.2', () => {
|
test('乌尔比安 T1 本性的坚守 heals per hit taken; T2 血脉的哺养 +HP/ATK per kill (abyssal allies half); elite healing ×1.2', () => {
|
||||||
const h = makeBattle({
|
const h = makeBattle({
|
||||||
defs: { enemies: { enemy_dummy: dummy() }, chess: { t_abyss: ally('t_abyss', { charId: 'char_143_ghost' }) } },
|
defs: { enemies: { enemy_dummy: dummy() }, chess: { t_abyss: ally('t_abyss', { charId: 'char_143_ghost' }) } },
|
||||||
|
|||||||
Reference in new issue
Block a user