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,54 @@
// server/sim/content/kits/ops/chess_char_3_10-pinecn.js — 松果 (char_440_pinecn) kit, tier 3.
// Conventions of the tier-3 kits: ../shared/tier3.js; kit contract and rules: ../README.md.
import { num, defOf, talentBb, selectedId, altSkills, instantKindOf, copyGrid } from '../shared/tier3.js';
export default {
// ---- 3_10 松果 · 散射手 — S2 电能过载: ATK + growing with each use (a→d), shorter range; 便携电源: SP regen for 60 s
chess_char_3_10_a: (bb, chess, def) => {
const d = defOf(chess, def);
const t0 = talentBb(d, 0);
const sel = selectedId(chess, d);
const steps = Object.keys(bb).filter((k) => /\[[a-z]\]\.atk$/.test(k)).sort().map((k) => num(bb[k]));
if (!steps.length) steps.push(num(bb.atk));
const skillGrid = copyGrid(d.skill?.rangeGrid);
const kit = {
skill: {
kind: 'duration',
onStart({ battle, unit, skill }) {
const atk = steps[Math.min(steps.length - 1, Math.max(0, skill.activations - 1))];
battle.addBuff(unit, { key: 'skill:pinecn_atk', mods: { atkPct: atk } });
},
onEnd({ battle, unit }) { battle.removeBuff(unit, 'skill:pinecn_atk'); },
},
// S1 RMA长钉 (charges): "立即以165%的攻击力进行一次攻击,无视敌人180的防御力" — an extra shot fired at once (all
// enemies in range, front-row × of the trait), on top of the normal attack it was cast before
skills: altSkills(chess, d, bb, {
skchr_pinecn_1: (s) => ({
kind: instantKindOf(s),
// (the DEF ignore rides on the shots' tag: they land after the instant skill has ended)
attack: { atkScale: num(s.bb.atk_scale, 1), tags: ['skill', 'pinecnSpike'] },
onStart({ battle, unit }) { battle.forceAttack(unit); },
}),
}),
talents: [{ install(battle, unit) {
battle.on('deploy', (ctx) => {
if (ctx.unit === unit) battle.addBuff(unit, { key: 'talent:pinecn_power', duration: num(t0.duration, 60), mods: { spRecoveryFlat: num(t0.sp_recovery_per_sec) } });
}, { owner: unit });
} }],
};
if (sel === 'skchr_pinecn_1') {
const pen = num(bb.def_penetrate_fixed, 0);
kit.install = (battle, unit) => battle.on('hit', (ctx) => {
if (ctx.source === unit && pen > 0 && ctx.dmg.tags?.includes('pinecnSpike')) ctx.dmg.defIgnoreFlat += pen;
}, { owner: unit });
}
if (skillGrid) {
kit.skill.targeting = { rangeGrid: skillGrid };
// "攻击范围缩短": offensive skills fire with an enemy inside the SKILL range (research 03 §1.4) — with the
// initial (wider) range she would open the skill on enemies the shortened range cannot reach
kit.skill.trigger = { rule: 'CUSTOM_RANGE', grid: skillGrid };
}
return kit;
},
};