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,69 @@
// server/sim/content/kits/ops/chess_char_6_10-nymph.js — 妮芙 (char_4146_nymph) kit, tier 6 (hidden).
// Conventions of the tier-6 kits: ../shared/tier6.js; kit contract and rules: ../README.md.
import { bodyInKeys } from '../../../body.js';
import { num, tbb, live, elementDmg } from '../shared/tier6.js';
// ------------------------------------------------------------------------------------------------------------------
// 妮芙 chess_char_6_10 (本源术师, hidden tier-6 entry) — S2 怵然震爆; 失魂; 窥心钥; module 心声
function nymph(bb, chess, def) {
const t0 = tbb(def, 0), t1 = tbb(def, 1), tb = def?.traitBb || {};
const soul = (battle, unit, t, scale) => {
const burst = t.findBuff('apoptosisBurst');
if (!burst || !(scale > 0)) return;
const key = `nymph:soul:${unit.id}`;
const cur = t.findBuff(key);
if (cur) { cur.data.scale = Math.max(cur.data.scale, scale); cur.timeLeft = Math.max(cur.timeLeft, burst.timeLeft); return; }
battle.addBuff(t, {
key, duration: Math.max(0.1, burst.timeLeft), interval: 1, source: unit, data: { scale },
// 元素伤害 = the 'elemental' damage type (no DEF/RES, × elementalTakenMul)
onTick: ({ unit: e, buff }) => { if (e.findBuff('apoptosisBurst')) battle.dealDamage(unit, e, { amount: unit.s.atk * buff.data.scale, type: 'elemental', element: 'apoptosis', canDodge: false, tags: ['talent', 'elementDmg'] }); },
});
};
return {
skill: {
kind: 'charges',
attack: {
atkScale: num(bb.atk_scale, 1),
splashRadius: num(bb.projectile_range, 1.5),
splashScale: 1,
onHit({ battle, unit, target }) {
if (target && target.alive && num(bb.fear) > 0) battle.applyStatus(target, 'fear', { duration: num(bb.fear), source: unit });
battle.fx('shockBlast', { x: target ? target.x : unit.x, y: target ? target.y : unit.y, id: unit.id });
},
},
},
talents: [
{ install(battle, unit) { // skill apoptosis (per damaged target) + 失魂
battle.on('damaged', (ctx) => {
const t = ctx.target;
if (ctx.source !== unit || !t || t.side !== 'enemy' || ctx.type === 'element' || !ctx.dmg?.isAttack) return;
const skillHit = !!ctx.dmg.isSkill;
if (t.alive) soul(battle, unit, t, skillHit ? num(bb.element_atk_scale, num(t0.element_atk_scale)) : num(t0.element_atk_scale));
if (skillHit && t.alive) elementDmg(battle, unit, t, 'apoptosis', ctx.amount * num(bb.ep_damage_ratio));
}, { owner: unit });
} },
{ install(battle, unit) { // 窥心钥 (elite module: field-wide, +ASPD at max stacks)
const atk = num(t1.atk), max = Math.max(1, Math.floor(num(t1.max_stack_cnt, 10)));
const fieldWide = t1.stack_cnt_check != null, as = num(t1.attack_speed);
battle.on('deploy', ({ unit: u }) => { if (u === unit) unit.mem.nymphKey = 0; }, { owner: unit });
battle.on('elementBurst', ({ target, element }) => {
if (element !== 'apoptosis' || !live(unit) || !target || target.side !== 'enemy') return;
if (!fieldWide && !bodyInKeys(target, unit.rangeKeySet)) return;
unit.mem.nymphKey = Math.min(max, (unit.mem.nymphKey || 0) + 1);
const n = unit.mem.nymphKey;
battle.addBuff(unit, { key: 'nymph:key', mods: { atkPct: atk * n, aspd: fieldWide && n >= max ? as : 0 } });
}, { owner: unit });
} },
{ install(battle, unit) { // elite module: ×1.1 vs targets in an element burst
const ds = num(tb.damage_scale, 1);
if (ds > 1) battle.on('hit', (ctx) => { if (ctx.source === unit && ctx.target.s.flags.burstLock) ctx.dmg.mul *= ds; }, { owner: unit });
} },
],
};
}
export default {
chess_char_6_10_a: nymph,
};