A 咒愈师's trait heals on every damage she deals; 收割者 / 武者 heal on their skill hits too (#115)

The official trait buffs fire on output damage, not only on a normal attack (buff_template_data vendla_tr / reed2_tr / titi_tr ON_AFTER_OUTPUT_DAMAGE; etlchi_trait etc. ON_OUTPUT_DAMAGE, attackType BUFF filtered for 隐德来希). Skill damage now heals: 缇缇's 凝固的时光 ticks, 焰影苇草 S2 fireballs and 刺玫 S2's counter heal the one ally the skill names (DamageInfo.traitAlly); 隐德来希's S2 blood sickles heal her, capped at her block count per instant. PRTS 分支特性信息 §咒愈师: the heal depends only on the damage value. Contributed by @shanzhaikabi.
This commit is contained in:
shanzhaikabi authored and GitHub committed 2026-10-05 14:20:59 +08:00
1 parent bbff3514a8
commit 763e224b8d
7 files changed
+146 -18

No files matched your search

+14 -6
View File
@@ -476,10 +476,17 @@ export default {
return {
skills: { 'skcom_magic_rage[3]': { kind: 'duration', mods: { aspd: num(skillBbOf(chess, 'skcom_magic_rage[3]').attack_speed) } } },
trait: {
afterHit(battle, u, target, info) {
if (!(info.dealt > 0)) return;
const ally = protege(u) ?? battle.lowestHpAllyInRange(u);
if (ally) battle.heal(u, ally, info.dealt * (u.profile.healRatio ?? 0.5), { tags: ['incantation'] });
// 咒愈师 trait: EVERY damage she deals heals an ally for 50 % of it (professions.js `installIncantation`,
// buff_template_data `vendla_tr` = ON_AFTER_OUTPUT_DAMAGE) — while 荆藤庇荫 runs her S2 says "仅对该角色触发刺玫
// 特性", so her protégé is the target then; otherwise it is the lowest-HP ally in range.
install(battle, u) {
battle.on('damaged', (c) => {
const t = c.target;
if (c.source !== u || !u.alive || !t || t.side !== 'enemy' || !(c.amount > 0)) return;
if (c.type === 'element' || c.type === 'elemental') return;
const ally = (c.dmg && c.dmg.traitAlly) || protege(u) || battle.lowestHpAllyInRange(u);
if (ally) battle.heal(u, ally, c.amount * (u.profile.healRatio ?? 0.5), { tags: ['incantation'] });
}, { owner: u });
},
},
skill: {
@@ -501,9 +508,10 @@ export default {
battle.on('damaged', (ctx) => {
const p = protege(unit);
if (!p || ctx.target !== p || !byEnemyAttack(ctx) || !ctx.source.alive || !unit.canAct) return;
const dealt = battle.dealDamage(unit, ctx.source, { amount: unit.s.atk * num(bb.atk_scale), type: 'arts', isSkill: true, canDodge: false, tags: ['counter'] });
// "并仅对该角色触发刺玫特性": this counter damage is healed by the trait (install above) for the protégé — the
// damage instance names her, so no separate heal here (it would double)
battle.dealDamage(unit, ctx.source, { amount: unit.s.atk * num(bb.atk_scale), type: 'arts', isSkill: true, canDodge: false, tags: ['counter'], traitAlly: p });
battle.fx('counter', { x: ctx.source.x, y: ctx.source.y, id: unit.id });
if (dealt > 0) battle.heal(unit, p, dealt * (unit.profile.healRatio ?? 0.5), { tags: ['incantation'] });
}, { owner: unit });
if (hs !== 1) {
let cacheT = -1, top = null;
+4 -3
View File
@@ -1470,7 +1470,7 @@ function reed2(bb, chess, def) {
}
},
onTick({ battle, unit, dt }) {
const cd = Math.max(0.1, num(bb.cooldown, 1.5)), ratio = num(unit.profile?.healRatio, num(tb.scale, 0.5));
const cd = Math.max(0.1, num(bb.cooldown, 1.5));
for (const F of unit.mem.reedFire || []) {
if (!live(F.a)) continue;
F.acc += dt;
@@ -1480,9 +1480,10 @@ function reed2(bb, chess, def) {
if (!c.length) c = enemiesIn(battle, unit);
if (!c.length) continue;
sortEnemyTargets(battle, F.a, c, null);
const dealt = battle.dealDamage(unit, c[0], { amount: unit.s.atk * num(bb.atk_scale, 1), type: 'arts', isSkill: true, tags: ['skill', 'fireball'] });
// "每1.5秒对一名敌人造成…法术伤害并仅对该干员触发焰影苇草特性": the trait heal (professions.js
// installIncantation) runs for this damage and names the carrier instead of the lowest-HP ally in range
battle.dealDamage(unit, c[0], { amount: unit.s.atk * num(bb.atk_scale, 1), type: 'arts', isSkill: true, tags: ['skill', 'fireball'], traitAlly: F.a });
battle.fx('strike', { x: c[0].x, y: c[0].y, id: c[0].id, src: F.a.id });
if (dealt > 0 && ratio > 0) battle.heal(unit, F.a, dealt * ratio, { tags: ['incantation'] });
}
},
onEnd({ battle, unit }) {