feedback3 WB: 琳琅诗怀雅 S1 heals an injured ally beside her without needing an attack or an enemy, at most once per attack cycle (owner's decision 2026-10-04, community report #5)

This commit is contained in:
sganggs committed 2026-10-04 18:18:18 +08:00
1 parent d1a2696e44
commit 7d3d7318d5
2 files changed
+68 -6

No files matched your search

+44
View File
@@ -226,6 +226,50 @@ test('3_04 琳琅诗怀雅 S1 仗义疏财: 2 coins; an attack spends one to hea
}
});
// Owner's decision 2026-10-04 (community report #5 「琳琅诗怀雅1技能不会主动奶身边受伤的干员」), a deliberate deviation from the official
// 「下一次攻击会为…」: S1 heals an injured ally beside her without an attack or an enemy — at most once per attack cycle
// (her attack interval, ASPD included) [ASSUMED cadence]; with an enemy the heal stays on her attack.
test('3_04 琳琅诗怀雅 S1 仗义疏财 (owner\'s decision): an injured ally beside her is healed with no enemy on the field, once per attack cycle; with an enemy, once per attack', () => {
const id = 'chess_char_3_04_a';
const b = SB(id, 'skchr_swire2_1');
const mk = (enemies = []) => makeBattle({ defs: { enemies: { enemy_d: dummy('enemy_d') } }, timeLimit: 60, autoFinish: false, hooks: ['heal', 'attack'], captureNoisy: true,
units: [U(id, 'skchr_swire2_1', 9, 5), { chessId: 'chess_char_3_16_a', row: 10, col: 5 }], enemies });
// no enemy: an ally at 80 % is left alone, one at 50 % is healed and a coin is spent
let h = mk();
let u = h.unit(id), ally = h.unit('chess_char_3_16_a');
h.step();
u.mem.coins = 2;
ally.hp = ally.s.maxHp * 0.8;
h.run(3);
assert.equal(h.hooksOf('heal').filter((c) => c.source === u).length, 0, '80 %: not below 70 %');
assert.equal(u.mem.coins, 2, 'the coin is kept');
ally.hp = ally.s.maxHp * 0.5;
h.step();
const heals = h.hooksOf('heal').filter((c) => c.source === u);
assert.equal(heals.length, 1, 'healed at once, no enemy needed');
assert.equal(heals[0].target, ally);
approx(heals[0].amount, u.s.atk * b['attack@heal_scale']);
assert.equal(u.mem.coins, 1, 'one coin spent');
assert.equal(h.hooksOf('attack').filter((c) => c.attacker === u).length, 0, 'without an attack');
// kept injured with coins to spare: one heal per attack interval, never more
const n0 = h.hooksOf('heal').length, t0 = h.b.time;
for (let i = 0; i < 300; i++) { ally.hp = ally.s.maxHp * 0.3; u.mem.coins = 2; h.step(); }
const per = h.hooksOf('heal').slice(n0).filter((c) => c.source === u).length;
assert.equal(per, Math.floor((h.b.time - t0) / u.s.interval + 1e-6), `one heal per ${u.s.interval} s`);
done(h);
// with an enemy in her range: the heal rides on each attack, never a second one in the cycle
h = mk([{ key: 'enemy_d', pos: [9, 6] }]);
u = h.unit(id); ally = h.unit('chess_char_3_16_a');
h.step();
const a0 = h.hooksOf('attack').length, h0 = h.hooksOf('heal').length; // (its first attack, at deployment, found the ally unhurt)
for (let i = 0; i < 300; i++) { ally.hp = ally.s.maxHp * 0.3; u.mem.coins = 2; h.step(); }
const atk = h.hooksOf('attack').slice(a0).filter((c) => c.attacker === u).length;
const hl = h.hooksOf('heal').slice(h0).filter((c) => c.source === u).length;
assert.ok(atk >= 5, `attacks (${atk})`);
assert.equal(hl, atk, 'one heal per attack');
done(h);
});
test('3_04 琳琅诗怀雅 S3 千金一掷: 二连击, kills pay a coin, a full purse is cashed out on the front range (hits + push)', () => {
for (const id of BOTH('chess_char_3_04_a')) {
const b = SB(id, 'skchr_swire2_3'), t0 = TB(id, 0);