feedback3 WI: 琳琅诗怀雅 S3 does not close itself when her coins are full (GitHub #89)

This commit is contained in:
sganggs committed 2026-10-04 20:35:50 +08:00
1 parent f9e2c49954
commit 473b8eb5b0
2 files changed
+66 -6

No files matched your search

+6 -6
View File
@@ -405,8 +405,9 @@ const KITS = {
// closing it spends every coin on random ground enemies of range 2-4 in front and those she blocks (atk_scale phys +
// 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]; 地面敌方单位,
// 弹道不可对空). Auto-close (the mode casts everything itself; the player's "主动关闭" is not available): once the
// purse is full (10) and a coin target stands there. 精锐 module MER-Y: ATK +4 % per trait payment (≤ 5 stacks).
// 弹道不可对空). It does not close itself when the purse is full (PRTS 卫戍协议/帮助 「通常不会自动关闭技能」; the skill
// text is 「可随时主动关闭」; GitHub #89-1). The player closes it: skill.end('manual'), which spends the coins.
// 精锐 module MER-Y: ATK +4 % per trait payment (≤ 5 stacks).
chess_char_3_04_a: (bb, chess, def) => {
const d = defOf(chess, def);
const t0 = talentBb(d, 0), t1 = talentBb(d, 1);
@@ -493,7 +494,7 @@ const KITS = {
skills: altSkills(chess, d, bb, {
[S1]: () => ({ kind: 'passive' }), // (coins → heals: installS1)
[S3]: (s) => {
const cash = num(s.bb.atk_scale, 1), force = num(s.bb.force, 0), full = num(s.bb.sp, 10);
const cash = num(s.bb.atk_scale, 1), force = num(s.bb.force, 0);
// the 【金币标记】 targets: ground enemies on range 2-4 in front of her (range_table "2-4") and every unit she blocks
const coinMarks = (battle, unit) => {
const list = enemiesOn(battle, unit, gridKeys(SWIRE2_COIN_GRID, unit), 0, { ...unit.profile, canHitFly: false });
@@ -503,9 +504,8 @@ const KITS = {
return {
kind: 'toggle',
attack: { hits: 2 },
onTick({ battle, unit, skill }) {
if ((unit.mem.coins ?? 0) >= full && coinMarks(battle, unit).length) skill.end('manual');
},
// PRTS 卫戍协议/帮助 「通常不会自动关闭技能」; 千金一掷 「可随时主动关闭」 (GitHub #89-1). A full purse
// with a markable enemy does not end it. skill.end('manual') is the close that spends the coins.
onEnd({ battle, unit, reason }) {
if (reason !== 'manual' || !unit.alive) return;
const n = unit.mem.coins ?? 0;
+60
View File
@@ -0,0 +1,60 @@
// test/sim/feedback3-swire-s3.test.js — GitHub #89-1: 琳琅诗怀雅 S3 千金一掷 used to call skill.end('manual')
// from onTick once her coins were full and a ground enemy stood in the coin range. PRTS 卫戍协议/帮助 技能操作
// 「通常不会自动关闭技能」 and the skill text 「可随时主动关闭技能;携带此技能时金币上限为10」: she keeps it
// open. The close is still skill.end('manual') — the same call the old onTick used, and feedback1d-push.test.js —
// which spends the coins and pushes. No markable target still ends and does not throw.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
import { hasGeneratedData } from '../../server/sim/simdata.js';
const REAL = { skip: !hasGeneratedData() };
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 });
function battle(withEnemy) {
return makeBattle({
defs: { enemies: { e_sw: foe } },
units: [{ chessId: ID, row: 10, col: 5, skillIndex: 2 }],
enemies: withEnemy ? [{ key: 'e_sw', pos: [10, 6] }] : [],
hooks: ['damaged', 'skillEnd'], autoFinish: false, timeLimit: 30,
});
}
const arm = (h) => {
h.step();
const u = h.unit(ID);
assert.equal(u.skill.id, 'skchr_swire2_3');
assert.ok(u.skill.active || u.skill.activate('test', { free: true }));
return u;
};
test('琳琅诗怀雅 S3 stays open with a full purse and a coin target; skill.end(\'manual\') still spends', REAL, () => {
const h = battle(true);
const u = arm(h);
const full = 10; // S3 blackboard sp: the purse cap 「金币上限为10」
u.mem.coins = full;
h.run(6);
assert.equal(u.skill.active, true, 'several seconds do not close it');
assert.equal(u.mem.coins, full, 'the coins are still hers');
const e = h.enemies()[0];
const hp0 = e.hp;
u.skill.end('manual');
assert.equal(u.skill.active, false);
assert.equal(u.mem.coins, 0, 'the close spends every coin');
assert.ok(e.hp < hp0, 'and the coins hit the enemy in range');
assert.equal(h.b.errors.length, 0);
checkInvariants(h.b);
});
test('琳琅诗怀雅 S3: closing with no markable target still ends and spends, and does not throw', REAL, () => {
const h = battle(false);
const u = arm(h);
u.mem.coins = 4;
assert.doesNotThrow(() => u.skill.end('manual'));
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);
checkInvariants(h.b);
});