feedback5 K2: stand-in kits for Stormeye, Pith and Raidian — every skill, talent and module at every form

Stormeye (char_611_acnipe; 空弦, 莫斯提马, 百炼嘉维尔 / 妮芙, 蕾缪安 / 异客): 风坠 rolls on every attack instance
(acnipe_t_1: ATK × atk_scale before DEF; S3 talent@prob), 风雨欲来 +0.2 SP/s after `delay` s without an attack
[ASSUMED reading], S1 ATK / ASPD / 100 DEF ignored, S2 an endless toggle (ATK +5 %, 2 targets), S3 3 targets × double
hit plus one physical ATK × 1.0 instance on a target at >= 90 % HP on the attack's first hit (acnipe_s_3[extra], no
风坠 / MAR-X on it); MAR-X stays the fastshot profile's flyScale.

Pith (char_612_accast; 烛煌, 焰影苇草 / 迷迭香 / 荒芜拉普兰德): splash from the trait blackboard, 12 RES ignored, ATK
+10 / +20 % on herself and the 【术师】 of the 4 tiles next to her, S1 ASPD + splash 1.5, S2 ASPD + ATK on every 【术师】,
S3 one ATK × atk_scale_aoe arts hit on every enemy of her range at the cast, then 2 targets, ASPD, splash 1.2 (PRTS
备注); SPC-X range (moduleRangeUp).

Raidian (char_614_acsupo; 灵知, 夕 / 安洁莉娜, 浊心斯卡蒂 / 仇白): 同调 on herself and the operators next to her (×
talent_scale in S3), 诱引 per PRTS 命中率 — one roll per enemy attack in her range, a miss cancels the whole attack
before the enemy riders (hit priority 300), S1 / S2 from the blackboards (S2 flat −0.1 / −0.2 s, 停顿 1.1 / 1.2 s), S3
y-4 + ATK + 脆弱 / 虚弱 aura with the 虚弱 stacking as 90 / 80 % (stackAs); S3 casts by the data's ACTIVE_RANGE;
DEC-X +0.2 SP/s with an enemy in range.

Triggers stay the data's (AUTO attack buffs Stormeye S2 / Pith S1 keep DEFAULT, as the W5C AUTO audit). No golden
scenario fields a stand-in: digests unchanged. Tests: test/content/standin_acnipe / _accast / _acsupo (27).
This commit is contained in:
sganggs committed 2026-10-05 18:34:46 +08:00
1 parent eac9b9737d
commit f317adf003
7 files changed
+1094 -1

No files matched your search

@@ -0,0 +1,97 @@
// server/sim/content/kits/ops/standin-accast.js — Pith (char_612_accast) 补位 stand-in kit: 6★ 扩散术师 for 烛煌 (T5) and
// 焰影苇草 / 迷迭香 / 荒芜拉普兰德 (T6), all S3 + SPC-X; every skill at every form.
// Kit contract and the stand-in rules: ../README.md ("Stand-in kits").
//
// Sources: data/backups.json (character_table / skill_table / battle_equip_table at E2 Lv1 rank 4 and E2 Lv60 rank 7),
// PRTS Pith(卫戍协议) (S3 备注 "※溅射范围扩大至1.2") and the client's battle data (charpack char_612_accast,
// battle/buff_template_data.json accast_s_3[AOE]).
// - 扩散术师 trait "攻击造成群体法术伤害": the splash around each struck target, radius = the trait's
// attack@projectile_range (1.1, PRTS 溅射半径一览's branch value); a skill's attack@projectile_range replaces it while it runs.
// - T1 "见我所见" "攻击无视目标12法术抗性": magic_resist_penetrate_fixed — a flat 法术穿透 attribute (charpack accast_t_1:
// attribute 27 from the blackboard; PRTS Pith 备注 "无视法抗效果为增加自身法术穿透属性(直接加算)"): every arts damage she deals.
// - T2 "授我所授" "自身及相邻四格的【术师】干员攻击力+10%" (module SPC-X level 2 / 3: +15 / +20 %): an aura on her own tile and
// the 4 orthogonal ones, 【术师】 operators only (charpack: profession mask CASTER, removed when the target leaves);
// several sources keep the strongest (installAura, [ASSUMED] like every same-named talent aura of the mode).
// - S1 "书我所书" (自动触发, 25 s): ASPD +attack_speed, splash radius attack@projectile_range (1.5). Trigger: the data's
// DEFAULT — an AUTO attack buff waits for her next attack (W5C's AUTO audit: "attack modes / attack buffs" keep waiting).
// - S2 "为我所为" (35 s): her ASPD +attack_speed; "所有【术师】干员攻击力+atk" — an aura on every 【术师】 operator of the field
// (her included) while it runs, refreshed every AURA_IV s; the strongest of several sources applies [ASSUMED].
// - S3 "驭我所驭" (35 s): at the cast, one atk_scale_aoe × ATK arts hit on every enemy in her attack range (accast_s_3[AOE]:
// AOEDamage MAGICAL, its s3_selector; a skill hit, not an attack); then attack@max_target targets (+1), ASPD
// +attack_speed, splash attack@projectile_range (1.2, PRTS 备注).
// - Module SPC-X "攻击范围扩大": her range becomes the module's own grid (the 3×3 caster range + the tile [0,3]; shared
// tier5 moduleRangeUp), so the S3 burst covers it too; HP / ATK in the stats; T2 +20 % at level 3 (composed talents).
import { num, talentBb, skillRec, statBuff, installAura, up } from '../shared/tier1.js';
import { moduleRangeUp } from '../shared/tier5.js';
const S1 = 'skchr_accast_1';
const S2 = 'skchr_accast_2';
const S3 = 'skchr_accast_3';
/** Refresh period / length of the S2 aura buff (the non-stacking aura convention of the kits). */
const AURA_IV = 0.25;
const AURA_DUR = 0.4;
const S2_KEY = 'accast:s2';
const bbOf = (chess, id) => skillRec(chess, id)?.bb ?? {};
/** A 【术师】 operator (summons are never 【术师】 operators). */
const isCaster = (a) => !!a && a.kind === 'op' && a.def?.profession === 'CASTER';
/** One of the 4 tiles next to `u` (相邻四格). */
const adjacent4 = (a, u) => Math.abs(a.tileR - u.tileR) + Math.abs(a.tileC - u.tileC) === 1;
/** S2: ATK +v on every 【术师】 operator unless a stronger one from another source is on it. */
function casterAtk(battle, unit, v) {
if (!(v > 0)) return;
for (const a of battle.alliesFor(unit)) {
if (!isCaster(a)) continue;
const cur = a.findBuff(S2_KEY);
if (cur && cur.source !== unit && (cur.data?.v ?? 0) > v && cur.timeLeft > 0.05) continue;
battle.addBuff(a, { key: S2_KEY, duration: AURA_DUR, mods: { atkPct: v }, source: unit, data: { v }, tags: ['aura'] });
}
}
export default {
char_612_accast: (bb, chess) => {
const t0 = talentBb(chess, 0), t1 = talentBb(chess, 1);
const tb = chess?.trait?.bb ?? {};
const b1 = bbOf(chess, S1), b2 = bbOf(chess, S2), b3 = bbOf(chess, S3);
return {
trait: { splashRadius: num(tb['attack@projectile_range'], 1.1) },
skills: {
[S1]: { kind: 'duration', mods: { aspd: num(b1.attack_speed) }, attack: { splashRadius: num(b1['attack@projectile_range'], 1.5) } },
[S2]: {
kind: 'duration',
mods: { aspd: num(b2.attack_speed) },
onStart({ battle, unit }) { casterAtk(battle, unit, num(b2.atk)); },
},
[S3]: {
kind: 'duration',
mods: { aspd: num(b3.attack_speed) },
targeting: { maxTargets: Math.max(1, Math.floor(num(b3['attack@max_target'], 2))) },
attack: { splashRadius: num(b3['attack@projectile_range'], 1.2) },
onStart({ battle, unit }) {
const scale = num(b3.atk_scale_aoe, 1);
for (const e of battle.enemiesInKeys(unit.rangeKeys, unit, unit.profile)) {
battle.dealDamage(unit, e, { amount: unit.s.atk * scale, type: 'arts', isSkill: true, tags: ['skill', 'accast:aoe'] });
battle.fx('aoe', { x: e.x, y: e.y, r: 0.5, id: unit.id, skill: 'accast' });
}
},
},
},
talents: [
{ install(battle, unit) { statBuff(battle, unit, 'talent:accast:res', { resIgnoreFlat: num(t0.magic_resist_penetrate_fixed) }); } },
{ install(battle, unit) {
const v = num(t1.atk);
if (v) installAura(battle, unit, { key: 'talent:accast', value: v, select: (a) => isCaster(a) && (a === unit || adjacent4(a, unit)), mods: { atkPct: v } });
} },
],
install(battle, unit) {
moduleRangeUp(battle, unit, chess);
if (unit.skill?.id !== S2) return;
// S2's aura while it runs (its onStart gives the first application at the cast)
const v2 = num(b2.atk);
battle.every(AURA_IV, () => { if (up(unit) && unit.skill.active) casterAtk(battle, unit, v2); }, { owner: unit });
},
};
},
};