The owner's ACTIVE_RANGE rule (a MANUAL skill whose running range strictly contains the operator's own) for two skills whose running range is no data range (O1, O11 reports): op-aphris.js adds the beam's path as a content trigger range; op-vvana.js switches S3 to ACTIVE_RANGE on 3-2 once its first cast of a deployment ended (DEFAULT again on redeploy) through a new additive SkillRuntime.setTrigger(rule, grid). The scan of the wave 2-3 reports and the 41 candidate skills is in the doc draft (others: target-centred, already fixed, or owner questions). Golden: diy-045 (谬因 S2 fires for enemies beyond her 6 tiles) and diy-078 (薇薇安娜 S3: skill timing in hooks / snapshots only) moved.
289 lines
20 KiB
JavaScript
289 lines
20 KiB
JavaScript
// server/sim/content/kits/ops/op-vvana.js — 薇薇安娜 (char_4098_vvana) 自选 operator kit: 6★ 术战者 (近卫), an owned-6★ pick
|
||
// of the tier-5 and tier-6 自选 slots; every skill, both talents, the trait and both modules at every form.
|
||
// Kit contract and the 自选 rules: ../README.md ("How to add an operator (自选)").
|
||
//
|
||
// Forms (data/backups.json units.char_4098_vvana, the DIY slot statuses): normal = E2 Lv1, skills at rank 4, no module;
|
||
// elite = E2 Lv60, rank 7, the picked module at stage 1 (tier 5) or 3 (tier 6). Potential 0 [ASSUMED: no account].
|
||
// Sources: character_table / skill_table / battle_equip_table (zh_CN, as built into backups.json); PRTS 薇薇安娜 (备注 of
|
||
// 散华, 光影迅捷剑 and “明灭”, the AFT-Δ trait note); gamedata_const ba.charged 蓄力, ba.shield 护盾, ba.steal 偷取,
|
||
// ba.magicfragile 法术脆弱; PRTS 作战机制 (伤害流程, 远近途径 "有弹道的攻击固定为10,无弹道的攻击固定为01"); range_table 3-2; the
|
||
// client's battle data read from the local install — charpack char_4098_vvana, battle/prefabs [uc]skills skchr_vvana_1/2/3
|
||
// and [uc]equips vvana_equip_*, buff_template_data vvana_* (the templates are named below).
|
||
// - Trait (术战者) "攻击造成法术伤害": the profession (melee arts, ground only, block 1, 1.25 s).
|
||
// - Module AFT-D 目不能及之处: trait "攻击灼燃损伤爆发期间的目标时额外造成攻击力15%的元素伤害" (trait bb ep_damage_ratio; PRTS
|
||
// "※于任意非本模组特性的伤害的输出伤害时触发"; vvana_e_002_trait: ON_OUTPUT_DAMAGE, not its own damage, the target in its FIRE
|
||
// 爆发冷却 → ELEMENT damage ep_damage_ratio × ATK): every damage instance she outputs on an enemy holding the `burnBurst` lock
|
||
// (docs/SIM.md §3) — at the output (the `hit` step, before the target's dodge / cancel) — adds ep_damage_ratio × ATK
|
||
// 元素伤害. Stage 3: 燃烛施明's 灼燃损伤 (below).
|
||
// - Module AFT-Y “最后一行”: trait "自身阻挡的敌人受到10%的法术脆弱效果" (trait bb damage_scale 1.1; vvana_equip_2_*: weak[magic]
|
||
// to every blockee): the 法术脆弱 status (同名效果取最高) on each enemy she blocks, renewed every 0.2 s for 0.3 s (as 史尔特尔's
|
||
// AFT-Y). Stage 3: 散华 25 %, 2 layers (below).
|
||
// - T1 燃烛施明 "造成的法术伤害+8%,受到的物理和法术伤害-8%。攻击范围内存在精英或领袖敌人时,该效果提升至2倍" (damage_scale_m,
|
||
// damage_resistance_pm, super_scale; vvana_t_1[self] / [aura] / [super]: an aura on the enemies of her current range —
|
||
// targetMotion ALL, flyers too, no untargetable one — and on those she blocks; an ELITE / BOSS one swaps [self] for [super],
|
||
// ×super_scale): artsDealtMul 1 + 0.08 f, phys / artsTakenMul 1 − 0.08 f, f = super_scale while such an enemy is there, else
|
||
// 1 — re-read every tick and before every hit she deals or takes. AFT-D stage 3 "攻击附带相当于9%伤害的灼燃损伤"
|
||
// (ep_damage_ratio_m; the templates' ON_AFTER_OUTPUT_DAMAGE on her non-continuous arts damage, ApplyElementDamageBasedOnDamageValue
|
||
// FIRE): each arts damage instance of hers that removes HP carries ep × f × that damage as 灼燃损伤.
|
||
// - T2 散华 "攻击精英或领袖敌人时,有18%概率获得一层仅抵挡近战攻击的护盾(最多1层)" (prob; AFT-Y stage 3: 25 %, max_stack_cnt 2;
|
||
// S3: × talent_scale; vvana_t_2: ON_OUTPUT_DAMAGE on an ELITE_AND_BOSS target, Dice prob, CreateBuff vvana_t_2[block_melee] —
|
||
// UNIQUE without max_stack_cnt, STACK up to it with — so a roll at the cap changes nothing, PRTS "※自身未存在本天赋的护盾时,每对
|
||
// 符合条件的目标造成一次伤害判定一次本天赋"): one roll per damage instance she outputs on an elite / leader (any damage — the AFT-D
|
||
// rider too — at the output, before the target's dodge / cancel). vvana_t_2[block_melee]: ON_TAKE_DAMAGE from an ENEMY source
|
||
// with apply way MELEE → BlockDamage, one layer spent (ba.shield "每层护盾可以抵挡一次伤害"; PRTS "※仅来源于敌方单位的近战途径伤害
|
||
// 可触发本天赋的护盾"): an enemy's damage that did not fly as a projectile (DamageInfo `isProjectile`, ai.js enemyAttack) is
|
||
// negated whole in a late `hit` handler (cancel, as the enemies' 护盾 layers in content/enemies.js); 无来源 damage has no enemy
|
||
// source. The enemy content's own projectiles (invisible / leaders / fly kits) are not marked and count as melee [ASSUMED].
|
||
// - S1 光影迅捷剑 (AUTO, 2 charges, data DEFAULT — a "next attack" waits for her attack): the next attack at atk_scale × ATK,
|
||
// S1_HITS hits (S1_Attack2, `_additionalTimes` 1). 蓄力 (ba.charged "回复至上限2倍时进入蓄力状态…任何时候开启均消耗全部技力"; PRTS
|
||
// 备注 "未满足蓄力所需技力时…仅消耗技能最低所需技力" / "“蓄力”模式将在下一次技能结束时结束" / "“蓄力”模式期间…攻击范围变为3-2";
|
||
// the skill's toggle at SP ratio 1 puts vvana_s_1[mode] — mode 1, range 3-2 — whose ON_SKILL_START clears the SP and
|
||
// ON_SKILL_FINISH ends it; S1_Attack, `_additionalTimes` 2 on 3-2, needs its mark): with both charges stored her own range is
|
||
// 3-2 (the DEFAULT trigger's initial range and the card follow it) until the next end of the skill; a cast then hits
|
||
// S1_CHARGED_HITS times and spends every charge, a cast below that spends one charge.
|
||
// - S2 烛燃影息 (MANUAL, data DEFAULT, 28 / 30 s; mode 2): ATK +atk, DEF +def, block +block_cnt, every attack hits all the
|
||
// enemies she blocks; each attack picks Attack_Once / Attack_Twice (attack@prob_once / attack@prob_twice: one roll per
|
||
// attack), the double hit at attack@atk_scale_twice × ATK carrying vvana_s_2[steal] (ON_BEFORE_TARGET_APPLY_MODIFIER of each
|
||
// damage → vvana_steal_attack_speed: ba.steal "减少目标的基础属性作为自身加成,目标减少和自身加成的属性不超过指定上限(同类属性取最高)"):
|
||
// each enemy it hits loses attack@steal_atk_speed ASPD (at most attack@steal_atk_speed_max per enemy, the largest of several
|
||
// thieves) and she gains as much (at most the max in all) — "持续至技能结束或薇薇安娜离场"; a dodged hit steals too (the step
|
||
// comes before the target's checks).
|
||
// - S3 “明灭” (MANUAL, data DEFAULT, 15 s): attack interval +base_attack_time s (flat), ATK +atk, DEF +def, RES
|
||
// +magic_resistance, S3_HITS hits per attack, 散华 × talent_scale, elite / leader enemies first (targeting priority 'elite',
|
||
// after the enemies she blocks — the engine's order). "第二次及以后使用时,攻击距离+2,攻击变为三连击,持续时间延长至25秒" (PRTS
|
||
// 备注 "每次部署薇薇安娜时,重新计算该技能的使用次数" / "首次技能结束后,本技能的技能范围永久扩大至3-2"; vvana_s_3[check]: a
|
||
// skill triggered before ⇒ the enhance mark and duration_plus = enhance_duration, vvana_s_3: mode 4 instead of 3): from her
|
||
// second cast of a deployment the skill runs enhance_duration s with S3_LATER_HITS hits on the 3-2 range (her own grid while
|
||
// it runs: the card shows it). Trigger: the data's DEFAULT on her own range for the first cast of a deployment; once it
|
||
// has ended the owner's ACTIVE_RANGE rule (2026-10-05: a MANUAL skill whose running range strictly contains her own casts
|
||
// with an enemy inside that range) on the 3-2 — no data range carries it, so the kit sets it (skill.setTrigger, 0.2.0 WE2,
|
||
// follow-up #16; O11's report) — and DEFAULT again at her next deployment.
|
||
|
||
import { num, talentBb, traitBb, skillRec, up, batMod } from '../shared/tier1.js';
|
||
import { isElite, elementDmg, enemiesIn } from '../shared/tier6.js';
|
||
import { hasHp } from '../../../damage.js';
|
||
|
||
const S1 = 'skchr_vvana_1';
|
||
const S2 = 'skchr_vvana_2';
|
||
const S3 = 'skchr_vvana_3';
|
||
/** range_table 3-2: the 蓄力 range (PRTS S1 备注) and S3's range from its second cast (PRTS S3 备注). */
|
||
const RANGE_3_2 = Object.freeze([[0, 0], [0, 1], [0, 2], [0, 3]].map((p) => Object.freeze(p)));
|
||
/** S1 "并连续攻击两次" / 蓄力 "改为连续攻击三次"; S2 "二连击"; S3 "攻击变为二连击" / later "攻击变为三连击" — text only. */
|
||
const S1_HITS = 2, S1_CHARGED_HITS = 3, S2_TWICE_HITS = 2, S3_HITS = 2, S3_LATER_HITS = 3;
|
||
/** AFT-Y: the 法术脆弱 renewal (as 史尔特尔's AFT-Y, kits/ops/chess_char_5_07-surtr.js). */
|
||
const FRAGILE_IV = 0.2, FRAGILE_DUR = 0.3;
|
||
const AFTD_TAG = 'vvanaAftD';
|
||
const CANDLE_KEY = 'talent:vvana:candle';
|
||
const SHIELD_KEY = 'talent:vvana:shield';
|
||
const LOOT_KEY = 'skill:vvana:loot';
|
||
const STOLEN_KEY = 'skill:vvana:stolen';
|
||
/** `hit` order: 燃烛施明 re-reads its factor first; the output effects (AFT-D, 散华's roll) come before the target-side
|
||
* handlers (priority 0: the enemies' own 护盾, guards); 散华's 护盾 itself last (a guard that cancelled first spends none). */
|
||
const CANDLE_PRIORITY = 100, OUTPUT_PRIORITY = 50, SHIELD_PRIORITY = -500;
|
||
|
||
const bbOf = (chess, id) => skillRec(chess, id)?.bb ?? {};
|
||
const tagged = (d, tag) => !!d && Array.isArray(d.tags) && d.tags.includes(tag);
|
||
/** Her own range grid (the form's 1-1), or the range she switches to. */
|
||
function setGrid(battle, unit, grid) {
|
||
if (!grid || unit.rangeGrid === grid) return;
|
||
unit.rangeGrid = grid;
|
||
battle.refreshRange(unit);
|
||
}
|
||
|
||
// ---- S2 偷取: the losses of the enemies, one battle-wide table (同类属性取最高 over several thieves) ---------------------
|
||
/** battle → Map(enemy → Map(thief id → ASPD stolen)). */
|
||
const STOLEN = new WeakMap();
|
||
const stolenOf = (battle) => { let m = STOLEN.get(battle); if (!m) STOLEN.set(battle, (m = new Map())); return m; };
|
||
function applyLoss(battle, e, per) {
|
||
let a = 0;
|
||
for (const v of per.values()) a = Math.max(a, v);
|
||
if (!(a > 0)) { battle.removeBuff(e, STOLEN_KEY); return; }
|
||
battle.addBuff(e, { key: STOLEN_KEY, mods: { aspd: -a }, tags: ['steal'] });
|
||
}
|
||
function steal(battle, unit, e, n, cap) {
|
||
if (!(n > 0) || !e || !e.alive || e.side !== 'enemy') return;
|
||
const losses = stolenOf(battle);
|
||
let per = losses.get(e);
|
||
if (!per) losses.set(e, (per = new Map()));
|
||
per.set(unit.id, Math.min(cap, (per.get(unit.id) ?? 0) + n));
|
||
applyLoss(battle, e, per);
|
||
(unit.mem.vvanaVictims ??= new Set()).add(e);
|
||
unit.mem.vvanaLoot = Math.min(cap, (unit.mem.vvanaLoot ?? 0) + n);
|
||
battle.addBuff(unit, { key: LOOT_KEY, mods: { aspd: unit.mem.vvanaLoot }, tags: ['skill'] });
|
||
}
|
||
/** "持续至技能结束或薇薇安娜离场": she gives everything back. */
|
||
function returnLoot(battle, unit) {
|
||
battle.removeBuff(unit, LOOT_KEY);
|
||
unit.mem.vvanaLoot = 0;
|
||
const losses = stolenOf(battle);
|
||
for (const e of unit.mem.vvanaVictims ?? []) {
|
||
const per = losses.get(e);
|
||
if (!per || !per.delete(unit.id)) continue;
|
||
if (e.alive) applyLoss(battle, e, per);
|
||
}
|
||
unit.mem.vvanaVictims = new Set();
|
||
}
|
||
|
||
export default {
|
||
char_4098_vvana: (bb, chess) => {
|
||
const t0 = talentBb(chess, 0), t1 = talentBb(chess, 1);
|
||
const tb = traitBb(chess);
|
||
const b1 = bbOf(chess, S1), b2 = bbOf(chess, S2), b3 = bbOf(chess, S3);
|
||
const twice = num(b2['attack@atk_scale_twice'], 1);
|
||
return {
|
||
skills: {
|
||
[S1]: {
|
||
kind: 'charges',
|
||
attack: { atkScale: num(b1.atk_scale, 1), hitsFn: (b, u) => (u.mem.vvanaCast === 'charged' ? S1_CHARGED_HITS : S1_HITS) },
|
||
onStart({ unit, skill }) {
|
||
// after activate's one charge: still ≥ max − 1 ⇒ every charge was stored (蓄力) — a charged cast spends them all
|
||
const charged = !!unit.mem.vvanaCharged || (skill.maxCharges > 1 && skill.charges >= skill.maxCharges - 1);
|
||
unit.mem.vvanaCast = charged ? 'charged' : 'plain';
|
||
if (charged) { skill.charges = 0; skill.sp = 0; }
|
||
},
|
||
onEnd({ unit }) { unit.mem.vvanaCast = null; },
|
||
},
|
||
[S2]: {
|
||
kind: 'duration',
|
||
mods: { atkPct: num(b2.atk), defPct: num(b2.def), blockCnt: num(b2.block_cnt) },
|
||
attack: {
|
||
hitAllBlocked: true,
|
||
hitsFn: (b, u) => (u.mem.vvanaTwice ? S2_TWICE_HITS : 1),
|
||
dmgMul: (b, u) => (u.mem.vvanaTwice ? twice : 1),
|
||
onEachHit({ battle, unit, target, kind }) {
|
||
if (unit.mem.vvanaTwice && kind === 'main') steal(battle, unit, target, num(b2['attack@steal_atk_speed']), num(b2['attack@steal_atk_speed_max'], Infinity));
|
||
},
|
||
},
|
||
onStart({ battle, unit }) { returnLoot(battle, unit); },
|
||
onEnd({ battle, unit }) { unit.mem.vvanaTwice = false; returnLoot(battle, unit); },
|
||
},
|
||
[S3]: {
|
||
kind: 'duration',
|
||
mods: { batPct: batMod(b3.base_attack_time, chess), atkPct: num(b3.atk), defPct: num(b3.def), resFlat: num(b3.magic_resistance) },
|
||
targeting: { priority: 'elite' },
|
||
attack: { hitsFn: (b, u) => (u.mem.vvanaS3Later ? S3_LATER_HITS : S3_HITS) },
|
||
onStart({ battle, unit, skill }) {
|
||
const later = (unit.mem.vvanaS3Casts ?? 0) >= 1;
|
||
unit.mem.vvanaS3Casts = (unit.mem.vvanaS3Casts ?? 0) + 1;
|
||
unit.mem.vvanaS3Later = later;
|
||
if (!later) return;
|
||
skill.timeLeft = Math.max(0.01, num(b3.enhance_duration, skill.duration));
|
||
setGrid(battle, unit, RANGE_3_2);
|
||
},
|
||
onEnd({ battle, unit, skill }) {
|
||
if (unit.mem.vvanaS3Later) setGrid(battle, unit, unit.def?.rangeGrid);
|
||
unit.mem.vvanaS3Later = false;
|
||
// its later casts run on the 3-2: from now the owner's ACTIVE_RANGE rule there (see the header)
|
||
if ((unit.mem.vvanaS3Casts ?? 0) >= 1) skill.setTrigger('ACTIVE_RANGE', RANGE_3_2);
|
||
},
|
||
},
|
||
},
|
||
talents: [
|
||
{ install(battle, unit) { // 燃烛施明: arts dealt +, phys / arts taken −, ×super_scale with an elite / leader there
|
||
const dsm = num(t0.damage_scale_m), drp = num(t0.damage_resistance_pm), sup = num(t0.super_scale, 1), ep = num(t0.ep_damage_ratio_m);
|
||
const factor = () => (enemiesIn(battle, unit, unit.rangeKeys).some(isElite) || unit.blocking.some(isElite) ? sup : 1);
|
||
const check = () => {
|
||
if (!up(unit)) return;
|
||
const f = factor();
|
||
if (unit.mem.vvanaCandle === f && unit.findBuff(CANDLE_KEY)) return;
|
||
unit.mem.vvanaCandle = f;
|
||
battle.addBuff(unit, { key: CANDLE_KEY, mods: { artsDealtMul: 1 + dsm * f, physTakenMul: 1 - drp * f, artsTakenMul: 1 - drp * f }, data: { f }, tags: ['talent'] });
|
||
};
|
||
battle.on('tick', check, { owner: unit });
|
||
battle.on('battleStart', check, { owner: unit });
|
||
battle.on('deploy', (c) => { if (c.unit === unit) { unit.mem.vvanaCandle = null; check(); } }, { owner: unit });
|
||
// exact at the damage: re-read before any hit she deals or takes is resolved (the pipeline reads both units'
|
||
// stats after the `hit` hook)
|
||
battle.on('hit', (c) => { if (c.source === unit || c.target === unit) check(); }, { owner: unit, priority: CANDLE_PRIORITY });
|
||
if (!(ep > 0)) return;
|
||
// AFT-D stage 3: 攻击附带相当于9%伤害的灼燃损伤 (× the same factor) — her arts damage that removed HP
|
||
battle.on('damaged', (c) => {
|
||
const d = c.dmg;
|
||
if (c.source !== unit || c.type !== 'arts' || tagged(d, 'dot') || !(c.amount > 0) || !c.target || c.target.side !== 'enemy') return;
|
||
elementDmg(battle, unit, c.target, 'burn', c.amount * ep * (unit.mem.vvanaCandle ?? 1), ['talent']);
|
||
}, { owner: unit });
|
||
} },
|
||
{ install(battle, unit) { // 散华: a melee-only 护盾 layer from her damage on elite / leader enemies
|
||
const p = num(t1.prob), max = Math.max(1, Math.floor(num(t1.max_stack_cnt, 1)));
|
||
const s3Scale = num(b3.talent_scale, 1);
|
||
const layers = () => unit.findBuff(SHIELD_KEY)?.data?.n ?? 0;
|
||
const setLayers = (n) => {
|
||
if (n > 0) battle.addBuff(unit, { key: SHIELD_KEY, data: { n }, visible: true, tags: ['talent'] });
|
||
else battle.removeBuff(unit, SHIELD_KEY);
|
||
};
|
||
battle.on('hit', (c) => {
|
||
if (c.source !== unit || !isElite(c.target) || !up(unit)) return;
|
||
const have = layers();
|
||
if (have >= max) return;
|
||
const prob = p * (unit.skill?.active && unit.skill.id === S3 ? s3Scale : 1);
|
||
if (!(prob > 0) || !battle.rng.chance(prob)) return;
|
||
setLayers(have + 1);
|
||
battle.fx('shield', { x: unit.x, y: unit.y, id: unit.id });
|
||
}, { owner: unit, priority: OUTPUT_PRIORITY });
|
||
battle.on('hit', (c) => {
|
||
if (c.target !== unit || c.dmg.cancel) return;
|
||
const s = c.source;
|
||
if (!s || s.side !== 'enemy' || c.dmg.isProjectile) return;
|
||
const have = layers();
|
||
if (!(have > 0)) return;
|
||
c.dmg.cancel = true;
|
||
setLayers(have - 1);
|
||
battle.fx('shieldBreak', { x: unit.x, y: unit.y, id: unit.id });
|
||
}, { owner: unit, priority: SHIELD_PRIORITY });
|
||
} },
|
||
],
|
||
install(battle, unit) {
|
||
const own = unit.def?.rangeGrid;
|
||
// S1's 蓄力 mode: both charges stored ⇒ her range is 3-2 until the next end of the skill
|
||
if (unit.skill?.id === S1) {
|
||
const leave = () => { unit.mem.vvanaCharged = false; setGrid(battle, unit, own); };
|
||
battle.on('tick', () => {
|
||
const sk = unit.skill;
|
||
if (!up(unit) || unit.mem.vvanaCharged || !sk || !(sk.maxCharges > 1) || sk.charges < sk.maxCharges) return;
|
||
unit.mem.vvanaCharged = true;
|
||
setGrid(battle, unit, RANGE_3_2);
|
||
}, { owner: unit });
|
||
battle.on('skillEnd', (c) => { if (c.unit === unit && c.skill.id === S1 && unit.mem.vvanaCharged) leave(); }, { owner: unit });
|
||
battle.on('deploy', (c) => { if (c.unit === unit) leave(); }, { owner: unit });
|
||
}
|
||
// S2: one Attack_Once / Attack_Twice pick per attack while it runs
|
||
if (unit.skill?.id === S2) {
|
||
const prob = num(b2['attack@prob_twice']);
|
||
battle.on('beforeAttack', (c) => {
|
||
if (c.attacker !== unit) return;
|
||
unit.mem.vvanaTwice = !!(unit.skill?.active && unit.skill.id === S2) && prob > 0 && battle.rng.chance(prob);
|
||
}, { owner: unit });
|
||
battle.on('death', (c) => { if (c.unit === unit) returnLoot(battle, unit); }, { owner: unit });
|
||
}
|
||
// S3: the cast count of a deployment ("每次部署…重新计算"), her own range back
|
||
if (unit.skill?.id === S3) {
|
||
battle.on('deploy', (c) => {
|
||
if (c.unit !== unit) return;
|
||
unit.mem.vvanaS3Casts = 0;
|
||
unit.mem.vvanaS3Later = false;
|
||
setGrid(battle, unit, own);
|
||
if (unit.skill?.id === S3) unit.skill.setTrigger('DEFAULT', null); // the first cast of a deployment: the data's rule
|
||
}, { owner: unit });
|
||
}
|
||
// AFT-D: 元素伤害 at the output of every damage of hers on an enemy in its 灼燃 爆发冷却 (not on this rider's own)
|
||
const er = num(tb.ep_damage_ratio);
|
||
if (er > 0) {
|
||
battle.on('hit', (c) => {
|
||
const t = c.target;
|
||
if (c.source !== unit || !t || t.side !== 'enemy' || tagged(c.dmg, AFTD_TAG) || !hasHp(t) || !t.findBuff('burnBurst')) return;
|
||
battle.dealDamage(unit, t, { amount: unit.s.atk * er, type: 'elemental', element: 'burn', canDodge: false, tags: [AFTD_TAG, 'dot'] });
|
||
}, { owner: unit, priority: OUTPUT_PRIORITY });
|
||
}
|
||
// AFT-Y: 自身阻挡的敌人受到10%的法术脆弱效果
|
||
const fragile = num(tb.damage_scale, 1) - 1;
|
||
if (fragile > 0) {
|
||
battle.every(FRAGILE_IV, () => {
|
||
if (!up(unit)) return;
|
||
for (const e of unit.blocking) if (e.alive) battle.applyStatus(e, 'artsFragile', { duration: FRAGILE_DUR, value: fragile, source: unit });
|
||
}, { owner: unit });
|
||
}
|
||
},
|
||
};
|
||
},
|
||
};
|