Files
ark-stronghold-protocol/server/sim/content/kits/ops/chess_char_3_08-mint.js
T
sganggs 383fe4a49e feedback5 WF: ACTIVE_RANGE also replaces the SEARCH row and covers 深巡 S2 — a skill whose running range strictly contains the own one casts with an enemy inside it (the owner's decisions of 2026-10-05)
tools/build-data.mjs resolveTrigger: a MANUAL operator skill on DEFAULT (no row, or a DEFAULT entry of the deviation
tables) or on the SEARCH row ("在初始攻击范围内存在敌人时释放技能": 解放者 / 阵法术师 / 安洁莉娜 — ACTIVE_RANGE_OVER) whose
running range strictly contains its own is ACTIVE_RANGE on that range, rawRule the official row; validateAll accepts a
DEFAULT deviation resolved to ACTIVE_RANGE (chess and stand-in tables) and ACTIVE_RANGE over SEARCH. Data rebuilt
offline, JSON-compared: only skills[].trigger rule / customRangeGrid of 薄绿 S1 (x-2), 蜜蜡 S1 (x-2), 卡涅利安 S3 (x-2),
玛恩纳 S2 (2-3), 安洁莉娜 S3 (y-4) — rawRule SEARCH — and 深巡 S2 (3-2, rawRule TAKE_DAMAGE), normal + elite (32
leaves); backups.json unchanged. Kits: 薄绿 S1 drops its DEFAULT trigger and 深巡 S2 PR #12's DEFAULT line, both read the
data now (雷蛇 S2 keeps PR #12's line). The sim needs no change (SEARCH was the DEFAULT condition on the initial range
every tick; ACTIVE_RANGE is the same on the running range). Docs: DESIGN §5.6 and the §21.20 flip row, DATA, SIM,
PLAYING, kits README, shared tier comments, skills.js header.

Tests: data (78 records / 39 skills, the five from SEARCH, the SEARCH skills that stay), feedback5-active-range (安洁莉娜
S3 on its y-4, S2 keeps SEARCH), feedback1-tank-triggers and kits_t1t2 (深巡 S2 on its 3-2, before any hit), kits_alt_t3
(薄绿 S1 on its x-2), feedback1f-fence (the idle measure uses the interval of the cooldown still running: the S2 now casts
between two attacks), docs-consistency (one PR #12 kit line left).

Golden: roster-001 / 002 (深巡), roster-016 / 044 (玛恩纳, 安洁莉娜), roster-026 / 027 (薄绿), roster-041 / 042 (卡涅利安),
bond-egirShip-low / bond-suntShip-high (深巡), boss-boss_2-pair / boss-boss_6-pair (玛恩纳, 安洁莉娜), matches solo-NORMAL-1,
coop2-NORMAL-3, coop4-FUNNY-6, coop2-NORMAL-8-serverrun — each fields one of the six skills, which now casts when an
enemy enters its running range.
2026-10-05 18:45:13 +08:00

81 lines
4.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// server/sim/content/kits/ops/chess_char_3_08-mint.js — 薄绿 (char_388_mint) kit, tier 3.
// Conventions of the tier-3 kits: ../shared/tier3.js; kit contract and rules: ../README.md.
import { num, defOf, talentBb, traitBb, altSkills, gridKeys, fx, copyGrid, enemiesOn, aura } from '../shared/tier3.js';
export default {
// ---- 3_08 薄绿 · 阵法术师 — S2 聚能涡旋: each attack strikes every enemy on her range (the trait's 群体法术伤害) and
// pushes each one towards her, end-of-skill burst on
// every enemy in range; 地质学者: DEF aura (skill off) / less likely targeted (skill on);
// 精锐 module PLX-X: keeps part of the guard (DEF/RES) while the skill runs
// S1 风语: wider range (skill grid), attacks every enemy on it at attack@atk_scale. Auto-cast: the official
// rule is the 阵法术师 row SEARCH (PRTS 卫戍协议/帮助 "不受基础策略影响,在初始攻击范围内存在敌人时释放技能"; it covers
// every MANUAL skill of the class — user playtest #6) = an enemy inside her INITIAL range, never any enemy on the
// field (she would burn the skill on enemies that just spawned). Since 0.2.0 the owner's ACTIVE_RANGE rule
// (2026-10-05) widens it: the S1 x-2 strictly contains her x-1, so the data rule is ACTIVE_RANGE on the x-2 (rawRule
// SEARCH) — an enemy she can target inside the x-2, every tick — which this spec reads. S2 keeps SEARCH (no range
// change).
chess_char_3_08_a: (bb, chess, def) => {
const d = defOf(chess, def);
const t0 = talentBb(d, 0);
const tb = traitBb(d);
const tGrid = copyGrid(d.talents?.[0]?.rangeGrid) ?? [[1, 0], [0, -1], [0, 0], [0, 1], [-1, 0]];
const pullForce = num(bb['attack@force'], num(bb.force, 0));
const endScale = num(bb.atk_scale, 0);
const keepDef = num(tb['soil_e_002[buff].def'], 0), keepRes = num(tb['soil_e_002[buff].magic_resistance'], 0);
// every skill: PLX-X keeps part of the guard, 地质学者 taunt −1 while it runs, DEF aura only while it does not
const guardOn = ({ battle, unit }) => {
if (keepDef || keepRes) battle.addBuff(unit, { key: 'trait:mint_keep', mods: { defPct: keepDef, resFlat: keepRes } });
battle.addBuff(unit, { key: 'talent:mint_taunt', mods: { taunt: num(t0.taunt_level, -1) } });
unit.mem.mintAura?.();
};
const guardOff = ({ battle, unit }) => {
battle.removeBuff(unit, 'trait:mint_keep');
battle.removeBuff(unit, 'talent:mint_taunt');
unit.mem.mintAura?.();
};
return {
skills: altSkills(chess, d, bb, {
skchr_mint_1: (s) => {
const grid = copyGrid(s.rangeGrid);
return {
kind: 'duration',
attack: { atkScale: num(s.bb['attack@atk_scale'], num(s.bb.atk_scale, 1)) },
...(grid ? { targeting: { rangeGrid: grid } } : {}),
onStart: guardOn,
onEnd: guardOff,
};
},
}),
skill: {
kind: 'duration',
attack: {
atkScale: num(bb['attack@atk_scale'], 1),
onHit({ battle, unit, target }) {
if (!target || !target.alive || target.side !== 'enemy') return;
// PRTS 备注: "此技能的“拖拽”机制实际为反方向(指向薄绿方向)的推开" — a radial push towards her by the
// official 力度 − 重量 push distance (小力 vs weight 1: 0.44 tiles), never past her (Battle.push inward). Her
// attack reaches air units (阵法术师 "攻击时可对空"), but the drones of the mode are 静态刚体 (PRTS 特殊机制): hit,
// never dragged (player report after 0.1.0, "飞机可以被薄绿的技能拉走")
if (battle.push(target, pullForce, { from: unit, inward: true }) > 0) fx(battle, 'pull', target, { src: unit.id });
},
},
onStart: guardOn,
onEnd(ctx) {
const { battle, unit, reason } = ctx;
if (reason !== 'death' && unit.alive && endScale > 0) {
for (const e of enemiesOn(battle, unit, unit.rangeKeys)) battle.dealDamage(unit, e, { amount: unit.s.atk * endScale, type: 'arts', isSkill: true, tags: ['skill', 'burst'] });
fx(battle, 'aoe', unit, { radius: 2, dmgType: 'arts', skill: 'mint_2' });
}
guardOff(ctx);
},
},
talents: [{ install(battle, unit) {
unit.mem.mintAura = aura(battle, unit, {
key: 'talent:mint_geo', side: 'ally', tiles: () => gridKeys(tGrid, unit), active: () => !unit.skill?.active, mods: { defPct: num(t0.def) },
});
} }],
};
},
};