feedback5 O9: 自选 operator kits 帕拉斯, 止颂 and 贝洛内 (with his 牵绊) — every skill, talent, trait and module (stage 1 / 3) at every form

- op-pallas.js (char_485_pallas, 教官): 英雄的诞生 精力充沛 on every 米诺斯 operator (one buff per ally, the
  highest active bonus — her S3's too), 女神的振奋 on every damage instance (her 1-1, through 禁疗; INS-Y stage 3 the
  米诺斯 extra), S1 two strikes, S2 range +1 / ATK / stun (data DEFAULT: build-data's ATTACK_RANGE_CHANGE misses
  "攻击范围向前延伸一格" — reported, not worked around), S3 three targets and the front-holder buff (low ground,
  operators only, passed on retreat / deploy). INS-Y's "可以额外部署在远程位" is a prep placement rule (owner's
  decision of 2026-10-04): unchanged, reported.
- op-lessng.js (char_4011_lessng, 无畏者): 苦痛专注 (hit-time cut while blocking, 无来源 / allies / himself
  included), 痛楚砺刃 (any damage aimed at him, dodged too), S2 the deploy window (2 strikes, ATK, talent ×2), S3
  status immunity, blocked-target scale, the cast under a 异常状态 (600 arts first, cleanse, then HP; 沉默 does
  not hold it back), DRE-X ×1.15 on a blocked target, DRE-Y once-per-deployment save and stage 3's 12 % DEF ignore.
- op-demetr.js (char_4037_demetr, 斗士): 【手段】 (one per enemy, stacks before the hit, 8 and 停顿 under S2, back
  to 5 on the 0.1 s update), the HP-ratio damage bonus, 街头直觉 from every deployment (a 【移动】 too), S1 two
  strikes, S2 3-13 / three targets, S3 the 【移动】s (x-2 around his located tile, buildable low-ground tiles,
  in-place move without a target, re-target after 1 s without damage or when the elite he hit falls), 牵绊
  (无敌 / untargetable / 孤立), the fatal-hit 不死 + end, the 【返回】 (SP emptied, a short 不死) and the forced
  retreat; FGT-Y ASPD above half HP.
- kits/index.js: the three files appended to OPERATOR_KIT_FILES.
- Tests: test/content/op_pallas.test.js (9), op_lessng.test.js (10), op_demetr.test.js (10).
- Golden: only diy moved — diy-049 … 054 now field the three operators (every form × module × skill), the
  prototype / reserve battles moved down to diy-054 … 058 (new ids, same packing); diy-001 … 048 and every other
  family unchanged.
This commit is contained in:
sganggs committed 2026-10-06 01:30:26 +08:00
1 parent fef4ea3d4b
commit c454b61075
8 files changed
+2062 -118

No files matched your search

+160
View File
@@ -0,0 +1,160 @@
// server/sim/content/kits/ops/op-lessng.js — 止颂 (char_4011_lessng) 自选 operator kit: 6★ 无畏者 (近卫), an owned-6★ pick of
// the tier-5 and tier-6 自选 slots; every skill, both talents, the trait and both modules at every form.
// Kit contract and the 自选 rules: ../README.md ("How to add an operator (自选)").
//
// Forms (data/backups.json units.char_4011_lessng, the DIY slot statuses): normal = E2 Lv1, skills at rank 4, no module;
// elite = E2 Lv60, rank 7, the picked module at stage 1 (tier 5) or 3 (tier 6). Potential 0 [ASSUMED: no account].
// Sources: character_table / skill_table / battle_equip_table (zh_CN, as built into backups.json); PRTS 止颂 (苦痛专注 备注
// "将降低无来源或任意来源于非“自身阻挡的敌人”的物理、法术伤害…伤害降低效果于“受到伤害前”生效…<Y模组>额外效果为在计算伤害前,若伤害
// 目标满足条件则临时获取…物理穿透(百分比)Buff(不可叠加,直接加算)"; 痛楚砺刃 备注 "天赋于受到伤害时触发,无需成功受到伤害也可
// 生效…重复受到伤害时,重置本天赋持续时间"; 苦修破誓 备注 "技能期间,持有状态免疫、晕眩反制、寒冷反制、冻结反制…技能开启时,若有
// 异常状态,会先对自身造成法术伤害(来源为自身,可致死),然后清除自身所有异常状态,最后再获得技能效果"; DRE-X 备注 "于每次计算伤害时检查
// 目标是否处于阻挡/被阻挡状态…提升效果为攻击力倍率提升"; DRE-Y 备注 "属于免死效果,触发效果后获得属性变化后生命上限100%的生命复原");
// the client's battle data — buff_template_data `lessng_t1` (ON_APPLYING_MODIFIER: he blocks, the source is not blocked by
// him ⇒ DamageScale 1 − damage_resistance on PHYSICAL_AND_MAGICAL), `lessng_t2` (ON_TAKE_DAMAGE ⇒ ATK MULTIPLIER for
// add_atk_duration), `lessng_s3[atk_scale]` / `lessng_e_002_trait[blocked]` (ON_CALCULATE_DAMAGE, CheckBlocked of the
// target — by anyone — ⇒ AtkScaleUp), `lessng_s3[anti]`, `lessng_e_003_trait` / `lessng_e_003_talent`; charpack
// char_4011_lessng (S2 mode: `_additionalTimes` 1, its talent with `_applyTalentScale`), skchr_lessng_2 (`_castOnLocate`,
// the mode for `duration` s), skchr_lessng_3 (`_canUseInAbnormalState`); his skeleton (Skill_2_Loop: OnAttack 0.300 / 0.567 s).
// - Trait (无畏者) "能够阻挡一个敌人": the profession default (block 1, melee, ground only). Module DRE-X “沉锋之束” "攻击被阻挡
// 的敌人时攻击力提升至115%" (trait bb atk_scale): ×atk_scale on his attack's ATK against a target blocked by anyone (a
// profile dmgMul — the scale of the attack, before DEF). Module DRE-Y “苦修者的抗压训练” "被击倒时不撤退且回复所有生命但生命上限
// -60%,攻击速度+30(单次部署只触发1次)" (trait bb max_hp 0.4 / attack_speed / hp_ratio): the first lethal hit of a deployment
// is prevented, max HP ×max_hp (FINAL_SCALER) and ASPD +attack_speed for the rest of that deployment, HP set to hp_ratio of
// the new max (生命复原, not a heal); not while a 不死 already holds him ("_dontConsumeWhenUndeadable": 坚固维式重锤's window,
// items/battle.js holdsUndying).
// - T1 苦痛专注 "阻挡时,受到来自非自身阻挡敌人的物理和法术伤害降低35%" (bb damage_resistance): while he blocks an enemy, a
// physical or arts damage instance whose source is not an enemy he blocks — 无来源, an ally, himself included — is
// ×(1 − damage_resistance) (`hit`: before the 伤判 / barrier steps). S2's window doubles it (talent_scale). DRE-Y stage 3:
// 40 %, and "攻击自身阻挡的敌人时,无视目标12%的防御力" (the hidden module talent's def_penetrate: defIgnorePct on his damage to an
// enemy he blocks).
// - T2 痛楚砺刃 "受到伤害后,攻击力+12%,持续15秒(不可叠加)" (bb atk / add_atk_duration): every damage instance aimed at him
// (`hit`, so a dodged or shielded one too; never a 流失) sets ATK +atk for add_atk_duration s, refreshed, never stacked.
// DRE-X stage 3: +20 %.
// - S1 强力击·γ型 (AUTO, attack SP 3; data DEFAULT): the next attack at atk_scale × ATK.
// - S2 虔修对决 (PASSIVE, 部署后, 18 / 21 s): from every deployment for the skill's duration: 苦痛专注 ×talent_scale, ATK +atk and
// every attack strikes twice (2连击 — both strikes land in the attack [ASSUMED: the skeleton's 0.267 s between them is not
// modelled]); then back to his single attack (lessng_s2[switch_mode]).
// - S3 苦修破誓 (MANUAL, 20 s; data DEFAULT): max HP +max_hp (MULTIPLIER), attacks on a blocked target (by anyone) at
// lessng_s3[atk_scale] × ATK, immune to every 异常状态 (晕眩, 寒冷, 冻结 … — tier6 ABNORMAL) while it runs. Cast while under a
// 异常状态: magical_value arts damage to himself first (source himself, may knock him out; 苦痛专注 and 痛楚砺刃 see it as any
// damage), then every 异常状态 is cleansed, then the effects apply (the HP buff after the damage). "可以无视异常状态开启": the
// basic strategy casts it when he is about to attack, and 沉默 does not hold it back; 晕眩 / 冻结 / 沉睡 stop his attack and so
// the cast [ASSUMED: the official 基础策略 waits for an attack too].
// Melee, ground-only (data canHitFly false: no anti-air); ground enemies target him normally (no 起飞 / 迷彩 / 隐匿).
import { num, talentBb, moduleBb, traitBb, skillRec, up } from '../shared/tier1.js';
import { ABNORMAL, hasAbnormal, cleanseAbnormal } from '../shared/tier6.js';
import { holdsUndying } from '../../items/battle.js';
const S1 = 'skchr_lessng_1';
const S2 = 'skchr_lessng_2';
const S3 = 'skchr_lessng_3';
/** S2 虔修对决's window after a deployment (2连击, ATK, 苦痛专注 ×talent_scale). */
export const DUEL_KEY = 'skill:lessng:duel';
/** S3 苦修破誓's effects while it runs (max HP; the status immunity and the blocked-target scale read it). */
export const OATH_KEY = 'skill:lessng:oath';
export const PAIN_KEY = 'talent:lessng:pain';
export const REBORN_KEY = 'trait:lessng:reborn';
const bbOf = (chess, id) => skillRec(chess, id)?.bb ?? {};
/** He blocks at least one living enemy (苦痛专注 "阻挡时"). */
const blocking = (u) => u.blocking.some((e) => e && e.alive && e.blockedBy === u);
export default {
char_4011_lessng: (bb, chess) => {
const tb = traitBb(chess); // DRE-X: atk_scale; DRE-Y: max_hp / attack_speed / hp_ratio / value
const t0 = talentBb(chess, 0); // 苦痛专注 (DRE-Y stage 3: 0.4)
const t1 = talentBb(chess, 1); // 痛楚砺刃 (DRE-X stage 3: 0.2)
const hb = moduleBb(chess); // DRE-Y stage 3: def_penetrate
const b1 = bbOf(chess, S1), b2 = bbOf(chess, S2), b3 = bbOf(chess, S3);
const s2 = skillRec(chess, S2);
const blockedScale = num(tb.atk_scale, 1);
const oathScale = num(b3['lessng_s3[atk_scale].atk_scale'], 1);
const duelOn = (u) => !!u.findBuff(DUEL_KEY);
const oathOn = (u) => !!u.findBuff(OATH_KEY);
return {
skills: {
[S1]: { kind: 'instant', attack: { atkScale: num(b1.atk_scale, 1) } },
[S2]: {
kind: 'passive',
onStart({ battle, unit }) { // every deployment (skills.js reset → passive start)
const dur = num(s2?.duration);
if (dur > 0) battle.addBuff(unit, { key: DUEL_KEY, duration: dur, mods: { atkPct: num(b2.atk) }, tags: ['skill'], visible: true });
},
},
[S3]: {
kind: 'duration',
onStart({ battle, unit }) {
if (hasAbnormal(unit)) {
battle.dealDamage(unit, unit, { amount: num(b3.magical_value), type: 'arts', canDodge: false, isSkill: true, tags: ['skill', 'lessngOath'] });
if (!unit.alive) return;
cleanseAbnormal(battle, unit);
}
battle.addBuff(unit, { key: OATH_KEY, mods: { hpPct: num(b3.max_hp) }, tags: ['skill'], visible: true });
},
onEnd({ battle, unit }) { battle.removeBuff(unit, OATH_KEY); },
},
},
trait: {
// S2's 2连击 (only while its window runs; 1 otherwise and under every other skill)
hitsFn: (b, u) => (duelOn(u) ? 2 : 1),
// DRE-X ×atk_scale and S3 ×lessng_s3[atk_scale] on a blocked target (CheckBlocked of the target: by anyone)
dmgMul: (b, u, t) => (t && t.blockedBy ? blockedScale * (oathOn(u) ? oathScale : 1) : 1),
},
talents: [
{ install(battle, unit) { // 苦痛专注
const cut = num(t0.damage_resistance), scale2 = num(b2.talent_scale, 1);
if (!(cut > 0)) return;
battle.on('hit', (c) => {
if (c.target !== unit || !up(unit) || !blocking(unit)) return;
const d = c.dmg;
if (!d || (d.type !== 'phys' && d.type !== 'arts')) return;
const src = c.source; // null = 无来源
if (src && src.side === 'enemy' && src.blockedBy === unit) return;
d.mul *= Math.max(0, 1 - cut * (duelOn(unit) ? scale2 : 1));
}, { owner: unit });
} },
{ install(battle, unit) { // 痛楚砺刃
const atk = num(t1.atk), dur = num(t1.add_atk_duration, 15);
if (!atk) return;
battle.on('hit', (c) => {
if (c.target !== unit || !up(unit)) return;
battle.addBuff(unit, { key: PAIN_KEY, duration: dur, refresh: 'replace', mods: { atkPct: atk }, tags: ['talent'], visible: true });
}, { owner: unit });
} },
],
install(battle, unit) {
// DRE-Y stage 3: 攻击自身阻挡的敌人时,无视目标12%的防御力 (every damage of his to an enemy he blocks)
const pen = num(hb.def_penetrate);
if (pen > 0) {
battle.on('hit', (c) => {
if (c.source === unit && c.target && c.target.side === 'enemy' && c.target.blockedBy === unit) c.dmg.defIgnorePct += pen;
}, { owner: unit });
}
// DRE-Y trait: 被击倒时不撤退且回复所有生命但生命上限-60%,攻击速度+30(单次部署只触发1次)
if (tb.hp_ratio != null && (tb.max_hp != null || tb.value != null)) {
const hpMul = tb.max_hp != null ? num(tb.max_hp, 0.4) : 1 - num(tb.value, 0.6);
let usedSeq = -1;
battle.on('fatal', (c) => {
if (c.unit !== unit || c.prevented || usedSeq === unit.deploySeq || holdsUndying(battle, unit)) return;
c.prevented = true;
usedSeq = unit.deploySeq;
battle.addBuff(unit, { key: REBORN_KEY, mods: { hpMul: Math.max(0.05, hpMul), aspd: num(tb.attack_speed) }, tags: ['trait'], visible: true });
unit.hp = Math.max(1, unit.s.maxHp * num(tb.hp_ratio, 1));
battle.fx('revive', { x: unit.x, y: unit.y, id: unit.id, module: true });
}, { owner: unit, priority: -60 });
}
// S3 苦修破誓: status immunity while it runs; "可以无视异常状态开启" — 沉默 does not hold the basic-strategy cast back
battle.on('beforeStatus', (c) => {
if (c.target === unit && oathOn(unit) && ABNORMAL.has(c.status)) c.cancel = true;
}, { owner: unit });
battle.on('beforeAttack', (c) => {
const sk = unit.skill;
if (c.attacker !== unit || !sk || sk.id !== S3 || !sk.ready || sk.active || sk.opCooling || !unit.s.flags.silence) return;
sk.activate('abnormal');
}, { owner: unit });
},
};
},
};