Community report relayed by the owner: 炼金师分支干员的炼金单元无法给不屈者等禁疗的干员提供生命恢复. The
alchemist branch is 锡人 and 引星棘刺. 锡人 S2's recovery was already an hpRegen buff (PRTS 锡人 备注:
"生命恢复的提供方式为增加目标的“生命回复速度”属性,不受治疗加成和禁疗影响"). 引星棘刺 S1 度算浪波 ("每秒回复相当于
攻击力…的生命值") and S2 解构涌潮 ("友方单位每秒恢复相当于攻击力…的生命") carry the same wording and blackboard key
(hp_recovery_per_sec_ratio[_chr]) but called battle.heal, which 不屈者 (no heal from others) and 禁疗 refuse.
Both are now an hpRegen buff per alchemy unit, set at each 1 s pulse until the next (锡人's pattern): the
same amount per second, not scaled by heal bonuses, credited to the target's own regen; S2 skips 孤立
units like every ally effect. Her PRTS page has no 备注 on this; the classification rests on 锡人 and the report.
Golden: roster-014, roster-015, roster-033, roster-034, bond-maniShip-high, bond-soloShip-high,
boss-boss_2-pair, boss-boss_4-pair, boss-boss_6-pair, hidden-boss_8-pair, hidden-boss_10-pair (引星棘刺 on
the board, S2 by default) and coop2-NORMAL-14-standins (h_0 fields her from round 11): her allies' HP
now rises over each second instead of in one lump, and the heal stats move from her to them.
Tests: test/content/feedback7-thorn2-regen.test.js (2; both fail on the parent); the S1 case of
kits_alt_t5 asserts the regen buff instead of a heal of hers.
56 lines
3.6 KiB
JavaScript
56 lines
3.6 KiB
JavaScript
// test/content/feedback7-thorn2-regen.test.js — 引星棘刺's alchemy units restore HP as 生命回复速度 (community report:
|
||
// 炼金师分支干员的炼金单元无法给不屈者等禁疗的干员提供生命恢复). S1 度算浪波 "每秒回复相当于攻击力…的生命值" and S2 解构涌潮
|
||
// "友方单位每秒恢复相当于攻击力…的生命" carry 锡人 S2's wording and blackboard key (hp_recovery_per_sec_ratio), and PRTS 锡人
|
||
// 备注 says that recovery "为增加目标的“生命回复速度”属性,不受治疗加成和禁疗影响" — an hpRegen buff, which 不屈者 (no heal
|
||
// from others) and 禁疗 units take too. Up to 0.2.1 both were heals (battle.heal), which those units refuse.
|
||
// Run: node --test test/content/feedback7-thorn2-regen.test.js
|
||
|
||
import { test } from 'node:test';
|
||
import assert from 'node:assert/strict';
|
||
import { makeBattle, enemyRec, checkInvariants } from '../helpers/battleHarness.js';
|
||
|
||
/** 引星棘刺 (skill `skillIndex`) beside 角峰 (10,5), 折桠 — 不屈者 — (10,6) and a 禁疗 角峰 (10,7); her skill cast at once. */
|
||
function field(skillIndex) {
|
||
const h = makeBattle({
|
||
defs: { enemies: { e_dummy: enemyRec({ key: 'e_dummy', hp: 1e9, speed: 0, atk: 0 }) } },
|
||
timeLimit: 20, autoFinish: false, seed: 2, flags: { dpInit: 99, dpPerSec: 0, dpMax: 999 }, hooks: ['heal'], captureNoisy: true,
|
||
units: [
|
||
{ uid: 1, chessId: 'chess_char_5_15_a', row: 10, col: 4, dir: 'RIGHT', skillIndex },
|
||
{ uid: 2, chessId: 'chess_char_1_02_a', row: 10, col: 5 },
|
||
{ uid: 3, chessId: 'chess_char_2_17_a', row: 10, col: 6 },
|
||
{ uid: 4, chessId: 'chess_char_1_02_a', row: 10, col: 7 },
|
||
],
|
||
});
|
||
h.step();
|
||
const [thorn, plain, unyield, banned] = [1, 2, 3, 4].map((uid) => h.b.allyUnits.find((u) => u.uid === uid));
|
||
h.b.addBuff(banned, { key: 'test:healFree', status: 'healFree', flags: { noHeal: true, healFree: true } }); // 禁疗
|
||
plain.hp = plain.s.maxHp * 0.3;
|
||
unyield.hp = unyield.s.maxHp * 0.2; // S1 picks the lowest HP ratio: its 3×3 covers all three
|
||
banned.hp = banned.s.maxHp * 0.3;
|
||
const hp0 = new Map([plain, unyield, banned].map((a) => [a, a.hp]));
|
||
h.spawn('e_dummy', { pos: [10, 6] });
|
||
thorn.skill.gainSp(999, 'test');
|
||
assert.ok(thorn.skill.activate('manual'), thorn.skill.id);
|
||
h.run(3.2);
|
||
return { h, thorn, plain, unyield, banned, gained: (a) => a.hp - hp0.get(a) };
|
||
}
|
||
|
||
for (const [skillIndex, id, key] of [[0, 'skchr_thorn2_1', 'hp_recovery_per_sec_ratio'], [1, 'skchr_thorn2_2', 'hp_recovery_per_sec_ratio_chr']]) {
|
||
test(`引星棘刺 ${id}: the alchemy unit's 生命回复速度 reaches 不屈者 (折桠) and 禁疗 operators as much as the others`, () => {
|
||
const { h, thorn, plain, unyield, banned, gained } = field(skillIndex);
|
||
assert.equal(thorn.skill.id, id);
|
||
assert.equal(unyield.profile.noHeal, true, '不屈者: no heal from others');
|
||
const perSec = thorn.s.atk * thorn.def.skill.bb[key];
|
||
for (const a of [plain, unyield, banned]) {
|
||
const regen = a.buffs.find((b) => b.source === thorn && b.mods?.hpRegen > 0);
|
||
assert.ok(regen, `${a.defId}: an hpRegen buff`);
|
||
assert.ok(Math.abs(regen.mods.hpRegen - perSec) < 1e-6, `${regen.mods.hpRegen} ≈ ${perSec}`);
|
||
assert.ok(gained(a) > perSec, `${a.defId} recovered ${gained(a).toFixed(1)}`);
|
||
}
|
||
assert.ok(Math.abs(gained(unyield) - gained(plain)) < 1, 'the same for 不屈者');
|
||
assert.ok(Math.abs(gained(banned) - gained(plain)) < 1, 'the same under 禁疗');
|
||
assert.equal(h.hooksOf('heal').filter((c) => c.source === thorn).length, 0, 'no heal of hers (治疗加成 does not apply)');
|
||
checkInvariants(h.b);
|
||
});
|
||
}
|