feedback5: merge feedback4 (583899d) — W4B ported: 阿戈尔's devoured base ATK as a 最终加算 (atkFinal), a fallen marker's marks still resolve, 缇缇 S2 pulses re-enter sleep for her trait (applyStatus reenter in server/sim/battle/status.js; the 缇缇 kit in kits/ops/chess_char_5_02-titi.js; Battle.js / tier5.js stay feedback5's façade and shim); golden: roster-042, bond-egirShip-high, coop2-ABYSS-10-boosted moved, the same three as on feedback4 (bond-egirShip-high identical to it)

This commit is contained in:
sganggs committed 2026-10-06 14:47:13 +08:00
commit c6827a0eaf
20 files changed
+302 -96

No files matched your search

+48 -4
View File
@@ -335,7 +335,29 @@ test('阿戈尔: HP ×(1.35+0.01L); devour chain (left first): 5000 物理流失
checkInvariants(h.b);
});
test('阿戈尔 devour: 物理流失 ignores the marker’s damage bonuses and the target’s shields; a dead marker’s marks are cancelled; kill → marker', () => {
test('阿戈尔 devour ATK is a 最终加算 (GitHub #165 point 2, PR #176): 1000 base ATK, +100 % skill ATK, +2000 devoured → 4000, not 6000', () => {
// PRTS 盟约记录 "该付与来源获得所有标记单位的基础攻击力(最终加算)"; PRTS 游戏数据基础 A_f = F_t[(A + D_p)(1 + D_t) + F_p]
const list = [
['g1_a', ['egirShip']], ['g2_a', ['egirShip']], ['g3_a', ['egirShip']],
['fod_a', ['preciShip'], { stats: { atk: 2000, maxHp: 20000, def: 0, blockCnt: 1 } }],
];
// g1 (10,3) → fodder (10,4, 2000 base ATK); g2 / g3 face empty tiles
const units = [{ chessId: 'g1_a', row: 10, col: 3 }, { chessId: 'fod_a', row: 10, col: 4 }, { chessId: 'g2_a', row: 12, col: 3 }, { chessId: 'g3_a', row: 12, col: 5 }];
const h = makeBattle({ defs: defsOf(list), units, bonds: { egirShip: bondOn(3, 0, null, [3, 5]) } });
h.step(1);
const g1 = h.unit('g1_a');
assert.deepEqual(buffOf(g1, 'bond:egir:devour')?.mods, { atkFinal: 2000, blockCnt: 1 }, 'the fodder\'s base ATK as a 最终加算, its block count');
close(g1.s.atk, 1000 + 2000, 1e-6, 'no percentage: as before');
h.b.addBuff(g1, { key: 'test:skill', mods: { atkPct: 1 } });
close(g1.s.atk, 1000 * 2 + 2000, 1e-6, '+100 %: 4000 (0.1.3: (1000 + 2000) × 2 = 6000)');
h.b.addBuff(g1, { key: 'test:flat', mods: { atkFlat: 100 } });
close(g1.s.atk, (1000 + 100) * 2 + 2000, 1e-6, 'a 直接加算 is still scaled by the percentages');
h.b.addBuff(g1, { key: 'test:weaken', mods: { atkMul: 0.5 } });
close(g1.s.atk, ((1000 + 100) * 2 + 2000) * 0.5, 1e-6, 'the 最终乘算 (Πmul) scales the whole, the 最终加算 included');
checkInvariants(h.b);
});
test('阿戈尔 devour: 物理流失 ignores the marker’s damage bonuses and the target’s shields; a fallen marker’s marks still resolve (GitHub #165 point 3); kill → marker', () => {
const list = [
['g1_a', ['egirShip', 'kjeragShip']], ['g2_a', ['egirShip'], { stats: { maxHp: 3000 } }], ['g3_a', ['egirShip']],
['fod_a', ['preciShip'], { tier: 2, stats: { maxHp: 20000, def: 500 } }],
@@ -353,14 +375,36 @@ test('阿戈尔 devour: 物理流失 ignores the marker’s damage bonuses and t
assert.ok(!g2.alive, 'g2 devoured');
assert.ok(h.hooksOf('kill').some((c) => c.victim === g2 && c.killer === g1), 'kill credited to the marker');
const dv = tagged(h, 'bond:egir:devour');
assert.deepEqual(dv.map((c) => [c.source.defId, c.target.defId]), [['g1_a', 'g2_a'], ['g1_a', 'fod_a']], 'g2’s own mark on the fodder is cancelled');
close(f.hp, 20000 - (5000 - 500), 1e-6, '5000 less its DEF 500: no ×1.25, shield untouched');
// PRTS 盟约记录: only the knocked-out TARGET's pending marks are cancelled — g2, knocked out by the first mark, still
// resolves its own (until 0.1.3 a marker off the field gave no further mark)
assert.deepEqual(dv.map((c) => [c.source.defId, c.target.defId]), [['g1_a', 'g2_a'], ['g1_a', 'fod_a'], ['g2_a', 'fod_a']], 'g2’s own mark on the fodder resolves');
close(f.hp, 20000 - 2 * (5000 - 500), 1e-6, '5000 less its DEF 500, twice: no ×1.25, shield untouched');
assert.equal(f.buffs.find((b) => b.key === 'test:shield')?.shield, 3000);
close(g1.s.atk, 1000 + 1000 + 1000, 1e-6, 'the base ATK of everything it marked stays');
assert.equal(h.b.getPlayer('p1').bonds.egirShip.layers, 1 + 2, 'layers = tiers of the devoured units');
checkInvariants(h.b);
});
test('阿戈尔 devour, A → B → C with B devoured first (GitHub #165 point 3, PR #176): C still takes B\'s 5000 and the kill is B\'s', () => {
const list = [
['A_a', ['egirShip']], ['B_a', ['egirShip'], { stats: { maxHp: 3000 } }], ['g3_a', ['egirShip']],
['C_a', ['preciShip'], { tier: 2, stats: { maxHp: 9000, def: 0 } }],
];
// A (10,3) → B (10,4, 3000 × 1.35 HP: knocked out by A's mark) → C (10,5, 9000 HP, DEF 0: A's mark leaves 4000, B's
// knocks it out); g3 faces an empty tile. Marks: A → B, A → C (through B), B → C.
const units = [{ chessId: 'A_a', row: 10, col: 3 }, { chessId: 'B_a', row: 10, col: 4 }, { chessId: 'C_a', row: 10, col: 5 }, { chessId: 'g3_a', row: 12, col: 3 }];
const h = makeBattle({ defs: defsOf(list), units, bonds: { egirShip: bondOn(3, 0, null, [3, 5]) }, hooks: ['damaged', 'kill'], captureNoisy: true });
h.step(1);
const [A, B, C] = ['A_a', 'B_a', 'C_a'].map((id) => h.unit(id));
assert.deepEqual(tagged(h, 'bond:egir:devour').map((c) => [c.source.defId, c.target.defId]), [['A_a', 'B_a'], ['A_a', 'C_a'], ['B_a', 'C_a']]);
assert.ok(!B.alive && !C.alive, 'B falls to A\'s mark, C to B\'s (until 0.1.3 B\'s mark was dropped: C stood at 4000 HP)');
// PRTS 盟约记录 "单位被【吞噬】击杀时,击杀来源始终为对应标记的付与来源"
assert.deepEqual(h.hooksOf('kill').map((c) => [c.victim.defId, c.killer?.defId]), [['B_a', 'A_a'], ['C_a', 'B_a']], 'the kill credit is the mark\'s marker, down or not');
close(A.s.atk, 1000 + 1000 + 1000, 1e-6, 'A: the base ATK of B and C');
assert.equal(h.b.getPlayer('p1').bonds.egirShip.layers, 1 + 2, 'each devoured unit adds its tier once');
checkInvariants(h.b);
});
test('阿戈尔 devour order: left first, then top first (row 0 is the bottom: the top board row is 12)', () => {
const list = [['g1_a', ['egirShip']], ['g2_a', ['egirShip']], ['g3_a', ['egirShip']], ['fod_a', ['preciShip']]];
const units = [
@@ -600,7 +644,7 @@ test('阿戈尔 devour, a unit back during the pass: a marker revived by the 5-t
h.step(1);
const [g2, f] = ['g2_a', 'fod_a'].map((id) => h.unit(id));
assert.ok(g2.alive && h.hooksOf('deploy').some((c) => c.unit === g2 && !c.initial), 'g2 knocked out and revived');
// only a marker off the field gives no further mark (the rule since 0.1.0): g2, back at once, still devours g3 and the fodder
// every mark resolves whatever became of its marker (DESIGN §24.7): g2, back at once, still devours g3 and the fodder
assert.deepEqual(tagged(h, 'bond:egir:devour').map((c) => [c.source.defId, c.target.defId]),
[['g1_a', 'g2_a'], ['g1_a', 'g3_a'], ['g1_a', 'fod_a'], ['g2_a', 'g3_a'], ['g2_a', 'fod_a'], ['g3_a', 'fod_a']]);
close(f.hp, 20000 - 3 * 5000, 1e-6, 'the fodder: g1, g2 and g3');
+3 -3
View File
@@ -39,7 +39,7 @@ test('联防 阿戈尔 chain 乌尔比安 → 幽灵鲨 (down) → 歌蕾蒂娅
const got = buffOf(ulpia, 'bond:egir:devour');
assert.ok(ref && got, 'both 乌尔比安 devour');
const base = (id) => down.unit(id).base;
close(got.mods.atkFlat, base(GHOST).atk + base(GLADY).atk + base(FODDER).atk, 1e-6, 'the base ATK of 幽灵鲨, 歌蕾蒂娅 and the fodder');
close(got.mods.atkFinal, base(GHOST).atk + base(GLADY).atk + base(FODDER).atk, 1e-6, 'the base ATK of 幽灵鲨, 歌蕾蒂娅 and the fodder');
assert.equal(got.mods.blockCnt, base(GHOST).blockCnt + base(GLADY).blockCnt + base(FODDER).blockCnt);
assert.deepEqual(got.mods, ref.mods, 'exactly the gains of the chain with 幽灵鲨 standing');
close(ulpia.s.atk, up.unit(ULPIA).s.atk, 1e-6, '乌尔比安 ATK');
@@ -57,7 +57,7 @@ test('联防 阿戈尔 chain 乌尔比安 → 幽灵鲨 (down) → 歌蕾蒂娅
assert.equal(fodder.alive, up.unit(FODDER).alive);
// her own marks (歌蕾蒂娅, the fodder) still give her their base ATK / block for when she is back
const own = buffOf(ghost, 'bond:egir:devour');
close(own ? own.mods.atkFlat : 0, base(GLADY).atk + base(FODDER).atk, 1e-6, '幽灵鲨 keeps her marking gains (a persistent buff)');
close(own ? own.mods.atkFinal : 0, base(GLADY).atk + base(FODDER).atk, 1e-6, '幽灵鲨 keeps her marking gains (a persistent buff)');
checkInvariants(down.b);
assert.equal(down.result().perPlayer.p1.deaths, up.result().perPlayer.p1.deaths - 1, 'no knock-out counted for her (standing, the devour knocks her out)');
});
@@ -84,7 +84,7 @@ test('联防 阿戈尔: a down member at the head of the chain devours as if it
const down = head(true, five);
const [ghost, glady, fodder] = [GHOST, GLADY, FODDER].map((id) => down.unit(id));
const g = buffOf(ghost, 'bond:egir:devour');
close(g.mods.atkFlat, glady.base.atk + fodder.base.atk, 1e-6, `${tag}: marks 歌蕾蒂娅 and, through her, the fodder`);
close(g.mods.atkFinal, glady.base.atk + fodder.base.atk, 1e-6, `${tag}: marks 歌蕾蒂娅 and, through her, the fodder`);
const pairs = (h) => devours(h).map((c) => [c.source.defId, c.target.defId]);
assert.deepEqual(pairs(down), pairs(up), `${tag}: the marks resolve as with 幽灵鲨 standing`);
assert.deepEqual(pairs(down), [[GHOST, GLADY], [GHOST, FODDER]], `${tag}: her two marks; 歌蕾蒂娅's on the fodder is cancelled (knocked out first)`);
+3 -3
View File
@@ -52,7 +52,7 @@ test('联防: an 阿戈尔 devours a teammate\'s living operator in front — th
const ref = buffOf(solo.unit(1), 'bond:egir:devour');
const fodderBase = solo.unit(100).base;
assert.ok(ref, 'solo: 乌尔比安 devours the operator in front');
close(ref.mods.atkFlat, fodderBase.atk, 1e-9, 'its base ATK');
close(ref.mods.atkFinal, fodderBase.atk, 1e-9, 'its base ATK');
assert.equal(ref.mods.blockCnt, fodderBase.blockCnt, 'its block count');
for (const [tag, h] of [['own', own], ['teammate\'s', mate]]) {
const ulpia = h.unit(1), t = h.unit(100);
@@ -92,7 +92,7 @@ test('联防: the chain goes on through a teammate\'s 阿戈尔 — the gains eq
const p2Units = [HN, MIZUKI, GLADY, DEEP].map((chessId, i) => ({ uid: 200 + i, kind: 'chess', chessId, row: 12, col: 3 + 2 * i, dir: 'RIGHT' }));
const mate = field({ owner: 'mate', front: [GHOST, FODDER], p2Units, p2Bonds: { egirShip: bondOn(5) } });
const ref = buffOf(own.unit(1), 'bond:egir:devour');
close(ref.mods.atkFlat, own.unit(100).base.atk + own.unit(101).base.atk, 1e-9, 'own chain: 幽灵鲨 and, through her, the fodder');
close(ref.mods.atkFinal, own.unit(100).base.atk + own.unit(101).base.atk, 1e-9, 'own chain: 幽灵鲨 and, through her, the fodder');
assert.deepEqual(buffOf(mate.unit(1), 'bond:egir:devour')?.mods, ref.mods, 'the teammate\'s chain gives the same');
assert.deepEqual(devours(mate).map((c) => [c.source.uid, c.target.uid]), devours(own).map((c) => [c.source.uid, c.target.uid]));
const ghost = mate.unit(100);
@@ -134,7 +134,7 @@ test('联防 through unite.js: food knocked out by the own combat\'s devour ente
u.step();
const ulpia = u.unit(1);
assert.deepEqual(buffOf(ulpia, 'bond:egir:devour')?.mods, gain, 'the own combat\'s gains');
close(gain.atkFlat, [2, 3, 4].reduce((s, uid) => s + u.unit(uid).base.atk, 0), 1e-9, '幽灵鲨 + 歌蕾蒂娅 + fodder base ATK');
close(gain.atkFinal, [2, 3, 4].reduce((s, uid) => s + u.unit(uid).base.atk, 0), 1e-9, '幽灵鲨 + 歌蕾蒂娅 + fodder base ATK');
assert.equal(gain.blockCnt, [2, 3, 4].reduce((s, uid) => s + u.unit(uid).base.blockCnt, 0));
for (const uid of [2, 3, 4]) assert.ok(!u.unit(uid).alive && u.unit(uid).removeReason === FORCED_EXIT, `${uid} forced out`);
assert.equal(u.b.getPlayer('p1').bonds.egirShip.layers, 10, 'no layers in 联防');
+53
View File
@@ -302,6 +302,59 @@ test('allyenemy_sleepstun_inrange (缇缇 125): enemies or operators entering
assert.equal(capOf('garrison_125_b'), 48);
});
test('缇缇 125 + S2 封护 (GitHub #162): every 0.25 s sleep pulse of the ward is a new entry — 8 s climb to the cap; a sleeper outside her range does not count', () => {
// the reporter's memory of the official mode: 「攻击范围内有陷入沉睡就开始迅速增加直至上限」; the pulse timing is [ASSUMED]
for (const id of ['chess_char_5_02_a', 'chess_char_5_02_b']) {
const gid = D.chess[id].garrisonIds.find((g) => GR(g).effectKey === 'act2autochess_gar_event_allyenemy_sleepstun_inrange');
const per = num(GR(gid).bb.bond_add_count), cap = capOf(gid);
const s2 = D.chess[id].skills.find((x) => x.skillId === 'skchr_titi_2').index;
// 缇缇 (10,4) facing right: range 3-3 = rows 9–11, cols 4–7. The ward ally (10,6) is the only operator in it; the
// enemy (10,5) stands beside both wards (in her range), the one at (10,3) beside her back (out of her range)
const run = (enemies) => {
const h = makeBattle({
seed: 3, autoFinish: false, timeLimit: 400, hooks: ['statusApplied'],
defs: { chess: { ward: rec('ward', []) }, enemies: { e_dummy: dummy() } },
units: [{ chessId: id, skillIndex: s2, row: 10, col: 4 }, { chessId: 'ward', row: 10, col: 6 }],
bonds: { sargonShip: B(0), preciShip: B(0) }, enemies,
});
h.step(1);
const tt = h.unit(id);
tt.skill.gainSp(1000);
assert.ok(tt.skill.activate('test'), `${id}: S2 cast`);
assert.equal(tt.skill.id, 'skchr_titi_2');
return { h, tt };
};
// out of range only: the pulses sleep it (each one an entry for the engine) but her trait ignores it
{
const { h, tt } = run([{ key: 'e_dummy', pos: [10, 3] }]);
const back = h.enemies()[0];
expectAll(h, ['sargonShip', 'preciShip'], 2 * per, `${id}: the ward's two operators fall asleep in her range`);
h.run(8);
assert.ok(tt.skill.active && back.s.flags.sleep, `${id}: the enemy at her back sleeps`);
const pulses = h.hooksOf('statusApplied').filter((c) => c.target === back && c.source === tt && c.entered);
assert.ok(pulses.length >= 30, `${id}: ${pulses.length} pulse entries in 8 s`);
expectAll(h, ['sargonShip', 'preciShip'], 2 * per, `${id}: an out-of-range sleeper does not count`);
checkInvariants(h.b);
}
// in range: one entry per pulse (beside both wards: still one), the cap within the 8 s
{
const { h, tt } = run([{ key: 'e_dummy', pos: [10, 5] }, { key: 'e_dummy', pos: [10, 3] }]);
const near = h.enemies().find((e) => Math.round(e.x) === 5);
let capAt = null;
for (let t = 0; t < 8 - 1e-9; t += 0.25) {
h.run(0.25);
if (capAt == null && (gains(h).sargonShip ?? 0) >= cap) capAt = t + 0.25;
}
assert.ok(tt.skill.active && near.s.flags.sleep, `${id}: still asleep after 8 s`);
const mine = h.hooksOf('statusApplied').filter((c) => c.target === near && c.source === tt && c.status === 'sleep');
assert.equal(mine.filter((c) => c.entered).length * 2, mine.length, `${id}: two wards, one entry per pulse`);
expectAll(h, ['sargonShip', 'preciShip'], cap, `${id}: the cap (${cap})`);
assert.ok(capAt != null && capAt <= 6.5, `${id}: capped after ${capAt} s`);
checkInvariants(h.b);
}
}
});
// ---------------------------------------------------------------------------------------------------------------------
// ADD_BOND grants
+12 -12
View File
@@ -220,8 +220,8 @@
"round": 10,
"seed": 3867395638,
"waveId": "act1autochess_h03",
"time": 74.03,
"ticks": 2221,
"time": 89.03,
"ticks": 2671,
"reason": "cleared",
"killed": 19,
"total": 19,
@@ -230,23 +230,23 @@
"rngDraws": 0,
"errors": {"count":0,"kinds":[]},
"players": {
"p1": {"killed":19,"total":19,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":379469,"bossDmg":0,"heal":4635,"deaths":1,"layerGains":{"raidShip":10}}
"p1": {"killed":19,"total":19,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":379469,"bossDmg":0,"heal":4635,"deaths":1,"layerGains":{"raidShip":8}}
},
"units": [
["p1",1,"op","chess_char_1_04_b",1,"uniequip_002_udflow",32931.36,1,2,0,0,0,0,0,0],
["p1",2,"op","chess_char_2_07_b",1,"uniequip_002_ghost",27707.68,1,3,0,0,4635,4635,0,0],
["p1",3,"op","chess_char_3_05_b",2,"uniequip_002_skadi",18673.58,1,11,11,135708,36837,0,45,1],
["p1",3,"op","chess_char_3_05_b",2,"uniequip_002_skadi",19561.92,1,11,9,153631,35961,0,57,1],
["p1",4,"op","chess_char_4_16_b",2,"uniequip_002_texas2",1619,1,17,0,0,1619,0,0,2],
["p1",5,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",20727.84,1,6,4,186331,0,0,12,2],
["p1",6,"op","chess_char_3_09_b",1,"uniequip_002_haini",17395.56,1,7,0,23243,0,0,20,1],
["p1",7,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,8,4,34187,0,0,35,15],
["p1",5,"op","chess_char_4_09_b",1,"uniequip_002_mizuki",20727.84,1,6,5,133052,0,0,14,2],
["p1",6,"op","chess_char_3_09_b",1,"uniequip_002_haini",17395.56,1,7,1,44900,0,0,54,2],
["p1",7,"op","chess_char_4_13_b",1,"uniequip_002_gnosis",1989,1,8,4,47885,0,0,54,21],
["p1",8,"op","chess_char_4_14_b",1,"uniequip_002_lionhd",1626,1,1,0,0,0,0,0,0]
],
"enemies": {"enemy_1229_darmy":[10,10,0,4638,104509],"enemy_1229_darmy_2":[7,7,0,18088,95800],"enemy_9007_acelem":[2,2,0,4609,179159]},
"hooks": [1,29,2221,148,148,256,276,251,20,21,21,20,0,4154,485,13,19,0,1,20,5,3,0],
"events": {"atk":167,"deploy":10,"die":21,"dmg":276,"engage":4,"fx":34,"layer":5,"skill":41,"spawn":27,"status":132},
"fx": {"beam":2,"blink":1,"burst":3,"devour":4,"dilemma":2,"frostNova":15,"garrison":5,"swordStorm":2},
"snaps": "066fec91 aec41fca b75071e0 478fe370 a68e442a 1b0b0907 cc527129 08c4150f"
"enemies": {"enemy_1229_darmy":[10,10,0,6146,104509],"enemy_1229_darmy_2":[7,7,0,9732,95800],"enemy_9007_acelem":[2,2,0,10581,179159]},
"hooks": [1,29,2671,206,206,337,354,251,20,21,28,28,0,5849,650,12,19,0,1,20,4,2,0],
"events": {"atk":222,"deploy":10,"die":21,"dmg":354,"engage":4,"fx":38,"layer":4,"skill":56,"spawn":27,"status":180},
"fx": {"beam":2,"blink":1,"burst":2,"devour":4,"dilemma":2,"frostNova":21,"garrison":4,"swordStorm":2},
"snaps": "bc558eb6 7676040f 1d3db929 9a6a9f81 69a155b8 633af258 443f1b65 60398dc5 f22ce2d0"
},
"bond-emptyShip-low": {
"about": "协防干员 low: tier 1 layers 1; chess_char_4_01_a chess_char_4_04_a chess_char_2_14_a chess_char_3_10_a chess_char_3_20_a chess_char_3_21_a chess_char_4_02_a chess_char_4_06_a",
+14 -14
View File
@@ -1382,7 +1382,7 @@
"combat": "client",
"boost": {"lp":400,"layers":300},
"setup": {"stageId":"act2autochess_m04","bossId":"boss_5","hiddenBossId":"boss_9","factions":["FLY","ELEMENT","INVISIBLE"]},
"end": {"victory":true,"roundsPassed":15,"hiddenReached":true,"hiddenCleared":true,"reason":"victory","teamLp":800,"bossPoolLeft":0,"virtualMs":126150},
"end": {"victory":true,"roundsPassed":15,"hiddenReached":true,"hiddenCleared":true,"reason":"victory","teamLp":793,"bossPoolLeft":0,"virtualMs":124650},
"rng": {"setup":25,"shop":674,"waves":0,"draft":61,"bots":22077,"meta":140},
"errors": {"engine":0,"logged":0,"sim":0,"dispatcher":0},
"rounds": [
@@ -1423,33 +1423,33 @@
},
{
"round": 8,
"ai_0": [1,400,12,0,0,4,8,"d692537c",1552,"arcaneShip 1/312, deputShip 0/304, egirShip 1/304, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 0/302, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 2/310, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 2/322, suntShip 0/300, swiftShip 0/302, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",18,18,0,64],
"ai_0": [1,400,12,0,0,4,8,"d692537c",1558,"arcaneShip 1/315, deputShip 0/304, egirShip 1/307, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 0/302, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 2/310, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 2/322, suntShip 0/300, swiftShip 0/302, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",18,18,0,64],
"ai_1": [1,400,11,0,3,4,8,"a8a41789",1261,"arcaneShip 0/302, deputShip 2/314, egirShip 0/300, emptyShip 0/300, indomShip 1/304, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/314, steadShip 1/329, suntShip 0/300, swiftShip 0/300, victoriaShip 0/305, visiShip 0/300, yanShip 0/305",20,20,0,67]
},
{
"round": 9,
"ai_0": [1,400,12,0,0,4,8,"8469d2a6",2226,"arcaneShip 2/315, deputShip 0/304, egirShip 1/323, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/310, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/314, raidShip 1/330, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/330, suntShip 0/300, swiftShip 0/306, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",24,24,0,77],
"ai_0": [1,400,12,0,0,4,8,"8469d2a6",2232,"arcaneShip 2/318, deputShip 0/304, egirShip 1/326, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/310, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/314, raidShip 1/330, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/330, suntShip 0/300, swiftShip 0/306, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",24,24,0,77],
"ai_1": [1,400,15,0,3,4,8,"59b4a75a",1568,"arcaneShip 0/302, deputShip 1/316, egirShip 0/300, emptyShip 0/300, indomShip 1/306, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/302, soloShip 0/314, steadShip 1/336, suntShip 0/300, swiftShip 0/300, victoriaShip 1/308, visiShip 0/300, yanShip 0/305",24,24,0,82]
},
{
"round": 10,
"ai_0": [1,400,12,0,0,5,8,"5e407c98",2262,"arcaneShip 2/320, deputShip 0/304, egirShip 1/334, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/314, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/320, raidShip 1/338, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/332, suntShip 0/300, swiftShip 0/306, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",12,12,0,93],
"ai_0": [1,400,12,0,0,5,8,"5e407c98",2268,"arcaneShip 2/323, deputShip 0/304, egirShip 1/337, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/314, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/320, raidShip 1/338, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/332, suntShip 0/300, swiftShip 0/306, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",12,12,0,93],
"ai_1": [1,400,15,0,0,5,8,"1cb9c2e4",1583,"arcaneShip 0/302, deputShip 1/318, egirShip 0/300, emptyShip 0/300, indomShip 1/308, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/304, soloShip 0/314, steadShip 1/342, suntShip 0/300, swiftShip 0/300, victoriaShip 1/311, visiShip 0/300, yanShip 0/305",12,12,0,97]
},
{
"round": 11,
"ai_0": [1,400,12,0,2,5,8,"cfd3ac7b",2321,"arcaneShip 1/323, deputShip 0/304, egirShip 1/352, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/322, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/324, raidShip 1/360, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",34,34,0,105],
"ai_0": [1,400,12,0,2,5,8,"cfd3ac7b",2321,"arcaneShip 1/326, deputShip 0/304, egirShip 1/353, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/322, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/324, raidShip 1/358, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/334, suntShip 0/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",34,34,0,105],
"ai_1": [1,400,12,0,1,6,8,"b6bd931e",2209,"arcaneShip 0/302, deputShip 1/320, egirShip 0/300, emptyShip 0/300, indomShip 1/312, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/306, soloShip 0/314, steadShip 1/349, suntShip 1/302, swiftShip 0/300, victoriaShip 1/316, visiShip 1/304, yanShip 0/305",34,34,0,120]
},
{
"round": 12,
"ai_0": [1,400,14,0,0,6,8,"e7a322b8",2348,"arcaneShip 1/323, deputShip 0/304, egirShip 1/353, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/330, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/332, raidShip 1/370, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",6,14,8,119],
"ai_0": [1,400,14,0,0,6,8,"e7a322b8",2348,"arcaneShip 1/326, deputShip 0/304, egirShip 1/354, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/330, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/332, raidShip 1/368, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/334, suntShip 0/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",6,14,8,119],
"ai_1": [1,400,13,0,1,6,8,"58fdf70d",2235,"arcaneShip 0/302, deputShip 1/322, egirShip 0/300, emptyShip 0/300, indomShip 2/314, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/308, soloShip 0/314, steadShip 1/357, suntShip 1/304, swiftShip 0/300, victoriaShip 1/324, visiShip 1/306, yanShip 0/310",15,15,0,134]
},
{
"round": 13,
"ai_0": [1,400,12,0,0,6,8,"feef54ce",2706,"arcaneShip 2/330, deputShip 0/304, egirShip 1/368, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/334, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/340, raidShip 1/390, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/340, suntShip 1/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",41,41,0,133],
"ai_1": [1,400,13,0,2,6,8,"6a6f946a",1962,"arcaneShip 0/302, deputShip 1/324, egirShip 0/300, emptyShip 0/300, indomShip 2/322, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/310, soloShip 0/314, steadShip 1/366, suntShip 1/306, swiftShip 0/300, victoriaShip 1/334, visiShip 0/306, yanShip 0/310",36,41,5,150]
"ai_0": [1,398,12,0,0,6,8,"feef54ce",2700,"arcaneShip 2/333, deputShip 0/304, egirShip 1/367, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/334, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/340, raidShip 1/386, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 1/300, swiftShip 0/310, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",39,41,2,133],
"ai_1": [1,395,13,0,2,6,8,"6a6f946a",1962,"arcaneShip 0/302, deputShip 1/324, egirShip 0/300, emptyShip 0/300, indomShip 2/322, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 0/309, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 1/310, soloShip 0/314, steadShip 1/366, suntShip 1/306, swiftShip 0/300, victoriaShip 1/334, visiShip 0/306, yanShip 0/310",36,41,5,150]
}
],
"players": {
@@ -1458,26 +1458,26 @@
"victory": true,
"roundsPassed": 15,
"eliminatedRound": null,
"lp": 400,
"lp": 398,
"bandId": "band_sarkazb",
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
"trophies": 8,
"reward": 425,
"stats": {"activatedLayers":2986,"bossDamage":4110836,"dmgDealt":14169113,"gold":158,"itemsEquipped":18,"kills":295,"leaks":8,"lpLost":0,"merges":7,"perfectRounds":12,"refreshes":25},
"stats": {"activatedLayers":2984,"bossDamage":4099302,"dmgDealt":13617793,"gold":158,"itemsEquipped":18,"kills":291,"leaks":10,"lpLost":2,"merges":7,"perfectRounds":11,"refreshes":25},
"lineup": ["4_09_b@11,5[4_11_e_a+6_09_e_a]","6_11_a@11,8","5_07_a@10,4[1_01_e_b+1_02_e_b]","1_19_b@10,8[5_02_e_a+4_04_e_a]","3_09_b@9,6[3_08_e_a+4_10_e_a]","6_05_a@9,7","4_20_a@9,8[2_01_e_a]","3_05_a@9,9[4_07_e_a+4_06_e_a]"],
"bonds": ["arcaneShip 1/330","deputShip 0/304","egirShip 1/368","emptyShip 0/300","indomShip 0/300","investShip 0/300","kazimierzShip 1/334","kjeragShip 0/302","lateranoShip 0/300","maniShip 1/300","miraShip 0/300","preciShip 1/345","raidShip 1/390","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/300","soloShip 1/304","steadShip 0/340","suntShip 1/300","swiftShip 1/315","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
"bonds": ["arcaneShip 1/333","deputShip 0/304","egirShip 1/367","emptyShip 0/300","indomShip 0/300","investShip 0/300","kazimierzShip 1/334","kjeragShip 0/302","lateranoShip 0/300","maniShip 1/300","miraShip 0/300","preciShip 1/345","raidShip 1/386","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/300","soloShip 1/304","steadShip 0/336","suntShip 1/300","swiftShip 1/315","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
},
"ai_1": {
"alive": true,
"victory": true,
"roundsPassed": 15,
"eliminatedRound": null,
"lp": 400,
"lp": 395,
"bandId": "band_doberm",
"title": {"id":"comment_3","name":"坚若磐石","picId":"comment_icon_3","text":"目标生命值损失最少"},
"title": {"id":"comment_5","name":"万事俱备","picId":"comment_icon_5","text":"装备配发数量最多"},
"trophies": 8,
"reward": 425,
"stats": {"activatedLayers":2322,"bossDamage":2829244,"dmgDealt":16856376,"gold":174,"itemsEquipped":28,"kills":280,"leaks":6,"lpLost":0,"merges":4,"perfectRounds":11,"refreshes":40},
"stats": {"activatedLayers":2322,"bossDamage":2840562,"dmgDealt":16880657,"gold":174,"itemsEquipped":28,"kills":280,"leaks":6,"lpLost":5,"merges":4,"perfectRounds":11,"refreshes":40},
"lineup": ["2_17_a@12,8[3_08_e_a+4_02_e_a]","5_03_a@11,8[3_02_e_a+3_10_e_a]","1_10_b@10,4[4_11_e_a+2_01_e_b]","4_11_a@10,5[2_03_e_b+3_10_e_b]","5_06_a@10,8[3_01_e_b+5_02_e_a]","3_16_a@9,3[2_03_e_b+3_09_e_a]","6_20_a@9,6[1_05_e_a+4_08_e_b]","1_06_b@9,9[3_08_e_b+1_05_e_b]"],
"bonds": ["arcaneShip 0/302","deputShip 1/328","egirShip 0/300","emptyShip 0/300","indomShip 1/326","investShip 0/300","kazimierzShip 0/300","kjeragShip 0/300","lateranoShip 0/300","maniShip 0/300","miraShip 0/300","preciShip 0/309","raidShip 0/300","sargonShip 0/300","siracusaShip 0/300","skillfulShip 1/314","soloShip 1/318","steadShip 2/384","suntShip 1/310","swiftShip 0/300","victoriaShip 1/342","visiShip 0/306","yanShip 0/310"]
}
+26 -26
View File
@@ -2546,14 +2546,14 @@
"round": 10,
"seed": 3609857679,
"waveId": "act1autochess_h03",
"time": 161.57,
"ticks": 4847,
"time": 178.03,
"ticks": 5341,
"reason": "cleared",
"killed": 59,
"total": 59,
"unspawned": 0,
"bossHpLeft": null,
"rngDraws": 64,
"rngDraws": 61,
"errors": {"count":0,"kinds":[]},
"players": {
"p1": {
@@ -2563,26 +2563,26 @@
"leaks": 0,
"leaksUncounted": 0,
"coins": 8,
"dmg": 704844,
"dmg": 706144,
"bossDmg": 0,
"heal": 28019,
"deaths": 3,
"heal": 27206,
"deaths": 6,
"layerGains": {"preciShip":80,"sargonShip":108}
}
},
"units": [
["p1",1,"op","chess_char_4_17_b",2,"none",4566.9,1,3,1,1288,0,0,2,0],
["p1",2,"op","chess_char_4_18_b",2,"none",6783,1,5,0,7191,0,0,3,1],
["p1",3,"op","chess_char_4_23_b",1,"uniequip_004_gvial2",3667.3,1,7,1,7785,649,649,3,2],
["p1",4,"op","chess_char_4_19_b",1,"none",2525.9,1,10,1,8997,1531,0,0,4],
["p1",5,"op","chess_char_4_22_b",1,"uniequip_002_svrash",3339.7,1,11,3,40105,9401,4764,46,1],
["p1",6,"op","chess_char_5_01_a",2,null,1722.46,1,40,4,78323,9642,6250,66,1],
["p1",7,"op","chess_char_4_16_b",1,"none",507.1,1,71,7,97453,7002,1741,95,6],
["p1",8,"op","chess_char_4_13_b",2,"uniequip_004_gnosis",2553.2,1,8,4,31086,0,0,39,3],
["p1",9,"op","chess_char_4_20_b",1,"none",1844.7,1,9,21,131494,1023,0,64,3],
["p1",10,"op","chess_char_4_24_b",2,"none",2571.4,1,12,10,154430,6521,646,37,3],
["p1",11,"op","chess_char_4_25_b",1,"uniequip_002_cetsyr",2172.3,1,4,0,19289,0,0,0,3],
["p1",12,"op","chess_char_5_02_a",1,null,1570.4,1,6,7,127404,903,13969,30,3],
["p1",1,"op","chess_char_4_17_b",2,"none",4566.9,1,3,0,0,0,0,0,0],
["p1",2,"op","chess_char_4_18_b",2,"none",6783,1,5,1,3204,0,0,2,0],
["p1",3,"op","chess_char_4_23_b",1,"uniequip_004_gvial2",3667.3,1,7,1,7785,649,453,3,2],
["p1",4,"op","chess_char_4_19_b",1,"none",2525.9,1,10,0,22404,1531,0,2,5],
["p1",5,"op","chess_char_4_22_b",1,"uniequip_002_svrash",3339.7,1,11,4,45135,11366,7678,52,1],
["p1",6,"op","chess_char_5_01_a",2,null,0,0,74,0,33180,11271,3600,57,0],
["p1",7,"op","chess_char_4_16_b",1,"none",0,0,70,7,103396,7566,1798,97,6],
["p1",8,"op","chess_char_4_13_b",2,"uniequip_004_gnosis",2553.2,1,8,4,29700,0,0,39,3],
["p1",9,"op","chess_char_4_20_b",1,"none",1844.7,1,9,23,148474,1023,0,68,3],
["p1",10,"op","chess_char_4_24_b",2,"none",2571.4,1,12,11,171104,6606,574,44,4],
["p1",11,"op","chess_char_4_25_b",1,"uniequip_002_cetsyr",2172.3,1,4,1,10365,0,0,0,3],
["p1",12,"op","chess_char_5_02_a",1,null,1570.4,1,6,7,131396,633,13103,31,5],
["-","~1","device","trap_1105_accrate",null,null,100,1,1,0,0,0,0,0,null],
["-","~2","device","trap_1105_accrate",null,null,100,1,2,0,0,0,0,0,null]
],
@@ -2592,17 +2592,17 @@
"enemy_1112_emppnt_2": [1,1,0,0,18432],
"enemy_1183_mlasrt": [1,1,0,573,7488],
"enemy_1249_lysdb_2": [1,1,0,0,6912],
"enemy_1267_nhpbr_2": [33,33,0,9577,209088],
"enemy_1270_nhstlk_2": [12,12,0,6539,221184],
"enemy_1272_nhtank_2": [6,6,0,7102,103680],
"enemy_1267_nhpbr_2": [33,33,0,8565,209088],
"enemy_1270_nhstlk_2": [12,12,0,6590,221184],
"enemy_1272_nhtank_2": [6,6,0,12872,103680],
"enemy_1329_cbshld_2": [1,1,0,1824,14976],
"enemy_1512_mcmstr": [1,1,0,5044,92160],
"enemy_1512_mcmstr": [1,1,0,4209,92160],
"enemy_9008_acbunn": [1,1,0,1373,13824]
},
"hooks": [1,76,4847,498,498,1282,1296,2030,65,62,30,27,16,17319,1994,40,59,0,1,70,51,1,7],
"events": {"atk":626,"bounty":4,"deploy":15,"die":62,"dmg":1130,"engage":10,"fx":198,"heal":161,"layer":51,"skill":57,"spawn":73,"status":274},
"fx": {"aoe":4,"bombard":5,"bombardShell":5,"burst":1,"coldWind":3,"devour":3,"dodge":7,"explode":26,"extraAttack":15,"garrison":27,"garrisonGrant":1,"iceSpike":3,"link":3,"mote":34,"overload":2,"revive":1,"reweave":3,"rockfall":1,"shieldBreak":2,"sleepGuard":3,"snow":1,"stone":1,"swordStorm":6,"telegraph":2,"zone":39},
"snaps": "875d082b 2d4fe188 7fcebf0f 0527d505 bb63a101 48180fae 265505ed 9e4dc1bc 9ba5f9b2 78ac7755 8a05d44c 142de75f 53a7aa5d 12ee3255 c9643b48 a3e02d33 beb312d1"
"hooks": [1,77,5341,508,508,1296,1311,2474,68,65,32,30,0,18486,2146,40,59,0,1,75,51,1,6],
"events": {"atk":620,"bounty":4,"deploy":16,"die":65,"dmg":1143,"engage":10,"fx":192,"heal":162,"layer":51,"skill":62,"spawn":73,"status":288},
"fx": {"aoe":5,"bombard":5,"bombardShell":5,"burst":1,"coldWind":3,"devour":4,"dodge":6,"explode":26,"extraAttack":9,"garrison":27,"garrisonGrant":1,"iceSpike":3,"link":3,"mote":33,"overload":2,"revive":1,"reweave":3,"shieldBreak":1,"sleepGuard":5,"snow":1,"swordStorm":6,"telegraph":2,"zone":40},
"snaps": "875d082b 2d4fe188 7fcebf0f bdea2189 9cf65199 18d2f7a8 90cd310a 78706492 7661fcef ac8a9f73 15508efb 81a2f945 80f95bc4 a3d670f4 2e7c868e 3ff4d1ff 771c9042 584ea9ff"
},
"roster-043": {
"about": "pass 2 band 5: chess_char_5_08_a chess_char_5_11_a chess_char_5_05_a chess_char_5_06_a chess_char_5_13_a chess_char_5_14_a chess_char_5_07_a chess_char_5_17_a chess_char_5_03_a chess_char_5_10_a chess_char_5_12_a chess_char_5_15_a",
+2 -2
View File
@@ -88,8 +88,8 @@ test('终极 Final Assault (+200 layers per active bond): one bloodPoint pool fo
for (const k of MUL_STATS) assert.ok(!(k in b.mods), `${u.name}: ${b.key} is a 直接乘算 bonus, not ${k} (${JSON.stringify(b.mods)})`);
}
const { add, mul } = aggregateMods(u.buffs);
const want = Math.max(0, (u.base.atk + (add.atkFlat ?? 0)) * Math.max(0, 1 + (add.atkPct ?? 0)) * (mul.atkMul ?? 1));
assert.ok(Math.abs(u.s.atk - want) <= 1e-6 * Math.max(1, want), `${u.name}: ATK = (base + flat) × (1 + Σ%) × Π(提升至/runes)`);
const want = Math.max(0, ((u.base.atk + (add.atkFlat ?? 0)) * Math.max(0, 1 + (add.atkPct ?? 0)) + (add.atkFinal ?? 0)) * (mul.atkMul ?? 1));
assert.ok(Math.abs(u.s.atk - want) <= 1e-6 * Math.max(1, want), `${u.name}: ATK = ((base + flat) × (1 + Σ%) + 最终加算) × Π(提升至/runes)`);
}
}
assert.ok(ops >= 12 && withBonds >= 8, `the bots' lineups carry bond / item bonuses (${withBonds} of ${ops})`);
+1 -1
View File
@@ -122,7 +122,7 @@ test('乌尔比安 S3: the 阿戈尔 devour gains stay through the 【移动】
const gain = () => u.buffs.find((x) => x.key === 'bond:egir:devour');
assert.ok(gain(), 'he devoured the piece in front of him at the battle start');
const mods = { ...gain().mods }, atk0 = u.s.atk, block0 = u.s.blockCnt;
assert.equal(mods.atkFlat, 1000);
assert.equal(mods.atkFinal, 1000);
u.skill.gainSp(1000);
assert.ok(h.runUntil(() => u.skill.active, 2));
assert.deepEqual([u.tileR, u.tileC], [10, 7], 'moved');