Files
ark-stronghold-protocol/server/sim/content/kits/ops/chess_char_5_17-f12yin.js
T
sganggs 69d791f9c6 feedback7 R22-OSIM: a skill that 白铁's 铁钳号 opens now acts on it — 蕾缪安 S3 / 艾丽妮 S3 / 陈 S2 / 引星棘刺 S2 spend on it, skills that pick enemies only stay closed; golden: unchanged
Grok's review of the 铁钳号 change (HIGH): the device opened every non-heal skill, but kits that pick their victims
with enemiesInKeys only were spent on nothing — 蕾缪安 S3 went active with 0 locks, 艾丽妮 S3 and 陈 S2 struck nothing,
引星棘刺 S2 threw at the empty far tile. Audit: every skill of every chess (loadouts) and of the 自选 pool, placed with
only the device in range; of the 351 skills the device opened, 67 never touched it.

- skills.js `allyTargetsOk`: the device counts for a skill's start only if the skill acts on it — SkillSpec
  `allyTargets` (true / false) from the kit, else [ASSUMED] a skill acting through the unit's own attacks (timed and
  still attacking, or a cast that is the next attack) on a unit that attacks. An onStart-only cast or a no-attack timed
  skill picks enemies itself and waits for one (德克萨斯 S2 剑雨, 锡人 S1/S2, 铃兰 S3 … about 50 skills).
- Spend on the device (allyTargets: true; its kit cancels the hits, its 受击回复 counts): 蕾缪安 S3 locks it and spends
  her bullets (ammoUsed, so the per-bullet layers come) and shells it; 艾丽妮 S3 strikes it; 陈 S2 draws on it after
  every enemy; 引星棘刺 S2 throws onto it and its pulses hit it. queries.js allyTargetsInRadius for their areas.
- Explicitly closed ([ASSUMED], allyTargets: false): 普罗旺斯 S2 (never shoots above 80 % HP), 卡涅利安 S1 (charged: no
  attack), 山 S2 (blocked enemies), 余 S2 / S3, 迷迭香 S3 (blocked only), 荒芜拉普兰德 S1 / S2 (drone locks), 淬羽赫默 S1–S3
  and 遥 S1–S3 (heal attacks), 机械师 S3, 珊比 S2 / S3, 陈 S3 / 艾丽妮 S2 (their guards already refused).
- 雪猎's empty-magazine cast back to enemies only (its S2 does not act on the device).
Re-audit: 281 skills open on the device alone and all act on it (蕾缪安 S3 through her locks); none of those that
acted on it before stopped. Docs: SIM.md, design/engine.md, PLAYING.md.

Tests: test/content/feedback7-allytarget-kits.test.js (5; all fail on the parent).
2026-10-08 20:53:24 +08:00

77 lines
4.2 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_5_17-f12yin.js — 山 (char_264_f12yin) kit, tier 5.
// Conventions of the tier-5 kits: ../shared/tier5.js; kit contract and rules: ../README.md.
import {
HALF_HP, num, talent, traitBb, skillGrid, batPct, mods, selectedId, lazySkills, instantKind, skillRange, whileOn,
permBuff,
} from '../shared/tier5.js';
export default {
// ---------------------------------------------------------------------------------------------------------------
// 山 — S2 横扫架势 (stance toggle): DEF −30 %, range = own tile, ATK +35 %, block +1, hits every blocked enemy, 4 % max HP/s
// regen. T1 巨力重拳: 20 % chance ×1.6 ATK and target ATK −15 % for 3 s. T2 强壮肉体: DEF +10 %, 15 % phys dodge.
// Module (elite): ASPD +10 above 50 % HP.
// S1 左勾扫拳 (instant, attack SP): next attack atk_scale × ATK on max_target enemies. S3 震地碎岩击 (duration): skill
// range, BAT +0.7 s, ATK +, double hits on up to attack@max_target enemies, each pushed (中等力度); T1 chance →
// talent@prob. Module FGT-X (elite): 15 % physical dodge.
chess_char_5_17_a: (bb, chess, def) => {
const t0 = talent(chess, 0), t1 = talent(chess, 1), tb = traitBb(chess);
const sid = selectedId(chess, def);
const critScale = num(t0.atk_scale, 1);
const critProb = (unit) => (sid === 'skchr_f12yin_3' && unit.skill?.active ? num(bb['talent@prob'], num(t0.prob)) : num(t0.prob));
return {
skills: lazySkills({
skchr_f12yin_1: () => ({ kind: instantKind(chess, def), attack: { atkScale: num(bb.atk_scale, 1), maxTargets: Math.max(1, num(bb.max_target, 2)) } }),
skchr_f12yin_3: () => ({
kind: 'duration',
mods: mods({ atkPct: num(bb.atk), batPct: batPct(bb.base_attack_time, chess) }),
targeting: skillRange(chess, def, { maxTargets: Math.max(1, num(bb['attack@max_target'], 3)) }),
attack: {
hits: 2,
onEachHit({ battle, unit, target, kind }) {
if (kind !== 'main' || !target || !target.alive || target.side !== 'enemy') return;
// "中等力度地推动" (PRTS 备注: on the 2nd hit of each attack — onEachHit runs after both): a radial push by
// the official 力度 − 重量 distance (Battle.push)
battle.push(target, num(bb['attack@force'], 1), { from: unit });
},
},
}),
}),
skill: {
kind: 'toggle',
// [ASSUMED] its attacks reach the enemies he blocks; the unblockable 铁钳号 of 白铁 never: it does not open it (skills.js
// allyTargetsOk)
allyTargets: false,
mods: mods({ atkPct: num(bb.atk), defPct: num(bb.def), blockCnt: num(bb.block_cnt), hpRegenRatio: num(bb.hp_recovery_per_sec_by_max_hp_ratio) }),
targeting: skillGrid(chess, def) ? { rangeGrid: skillGrid(chess, def) } : undefined,
attack: { hitAllBlocked: true },
},
trait: {
dmgMul: (b, u) => (u.mem.crit ? critScale : 1),
afterHit: (b, u, t) => {
if (!u.mem.crit || !t || !t.alive || !num(t0.atk)) return;
b.addBuff(t, { key: 'f12yin:punch', duration: num(t0.duration, 3), mods: { atkPct: num(t0.atk) }, visible: true, status: 'weaken' });
},
},
talents: [
{ install(battle, unit) { // 巨力重拳: one roll per attack
battle.on('beforeAttack', (c) => {
if (c.attacker !== unit) return;
const p = critProb(unit);
unit.mem.crit = p > 0 && battle.rng.chance(p);
if (unit.mem.crit) battle.fx('crit', { x: unit.x, y: unit.y, id: unit.id });
}, { owner: unit });
} },
{ install(battle, unit) { permBuff(battle, unit, 'f12yin:body', { defPct: num(t1.def), dodgePhys: num(t1.prob) }); } },
],
install(battle, unit) {
// FGT-X: 拥有15%的物理闪避 (an own dodge source: rolls independently of 强壮肉体)
if (num(tb.prob) > 0) permBuff(battle, unit, 'f12yin:moduleX', { dodgePhys: num(tb.prob) });
const aspd = num(tb.attack_speed);
if (!aspd) return;
whileOn(battle, unit, 0.2, () => { if (unit.hpRatio > HALF_HP) battle.addBuff(unit, { key: 'f12yin:module', duration: 0.3, mods: { aspd } }); });
},
};
},
};