feedback3 WI: 琳琅诗怀雅 S3 shoots at 10 coins only when an enemy is in her attack range
This commit is contained in:
1 parent
ab56ea01b1
commit
627bb6d4c1
2 files changed
+34
-31
No files matched your search
@@ -406,8 +406,8 @@ const KITS = {
|
|||||||
// a small push, radial despite the text's 向前 — PRTS 备注 "推开效果为径向推动"; client charpack char_1033_swire2:
|
// a small push, radial despite the text's 向前 — PRTS 备注 "推开效果为径向推动"; client charpack char_1033_swire2:
|
||||||
// the RandomGold ability (Skill_3_End) carries swire2_s_3[knockback] of template knockback[relative]; 地面敌方单位,
|
// the RandomGold ability (Skill_3_End) carries swire2_s_3[knockback] of template knockback[relative]; 地面敌方单位,
|
||||||
// 弹道不可对空). It does not close itself when the purse is full (PRTS 卫戍协议/帮助 「通常不会自动关闭技能」; the skill
|
// 弹道不可对空). It does not close itself when the purse is full (PRTS 卫戍协议/帮助 「通常不会自动关闭技能」; the skill
|
||||||
// text is 「可随时主动关闭」). Owner's decision 2026-10-04: the written cap (金币上限为10) is the close — at the cap the
|
// text is 「可随时主动关闭」). Owner 2026-10-04: at the cap (金币上限为10) she shoots once an enemy is in the skill's
|
||||||
// coins are shot at once (skill.end('manual')), with or without a mark. Below the cap it stays open.
|
// attack range (the 1-tile range, not the coin-mark 2-4 grid). Below the cap, or with nobody there, it stays open.
|
||||||
// 精锐 module MER-Y: ATK +4 % per trait payment (≤ 5 stacks).
|
// 精锐 module MER-Y: ATK +4 % per trait payment (≤ 5 stacks).
|
||||||
chess_char_3_04_a: (bb, chess, def) => {
|
chess_char_3_04_a: (bb, chess, def) => {
|
||||||
const d = defOf(chess, def);
|
const d = defOf(chess, def);
|
||||||
@@ -506,11 +506,13 @@ const KITS = {
|
|||||||
return {
|
return {
|
||||||
kind: 'toggle',
|
kind: 'toggle',
|
||||||
attack: { hits: 2 },
|
attack: { hits: 2 },
|
||||||
// Owner 2026-10-04: 「金币上限为10」 is the close. Reaching the cap shoots the coins (the onEnd below).
|
// Owner 2026-10-04: at the cap, shoot once a ground enemy is in the skill attack range (data rangeGrid,
|
||||||
// It does not wait for a mark — a cap with nobody in range still spends them and hits nothing. Below the
|
// the same 1-tile range as her attack). The coin marks (前方 2-4) are who the burst pays, not the trigger.
|
||||||
// cap the skill stays open (the old close also required a markable enemy; that wait is withdrawn).
|
// Nobody in that range: stay open and keep the coins. Below the cap: stay open.
|
||||||
onTick({ unit, skill }) {
|
onTick({ battle, unit, skill }) {
|
||||||
if (skill.active && (unit.mem.coins ?? 0) + 1e-9 >= purseCap) skill.end('manual');
|
if (!skill.active || (unit.mem.coins ?? 0) + 1e-9 < purseCap) return;
|
||||||
|
const keys = gridKeys(skillGrid ?? unit.rangeGrid, unit);
|
||||||
|
if (enemiesOn(battle, unit, keys, 0, { ...unit.profile, canHitFly: false }).length) skill.end('manual');
|
||||||
},
|
},
|
||||||
onEnd({ battle, unit, reason }) {
|
onEnd({ battle, unit, reason }) {
|
||||||
if (reason !== 'manual' || !unit.alive) return;
|
if (reason !== 'manual' || !unit.alive) return;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// test/sim/feedback3-swire-s3.test.js — 琳琅诗怀雅 S3 千金一掷. Owner 2026-10-04: the written purse cap
|
// test/sim/feedback3-swire-s3.test.js — 琳琅诗怀雅 S3 千金一掷. Owner 2026-10-04: at the purse cap of 10
|
||||||
// (「金币上限为10」) is the close. At the cap the coins are shot (skill.end('manual'): damage + radial push).
|
// she shoots once a ground enemy is in the skill attack range (the 1-tile range). Below the cap, or with
|
||||||
// Below the cap the skill stays open. No mark still spends and hits nothing.
|
// the enemy only further ahead, the skill stays open and the coins stay. A manual close still spends.
|
||||||
|
|
||||||
import { test } from 'node:test';
|
import { test } from 'node:test';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
@@ -11,11 +11,11 @@ const REAL = { skip: !hasGeneratedData() };
|
|||||||
const ID = 'chess_char_3_04_a';
|
const ID = 'chess_char_3_04_a';
|
||||||
const foe = enemyRec({ key: 'e_sw', hp: 1e9, atk: 0, speed: 0, def: 0, res: 0, mass: 1 });
|
const foe = enemyRec({ key: 'e_sw', hp: 1e9, atk: 0, speed: 0, def: 0, res: 0, mass: 1 });
|
||||||
|
|
||||||
function battle(withEnemy) {
|
function battle(pos) {
|
||||||
return makeBattle({
|
return makeBattle({
|
||||||
defs: { enemies: { e_sw: foe } },
|
defs: { enemies: { e_sw: foe } },
|
||||||
units: [{ chessId: ID, row: 10, col: 5, skillIndex: 2 }],
|
units: [{ chessId: ID, row: 10, col: 5, skillIndex: 2 }],
|
||||||
enemies: withEnemy ? [{ key: 'e_sw', pos: [10, 6] }] : [],
|
enemies: pos ? [{ key: 'e_sw', pos }] : [],
|
||||||
hooks: ['damaged', 'skillEnd'], autoFinish: false, timeLimit: 30,
|
hooks: ['damaged', 'skillEnd'], autoFinish: false, timeLimit: 30,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -27,42 +27,43 @@ const arm = (h) => {
|
|||||||
return u;
|
return u;
|
||||||
};
|
};
|
||||||
|
|
||||||
test('琳琅诗怀雅 S3 shoots the purse when it reaches the cap of 10, and stays open below it', REAL, () => {
|
test('琳琅诗怀雅 S3 shoots at the cap only once an enemy is in the skill attack range', REAL, () => {
|
||||||
const under = battle(true);
|
const under = battle([10, 6]);
|
||||||
const u9 = arm(under);
|
const u9 = arm(under);
|
||||||
u9.mem.coins = 9;
|
u9.mem.coins = 9;
|
||||||
// shorter than the merchant trait's 3 s payment, which would add a coin and reach the cap
|
|
||||||
under.run(2);
|
under.run(2);
|
||||||
assert.equal(u9.skill.active, true, '9 coins do not close it');
|
assert.equal(u9.skill.active, true, '9 coins do not close it');
|
||||||
assert.equal(u9.mem.coins, 9);
|
assert.equal(u9.mem.coins, 9);
|
||||||
|
|
||||||
const h = battle(true);
|
const far = battle([10, 7]); // two tiles ahead: outside the 1-tile attack range, inside nothing she swings at
|
||||||
|
const uf = arm(far);
|
||||||
|
uf.mem.coins = 10;
|
||||||
|
far.run(0.5);
|
||||||
|
assert.equal(uf.skill.active, true, 'an enemy outside the attack range does not make her shoot');
|
||||||
|
assert.equal(uf.mem.coins, 10);
|
||||||
|
|
||||||
|
const none = battle(null);
|
||||||
|
const un = arm(none);
|
||||||
|
un.mem.coins = 10;
|
||||||
|
none.run(0.5);
|
||||||
|
assert.equal(un.skill.active, true, 'nobody in range: the purse stays');
|
||||||
|
assert.equal(un.mem.coins, 10);
|
||||||
|
|
||||||
|
const h = battle([10, 6]); // one tile ahead: the skill attack range
|
||||||
const u = arm(h);
|
const u = arm(h);
|
||||||
const e = h.enemies()[0];
|
const e = h.enemies()[0];
|
||||||
const hp0 = e.hp;
|
const hp0 = e.hp;
|
||||||
u.mem.coins = 10;
|
u.mem.coins = 10;
|
||||||
h.run(0.2);
|
h.run(0.2);
|
||||||
assert.equal(u.skill.active, false, 'the cap shoots');
|
assert.equal(u.skill.active, false, 'the enemy in the attack range is shot');
|
||||||
assert.equal(u.mem.coins, 0, 'every coin is spent');
|
assert.equal(u.mem.coins, 0, 'every coin is spent');
|
||||||
assert.ok(e.hp < hp0, 'the coins hit the enemy in range');
|
assert.ok(e.hp < hp0, 'the coins hit that enemy');
|
||||||
assert.equal(h.b.errors.length, 0);
|
|
||||||
checkInvariants(h.b);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('琳琅诗怀雅 S3: the cap with no markable target still ends and spends, and does not throw', REAL, () => {
|
|
||||||
const h = battle(false);
|
|
||||||
const u = arm(h);
|
|
||||||
u.mem.coins = 10;
|
|
||||||
assert.doesNotThrow(() => h.run(0.2));
|
|
||||||
assert.equal(u.skill.active, false);
|
|
||||||
assert.equal(u.mem.coins, 0);
|
|
||||||
assert.equal(h.hooksOf('damaged').length, 0, 'nothing to pay');
|
|
||||||
assert.equal(h.b.errors.length, 0);
|
assert.equal(h.b.errors.length, 0);
|
||||||
checkInvariants(h.b);
|
checkInvariants(h.b);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('琳琅诗怀雅 S3: a manual close below the cap still spends', REAL, () => {
|
test('琳琅诗怀雅 S3: a manual close below the cap still spends', REAL, () => {
|
||||||
const h = battle(false);
|
const h = battle(null);
|
||||||
const u = arm(h);
|
const u = arm(h);
|
||||||
u.mem.coins = 4;
|
u.mem.coins = 4;
|
||||||
assert.doesNotThrow(() => u.skill.end('manual'));
|
assert.doesNotThrow(() => u.skill.end('manual'));
|
||||||
|
|||||||
Reference in new issue
Block a user