Official: S1 「下一次攻击会为周围八格内血量不足70%的一名友方单位恢复…」; the client charpack (char_1033_swire2, mode S1, ability HealAlly) selects with range x-4 (the 3×3 with her tile), ally side, _excludeOwner 0, max HP ratio 0.7, one target. Cause: kits/ops/chess_char_3_04-swire2.js healTarget skipped her (a === unit) and kept only Chebyshev distance 1. Now: the lowest HP ratio below 70 % of the 3×3, herself included (her own 禁疗 still stops it); the owner's 2026-10-04 cadence (a heal without an attack, once per attack cycle) unchanged. Golden: roster-027 (琳琅诗怀雅 elite S1 in band 4: she heals herself below 70 %). Tests: test/content/feedback5-swire2-self-heal.test.js (2, fail on the parent).
49 lines
2.5 KiB
JavaScript
49 lines
2.5 KiB
JavaScript
// test/content/feedback5-swire2-self-heal.test.js — 琳琅诗怀雅 S1 仗义疏财 heals herself too (community report of 2026-10-06
|
||
// 「干员琳琅诗怀雅不会治疗自己」): 「下一次攻击会为周围八格内血量不足70%的一名友方单位恢复…」 — the client charpack
|
||
// (char_1033_swire2, mode S1, ability HealAlly) selects with range x-4 (the 3×3 with her own tile), ally side,
|
||
// `_excludeOwner` 0, max HP ratio 0.7, one target. kits/ops/chess_char_3_04-swire2.js used to skip her own tile.
|
||
// Run: node --test test/content/feedback5-swire2-self-heal.test.js
|
||
|
||
import { test } from 'node:test';
|
||
import assert from 'node:assert/strict';
|
||
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||
import { getDefaultSource } from '../../server/sim/simdata.js';
|
||
|
||
const ds = getDefaultSource();
|
||
const ID = 'chess_char_3_04_a', S1 = 'skchr_swire2_1';
|
||
const S1_INDEX = ds.rawChess(ID).skills.find((s) => s.skillId === S1).index;
|
||
const NEIGHBOUR = 'chess_char_3_16_a';
|
||
|
||
/** 琳琅诗怀雅 (S1) on (9, 5), an ally on (10, 5); HP ratios set after the deployment; coins to spare. */
|
||
function field(herRatio, allyRatio) {
|
||
const h = makeBattle({
|
||
defs: { enemies: { enemy_d: enemyRec({ key: 'enemy_d', hp: 1e7, speed: 0 }) } },
|
||
units: [{ chessId: ID, row: 9, col: 5, skillIndex: S1_INDEX }, { chessId: NEIGHBOUR, row: 10, col: 5 }],
|
||
timeLimit: 60, autoFinish: false, hooks: ['heal'], captureNoisy: true, flags: { dpInit: 60, dpMax: 99 },
|
||
});
|
||
h.step();
|
||
const u = h.unit(ID), ally = h.unit(NEIGHBOUR);
|
||
u.mem.coins = 2;
|
||
u.hp = u.s.maxHp * herRatio;
|
||
ally.hp = ally.s.maxHp * allyRatio;
|
||
h.run(1);
|
||
return { h, u, ally, heals: h.hooksOf('heal').filter((c) => c.source === u) };
|
||
}
|
||
|
||
test('alone below 70 %: a coin heals herself (her own tile is in the x-4 selector)', () => {
|
||
const { h, u, heals } = field(0.5, 1);
|
||
assert.equal(heals.length, 1, 'one heal');
|
||
assert.equal(heals[0].target, u, 'on herself');
|
||
assert.equal(u.mem.coins, 1, 'one coin spent');
|
||
checkInvariants(h.b);
|
||
assert.equal(h.b.errors.length, 0);
|
||
});
|
||
|
||
test('the lowest HP ratio of the 3×3 wins: herself below the neighbour, the neighbour below her; 70 % or more is never healed', () => {
|
||
assert.equal(field(0.4, 0.6).heals[0].target.defId, ID, 'she is lower: herself');
|
||
assert.equal(field(0.6, 0.4).heals[0].target.defId, NEIGHBOUR, 'the neighbour is lower: the neighbour');
|
||
const none = field(0.75, 1);
|
||
assert.equal(none.heals.length, 0, 'not below 70 %: no heal, the coin is kept');
|
||
assert.equal(none.u.mem.coins, 2);
|
||
});
|