feedback5 R4: one file per operator kit — kits/tier1..6.js split into kits/ops/<chessId>-<codename>.js (129 kits), kits/shared/tier1..6.js (the helpers two or more kits of a tier use, and each tier's header notes) and kits/index.js (the registry, same keys in the same order); the tier files become re-export shims

Pure move: every line of a kit, of a helper and of the tier headers is copied verbatim (only the headers' first
line names the new file); a helper used by one kit moved into that kit's file. Glue only: the generated imports,
`export default { … }` around each registry entry, `export { … }` lists in shared/tier2..6.js, and tier4's
`(bb, chess, def)` default-argument wrapper as shared/tier4.js `withDefaults` (applied in each tier-4 kit file).
kits/index.js loads every kit file with a guarded dynamic import (browser-safe, no directory listing); tierN.js
re-export the tier registry (TIER_KITS) and their old named exports (tier1 helpers + tinmanKit, tier6
PITHST_ELEMENTS). The merged registry, every tier default and named export have the same keys, order, frozenness
and function sources as before. test/docs-consistency.test.js reads the moved code at its new paths.
Golden: GOLDEN_FULL=1 node --test test/golden.test.js unchanged.
This commit is contained in:
sganggs committed 2026-10-05 16:13:56 +08:00
1 parent 6b489b1776
commit 1169102d46
143 files changed
+12924 -11784

No files matched your search

@@ -0,0 +1,73 @@
// server/sim/content/kits/ops/chess_char_1_06-vendla.js — 刺玫 (char_494_vendla) kit, tier 1.
// Conventions of the tier-1 kits: ../shared/tier1.js; kit contract and rules: ../README.md.
import { num, talentBb, up, byEnemyAttack, alliesInGridOf, skillBbOf } from '../shared/tier1.js';
export default {
// ---------------------------------------------------------------------------------------------------------------
// 1_06 刺玫 荆藤庇荫: ATK +atk; the ally with the highest max HP in range gets taunt +taunt_level; whenever that ally is
// attacked, 刺玫 deals atk_scale × ATK arts to the attacker, and her trait heal (scale × damage) only goes to that ally.
// 土壤基肥改良: the highest-max-HP ally in range receives heal_scale × healing ("受到的治疗效果提升") — never its natural /
// skill HP regeneration (the 生命回复速度 attribute is "不受治疗加成影响": 宴 分神, 角峰 体能强化; PRTS).
// Alternate S1 战术咏唱·γ型: ASPD +attack_speed (the trait heal keeps going to the most injured ally in range).
// Elite module INC-X (heal 60 % of the damage) is the incantation profile of the module trait (TUNE.incantationmedic).
chess_char_1_06_a: (bb, chess) => {
const hs = num(talentBb(chess, 0).heal_scale, 1);
const tauntKey = 'vendla:taunt';
// the protégé only exists while 荆藤庇荫 runs (mem.protege is set by its onStart only)
const protege = (u) => (u.skill?.active && up(u.mem.protege) ? u.mem.protege : null);
return {
skills: { 'skcom_magic_rage[3]': { kind: 'duration', mods: { aspd: num(skillBbOf(chess, 'skcom_magic_rage[3]').attack_speed) } } },
trait: {
// 咒愈师 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: {
kind: 'duration', mods: { atkPct: num(bb.atk) },
onStart({ battle, unit, skill }) {
const cands = alliesInGridOf(battle, unit).sort((a, b) => b.s.maxHp - a.s.maxHp || a.deploySeq - b.deploySeq);
const p = cands[0] ?? null;
unit.mem.protege = p;
if (!p) return;
battle.addBuff(p, { key: tauntKey, duration: skill.duration + 0.1, mods: { taunt: num(bb.taunt_level, 1) }, visible: true, source: unit });
battle.fx('taunt', { x: p.x, y: p.y, id: p.id });
},
onEnd({ battle, unit }) {
if (unit.mem.protege) battle.removeBuff(unit.mem.protege, tauntKey);
unit.mem.protege = null;
},
},
talents: [{ install(battle, unit) {
battle.on('damaged', (ctx) => {
const p = protege(unit);
if (!p || ctx.target !== p || !byEnemyAttack(ctx) || !ctx.source.alive || !unit.canAct) return;
// "并仅对该角色触发刺玫特性": 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 });
}, { owner: unit });
if (hs !== 1) {
let cacheT = -1, top = null;
battle.on('heal', (ctx) => {
if (!up(unit) || ctx.opts?.regen) return;
if (cacheT !== battle.time) {
cacheT = battle.time;
top = alliesInGridOf(battle, unit).sort((a, b) => b.s.maxHp - a.s.maxHp || a.deploySeq - b.deploySeq)[0] ?? null;
}
if (ctx.target === top) ctx.amount *= hs;
}, { owner: unit });
}
} }],
};
},
};