feedback5 CB2: 刺玫's S2 sends only the counter's trait heal to her protégé — her attacks keep healing the most injured ally in range, herself included (community report of 2026-10-06 「刺玫开技能(装备源石药剂)之后不能治疗」)
Official: S2 「该角色受到攻击时刺玫对目标造成攻击力20%的法术伤害并仅对该角色触发刺玫特性」 (en "...and activates her Trait on the ally"); the client buff vendla_tr heals through the S2TraitHealRange selector (the vendla_s_2 holder) only for a damage whose modifier carries vendla_s_2 (the counter, vendla_s_2[extra_damage]), else through TraitHealRange (_excludeOwner 0). Cause: kits/ops/chess_char_1_06-vendla.js sent EVERY trait heal to the protégé while the skill ran (usually at full HP), so a 源石溶剂 carrier healed nobody for 15 s. Golden: roster-001 / roster-002 (刺玫 S2 in band 1), bond-deputShip-low / -high, bond-suntShip-high, bond-victoriaShip-low / -high (刺玫 on those teams), matches solo-FUNNY-2, coop2-NORMAL-3, coop3-ABYSS-5, coop4-FUNNY-6, coop4-ABYSS-7 (bots field 刺玫: her heals land on injured allies during S2, fights change). Tests: test/content/feedback5-vendla-heal.test.js (2, fail on the parent); kits_t1t2's 刺玫 assertion message reworded.
This commit is contained in:
1 parent
30d9a41c51
commit
017390c93f
6 files changed
+251
-179
No files matched your search
@@ -0,0 +1,58 @@
|
||||
// test/content/feedback5-vendla-heal.test.js — 刺玫 S2 荆藤庇荫 and her 咒愈师 trait (community report of 2026-10-06
|
||||
// 「干员刺玫开技能(装备源石药剂)之后不能治疗」): the protégé takes only the trait heal of the S2 counter ("该角色受到攻击时刺玫
|
||||
// 对目标造成攻击力20%的法术伤害并仅对该角色触发刺玫特性"; en "…and activates her Trait on the ally"; client buff vendla_tr: the
|
||||
// S2TraitHealRange selector only for a damage whose modifier carries vendla_s_2). Her own attacks keep healing the lowest-HP
|
||||
// ally in range — herself too (TraitHealRange: _excludeOwner 0). Until 0.2.0 every damage she dealt during the skill healed
|
||||
// the protégé, so with 源石溶剂 draining her she healed nobody while it ran.
|
||||
// Run: node --test test/content/feedback5-vendla-heal.test.js
|
||||
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { makeBattle, enemyRec, chessRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
|
||||
const VENDLA = 'chess_char_1_06_a', SOLVENT = 'chess_item_1_05_e_a';
|
||||
const tank = chessRec({ id: 't_tank', stats: { maxHp: 9000, atk: 0, def: 0 }, skill: null });
|
||||
const still = (r, c) => ({ motion: 'WALK', start: [r, c], end: [r, c], checkpoints: [] });
|
||||
|
||||
/** 刺玫 (+ 源石溶剂) on (10, 4), a high-max-HP ally on (11, 4) — her protégé —, one dummy enemy on (10, 6) hitting `hits`. */
|
||||
function field({ enemyAtk = 0, hits = null } = {}) {
|
||||
const h = makeBattle({
|
||||
defs: { chess: { t_tank: tank }, enemies: { e_dummy: enemyRec({ key: 'e_dummy', hp: 1e8, atk: enemyAtk, speed: 0, range: enemyAtk ? 5 : 0, bat: 1 }) } },
|
||||
units: [{ chessId: VENDLA, row: 10, col: 4, items: [SOLVENT] }, { chessId: 't_tank', row: 11, col: 4 }],
|
||||
enemies: [{ key: 'e_dummy', time: 0, pos: [10, 6], route: still(10, 6) }],
|
||||
autoFinish: false, timeLimit: 60, seed: 3, captureNoisy: true, hooks: ['heal', 'damaged', 'skillStart'],
|
||||
setup: hits ? (b) => b.on('beforeAttack', (ctx) => { if (ctx.attacker.side === 'enemy') ctx.targets = [b.allyUnits.find((u) => u.defId === hits)]; }, { priority: 50 }) : null,
|
||||
});
|
||||
const v = h.unit(VENDLA), tk = h.unit('t_tank');
|
||||
h.run(8); // the 源石溶剂 drain has her below full HP
|
||||
const sk = v.skill;
|
||||
sk.sp = sk.spCost; sk.charges = Math.max(1, sk.charges);
|
||||
assert.ok(sk.activate('manual'), 'S2 starts');
|
||||
assert.equal(v.mem.protege, tk, 'the protégé is the highest-max-HP ally in range');
|
||||
return { h, v, tk, t0: h.b.time };
|
||||
}
|
||||
|
||||
test('during 荆藤庇荫 her attacks heal the most injured ally in range (herself, drained by 源石溶剂), not the full-HP protégé', () => {
|
||||
const { h, v, tk, t0 } = field();
|
||||
h.run(10);
|
||||
assert.ok(v.skill.active, 'still running');
|
||||
const heals = h.hooksOf('heal').filter((c) => c.source === v && c.t >= t0 && c.amount > 0);
|
||||
assert.ok(heals.length >= 4, `she keeps healing: ${heals.length} heals in 10 s`);
|
||||
assert.ok(heals.every((c) => c.target === v), 'every attack heal goes to her — the only injured ally — never to the protégé');
|
||||
assert.equal(tk.hp, tk.s.maxHp);
|
||||
checkInvariants(h.b);
|
||||
assert.equal(h.b.errors.length, 0);
|
||||
});
|
||||
|
||||
test('the S2 counter (a hit on the protégé) heals the protégé; her attacks still heal the lowest-HP ally', () => {
|
||||
const { h, v, tk, t0 } = field({ enemyAtk: 300, hits: 't_tank' });
|
||||
h.run(8);
|
||||
const counters = h.hooksOf('damaged').filter((c) => c.source === v && c.t >= t0 && (c.dmg?.tags || []).includes('counter'));
|
||||
assert.ok(counters.length >= 3, 'the enemy hitting the protégé draws counters');
|
||||
const heals = h.hooksOf('heal').filter((c) => c.source === v && c.t >= t0);
|
||||
const toTank = heals.filter((c) => c.target === tk), toHer = heals.filter((c) => c.target === v);
|
||||
assert.ok(toTank.length >= counters.length, `each counter heals the protégé (${toTank.length} heals for ${counters.length} counters)`);
|
||||
assert.ok(toHer.length > 0, 'her attacks heal the most injured ally — herself when she is lower than the protégé');
|
||||
checkInvariants(h.b);
|
||||
assert.equal(h.b.errors.length, 0);
|
||||
});
|
||||
@@ -219,7 +219,9 @@ test('1_06 刺玫: 荆藤庇荫 taunts the highest-HP ally in range and counters
|
||||
const counters = dealt(h, u, tagged('counter'));
|
||||
assert.ok(counters.length >= 2);
|
||||
for (const c of counters) approx(c.amount, u.s.atk * bb.atk_scale, 'counter = 20 % ATK arts');
|
||||
assert.ok(heals(h, u).every((c) => c.target === yak), 'trait heal only on the protected ally during the skill');
|
||||
// the counters' trait heal goes to the protected ally; her attacks heal the most injured ally in range — the protected
|
||||
// one here, the only ally hit (test/content/feedback5-vendla-heal.test.js: herself when she is the most injured)
|
||||
assert.ok(heals(h, u).every((c) => c.target === yak), 'trait heals on the protected ally (counters; the most injured)');
|
||||
// talent: the highest max-HP ally in range receives more healing
|
||||
yak.hp = yak.s.maxHp * 0.3;
|
||||
approx(h.b.heal(null, yak, 100), 100 * t.heal_scale, 'heal ×1.08');
|
||||
|
||||
Reference in new issue
Block a user