feedback5 WL: Touch follows PRTS — S3's extra heal is 30 % of the base with its own recipient's boost, 「低于」 half HP, 攫升 on every heal she outputs, 超脱 on a dying forced exit

The shared code of the 外勤医疗 strategy's Touch and the Touch 补位 stand-in (content/tokens.js touchGospel /
mapCharTalents), against PRTS Touch(卫戍协议) and its 备注 / 修正:
- S3 恳切福音's extra heal: 30 % of the main heal's base (before the ×1.35 / ×1.40), a heal of its own — its recipient
  below half HP gets the boost (and the elite's PHY-X), 备注 「额外治疗可触发技能后半段的治疗量提高效果」; it goes to the
  lowest HP ratio of the main target and its 4 orthogonal neighbours, a full-HP unit included (x-5,
  「可治疗生命值已满单位」). The touchExtra / touchMainHeal block is gone.
- The boost needs HP strictly below half (修正 「低于」, was 「不高于」).
- 攫升: every heal she outputs gives SP — a heal on herself and one that restores nothing too (备注 「无需实际产生治疗量」);
  still no device, no unit without a skill, and not her own HP-regeneration tick.
- 超脱: a forced exit that plays the death animation counts like a knock-out (备注 「如史尔特尔的天赋效果」). Battle.retreat
  takes `dying` and the death hook carries it: 史尔特尔's 余烬 and 骑士戒律 + 竞技旗 set it; planned exits (耀骑士临光 S2,
  伊内丝 S3), the 商人's automatic 撤退 and the 突袭 jump do not. A battle has no player 撤退 command.

Golden moved: roster-041 (the strategy's Touch heals differently: S3 extra heal / boost), standin-03, standin-04,
standin-08, standin-09, standin-10 (Touch standing in for 塞雷娅 / 塑心 / 纯烬艾雅法拉), coop2-NORMAL-14-standins (the
human seat plays 外勤医疗, so its Touch takes part). Docs: SIM.md (death hook `dying`, retreat option, the forced-exit
paragraph).
This commit is contained in:
sganggs committed 2026-10-05 20:47:06 +08:00
1 parent ce0d85c78a
commit 8b7316d93e
12 files changed
+244 -127

No files matched your search

+9 -6
View File
@@ -495,7 +495,7 @@ test('炎佑: spawnYanyou — flying ally, bond stats, 3 targets with burn + ele
checkInvariants(h.b);
});
test('band map characters: spawnMapChar puts 预备干员-医疗 at its stage slot; Touch 恳切福音 heals ×heal_scale on ≤50 % HP allies', REAL, () => {
test('band map characters: spawnMapChar puts 预备干员-医疗 at its stage slot; Touch 恳切福音 heals ×heal_scale on allies below 50 % HP', REAL, () => {
const g = guard({ stats: { maxHp: 10000 } });
const h = makeBattle({ stageId: 'act2autochess_m01', defs: { chess: { test_guard: g } }, units: [{ chessId: 'test_guard', row: 10, col: 3 }], autoFinish: false, timeLimit: 60,
setup: (b) => b.on('heal', (c) => { if (c.source?.defId === TOKEN_IDS.touch) (b.mem ??= []).push({ amount: c.amount, ratio: c.target.hpRatio, active: c.source.skill.active }); }, { priority: -500 }) });
@@ -515,7 +515,7 @@ test('band map characters: spawnMapChar puts 预备干员-医疗 at its stage sl
gu.hp = 3000;
h.run(4);
const bb = touch.skill.bb;
const low = h.b.mem.find((x) => x.active && x.ratio <= bb.hp_ratio);
const low = h.b.mem.find((x) => x.active && x.ratio < bb.hp_ratio);
assert.ok(low, 'healed a low ally');
approx(low.amount, touch.s.atk * bb.heal_scale, 1e-6, 'boosted heal');
checkInvariants(h.b);
@@ -1090,7 +1090,7 @@ test('预备干员-医疗: stat talent 攻击提升 (+4 % ATK) on top of the dat
approx(med.s.atk, tokDef(TOKEN_IDS.reserveMedic).stats.atk * (1.04 + 0.5), 1e-9, '治疗强化·β型 +50 %');
});
test('Touch talents: 攫升 +3 SP to the healed unit, 超脱 +5 SP when an operator in range is knocked out; extra heal = 30 % of the main heal', REAL, () => {
test('Touch talents: 攫升 +3 SP to the healed unit, 超脱 +5 SP when an operator in range is knocked out; extra heal = 30 % of the main heal\'s base, ×heal_scale on its own low recipient', REAL, () => {
const g = chessRec({ id: 'test_sp', stats: { maxHp: 10000, atk: 0, spRecovery: 0 }, skill: { spCost: 100, initSp: 0 } });
const h = makeBattle({ stageId: 'act2autochess_m01', defs: { chess: { test_sp: g } }, units: [{ chessId: 'test_sp', row: 10, col: 3, uid: 1 }, { chessId: 'test_sp', row: 11, col: 3, uid: 2 }], autoFinish: false, timeLimit: 60,
setup: (b) => b.on('heal', (c) => { if (c.source?.defId === TOKEN_IDS.touch) (b.mem ??= []).push({ t: c.target.id, amount: c.amount, ratio: c.target.hpRatio }); }, { priority: -500 }) });
@@ -1105,14 +1105,17 @@ test('Touch talents: 攫升 +3 SP to the healed unit, 超脱 +5 SP when an opera
h.b.dealDamage(null, b2, { amount: 1e6, type: 'true' });
assert.equal(b2.alive, false);
approx(touch.skill.sp - sp0, 5, 0.1, '超脱');
// skill: main heal (×1.5 at ≤ 50 %) + extra 30 % of it, not boosted again
// skill: main heal (×1.5 below 50 %) + an extra heal of 30 % of its base (ATK) on the lowest-ratio unit of the target and
// its neighbours — the target again, still below half after the main heal: ×1.5 on its own (PRTS 技能3 备注)
h.b.mem = [];
touch.skill.activate('test', { free: true });
a.hp = 4000;
a.hp = 2000;
assert.ok(h.runUntil(() => h.b.mem.length >= 2, 5));
const [main, extra] = h.b.mem;
assert.deepEqual([main.t, extra.t], [a.id, a.id]);
approx(main.amount, touch.s.atk * 1.5, 1e-6, 'main heal boosted');
approx(extra.amount, main.amount * 0.3, 1e-6, 'extra = 30 % of the main heal');
assert.ok(extra.ratio < 0.5);
approx(extra.amount, touch.s.atk * 0.3 * 1.5, 1e-6, 'extra = 30 % of the base, boosted on its low recipient');
checkInvariants(h.b);
});