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,49 @@
// server/sim/content/kits/ops/chess_char_2_19-tinman.js — 锡人 (char_4151_tinman) kit, tier 2.
// Conventions of the tier-2 kits: ../shared/tier2.js; kit contract and rules: ../README.md.
import { num, talentBb, enemiesInGrid, instantKind } from '../shared/tier1.js';
import { tinmanKit } from './chess_char_1_16-tinman.js';
export default {
// ---------------------------------------------------------------------------------------------------------------
// 2_19 锡人 “大拉里”: see tinmanKit (tier1.js).
// S1 “老科利” (alt, attack SP, needs a target): throws an alchemy unit at the target (ground first); for
// projectile_delay_time s ground enemies within projectile_range tiles are 虚弱 (weaken −atk) and take atk_scale ×
// ATK arts per second (ATK cached at the cast; damage over time, so the elite 凋敝魂灵 ×skill@damage_scale applies;
// the zone counts for the module's SP bonus and outlives her).
chess_char_2_19_a: (bb, chess, def) => {
const k = tinmanKit(bb, chess, def);
const dur = num(bb.projectile_delay_time, 8), radius = num(bb.projectile_range, 1), dmgScale = num(bb.atk_scale);
const weak = Math.min(1, Math.max(0, -num(bb.atk)));
const wither = num(talentBb(chess, 1)['skill@damage_scale'], 1);
const STEP = 0.25; // weaken refresh cadence (damage every 1 s)
return {
...k,
skills: {
...(k.skills || {}),
skchr_tinman_1: {
kind: instantKind(def),
onStart({ battle, unit }) {
const tgt = enemiesInGrid(battle, unit, null, { n: 1, groundOnly: true })[0] ?? enemiesInGrid(battle, unit, null, { n: 1 })[0];
const x = tgt ? tgt.x : unit.x + unit.fwd[1], y = tgt ? tgt.y : unit.y + unit.fwd[0];
const atk = unit.s.atk;
const n = Math.max(1, Math.round(dur / STEP)), per = Math.max(1, Math.round(1 / STEP));
let i = 0;
unit.mem.tinZones = (unit.mem.tinZones ?? 0) + 1;
battle.fx('zone', { x, y, radius, dur, id: unit.id, skill: 'tinman1' });
battle.every(STEP, (b, sc) => {
const pulse = i % per === 0;
for (const e of b.foesInRadius(x, y, radius)) {
if (e.isFlying || e.s.flags.untargetable) continue;
if (weak > 0) b.applyStatus(e, 'weaken', { duration: STEP + 0.05, value: weak, source: unit });
if (wither > 1) b.addBuff(e, { key: 'tinman:wither', duration: STEP + 0.05, data: { mul: wither }, source: unit });
if (pulse && dmgScale > 0) b.dealDamage(unit, e, { amount: atk * dmgScale, type: 'arts', isSkill: true, canDodge: false, tags: ['dot', 'zone'] });
}
if (++i >= n) { sc.cancel(); unit.mem.tinZones = Math.max(0, (unit.mem.tinZones ?? 1) - 1); }
}, { immediate: true });
},
},
},
};
},
};