Playtest #6 follow-up (v2.5.1): leader HP review — 直接乘算, one debuff instance, 999 layer cap, 限伤; elite to the board; 假想敌:胄 kit

- co-op leaders died within seconds: leader HP is the official data (40 values pinned); bond / strategy / item /
  机变 / 特质 "+X%" bonuses now add up (PRTS 直接乘算) instead of compounding; a same-named enemy debuff keeps one
  (strongest) instance per target (奥术 across a pair field); leader parts pass damage 1:1; fixed co-op pool (the user's call)
- official limits read from the client: each bond stops at 999 layers (MAX_GARRISON_STACK); a leader hit of 300000+ in
  boss / hidden battles is cancelled (MAX_BATTLE_DAMAGE, 限伤) — shared/constants.js switches, research 11
- a merge that consumes a deployed copy puts the elite on that tile and facing (user-confirmed); gold target highlight,
  promotion effect
- 假想敌:胄 per PRTS: one shell, shells within range, any drone death costs 2 % max HP, 剑/锤 sorties and 瘫痪
- DESIGN §20.10–§20.14; 2842 unit tests, all 28 browser suites green; Chrome = Node on boss fields
This commit is contained in:
sganggs committed 2026-10-02 04:19:28 +08:00
1 parent 6464e4b46a
commit 620f88c0d8
81 files changed
+4194 -447

No files matched your search

+36 -1
View File
@@ -494,7 +494,7 @@ test('灵知 S2: 130 % ATK arts + 2.5 s cold to all in range; fully charged cast
approx(burst[0].amount, u.s.atk * bb.atk_scale, 1e-6);
assert.ok(a.s.flags.freeze && b.s.flags.freeze, 'charged cast: second cold ⇒ freeze');
h.run(0.2);
approx(a.findBuff(`gnosis:fragile:${u.id}`).mods.dmgTakenMul, t0.damage_scale_freeze, 1e-9, 'frozen ×2 fragile');
approx(a.findBuff('gnosis:fragile').mods.dmgTakenMul, t0.damage_scale_freeze, 1e-9, 'frozen ×2 fragile');
// next (single-charge) cast only chills once per enemy
assert.ok(h.runUntil(() => u.skill.activations >= 2, 20));
const starts = noisy(h, 'skillStart').filter((c) => c.unit === u).map((c) => c.t);
@@ -552,6 +552,41 @@ test('莱恩哈特 S2: 170 % ATK arts to all enemies in the wider skill range +
assert.ok(inR.alive);
});
test('同名效果取最高: two 灵知 never compound 坚冰, two 莱恩哈特 never compound the RES cut (one instance per enemy, the strongest)', () => {
// DESIGN §20.10 (the 奥术 rule): a pair / 联防 partner's copy of the same operator puts the same-named effect on the
// same enemy — one instance, the strongest (PRTS 作战机制 "同名buff…只能表现出一个"), never m × m
const gn = 'chess_char_4_13_a', t0 = D(gn).talents[0].bb;
const g = makeBattle({ defs: { enemies: { enemy_dummy: dummy() } }, units: [{ chessId: gn, row: 10, col: 3 }, { chessId: gn, row: 11, col: 3 }], timeLimit: 60, hooks: [] });
g.step();
const both = g.b.allyUnits.filter((u) => u.def.id === gn);
assert.equal(both.length, 2, 'two 灵知 on the board');
const e = g.spawn('enemy_dummy', { pos: [10, 4] });
let seen = 0;
for (let i = 0; i < 120; i++) { // 4 s: chilled / frozen by both
g.step();
const fr = e.buffs.filter((b) => String(b.key).startsWith('gnosis:fragile'));
assert.ok(fr.length <= 1, `one 坚冰 instance (${fr.map((b) => b.key)})`);
if (!fr.length) continue;
seen++;
const want = e.s.flags.freeze ? t0.damage_scale_freeze : t0.damage_scale_cold;
approx(e.s.dmgTakenMul, fr[0].mods.dmgTakenMul, 1e-9, 'the only damage-taken modifier');
assert.ok(e.s.dmgTakenMul <= t0.damage_scale_freeze + 1e-9 && fr[0].mods.dmgTakenMul >= want - 1e-9, `never ${t0.damage_scale_cold}² / ${t0.damage_scale_freeze}² (${e.s.dmgTakenMul})`);
}
assert.ok(seen > 30, `坚冰 was up (${seen})`);
const lh = 'chess_char_4_14_a', bb = D(lh).skill.bb;
const h = makeBattle({ defs: { enemies: { enemy_dummy: dummy({ res: 50 }) } }, units: [{ chessId: lh, row: 10, col: 3 }, { chessId: lh, row: 11, col: 3 }], timeLimit: 60, hooks: [] });
h.step();
const two = h.b.allyUnits.filter((u) => u.def.id === lh);
assert.equal(two.length, 2);
const x = h.spawn('enemy_dummy', { pos: [10, 5] });
h.step();
for (const u of two) assert.ok(u.skill.activate('test', { free: true }), 'S2 cast');
assert.equal(x.buffs.filter((b) => String(b.key).startsWith('lionhd:res')).length, 1, 'one RES cut');
approx(x.s.res, 50 * (1 + bb.magic_resistance), 1e-9, 'RES −8 % once, not twice');
h.run(bb.duration + 0.1);
approx(x.s.res, 50, 1e-9, 'expired');
});
test('录武官 S2: healed allies regain 80 HP whenever damaged for 10 s; 学成于聚 SP +1 & ASPD +16 when an operator in range casts', () => {
const id = 'chess_char_4_15_a', bb = D(id).skill.bb, t0 = D(id).talents[0].bb;
const h = makeBattle({ units: [{ chessId: id, row: 10, col: 3 }, { chessId: 'chess_char_1_02_a', row: 10, col: 4 }], timeLimit: 60, hooks: ['heal'], captureNoisy: true });