feedback4: 阿戈尔's devoured base ATK is a 最终加算, and a marker knocked out during the devour still resolves its own marks (GitHub #165 points 2 and 3, PR #176 by @SpiritedAwayCN; the owner's decision of 2026-10-06)
- PRTS 卫戍协议:盟约 下半/PRTS盟约记录, 阿戈尔 ※: 「该付与来源获得所有标记单位的基础攻击力(最终加算)和阻挡数」. New additive mod key atkFinal (PRTS 游戏数据基础 A_f = F_t[(A + D_p)(1 + D_t) + F_p]): ATK = ((base + ΣatkFlat) × (1 + ΣatkPct) + ΣatkFinal) × ΠatkMul. The devour buff carries atkFinal instead of atkFlat: 1000 base ATK, +100 % skill, +2000 devoured → 4000 (was 6000). Every other mod key keeps its meaning. - 「标记按付与顺序触发【吞噬】效果,目标首次被击倒后解除自身被付与但还未触发的【吞噬】效果」 cancels only the knocked-out target's marks: a marker knocked out earlier in the pass now resolves its own marks, the kill credited to it (「击杀来源始终为对应标记的付与来源」). A → B → C with B devoured first: C takes B's 5000 and the kill is B's. The 3 revive slots, the 联防 front-tile devour and the down-at-start rules (DESIGN §24.3 / §24.4) are unchanged. - Point 5 (the 流失's own source is the target itself) stays open: the hooks still see the marker (DESIGN §24.7). - Tests: bonds_core — new 最终加算 test (4000; a 直接加算 still scaled; ×0.5 scales the whole), new A → B → C test, the dead-marker test rewritten (its mark now lands); feedback3-egir-down, feedback4-egir-unite, feedback3-ulpia-move read atkFinal; match/bosshp recomputes ATK with the 最终加算. - Docs: DESIGN §24.7 (and the §24 intro, §5.2 / §5.3, the §24.4 atkFlat lines marked), SIM.md §3, research 02 §3.6 and its JSON spec; data/bonds.json regenerated with build-data --offline — only egirShip.spec.algorithm[2] / [3] changed. - Golden: bond-egirShip-high (the devourers 深巡 / 幽灵鲨 / 斯卡蒂 no longer scale the devoured ATK by their ATK +%; the fight ends at 89.03 s instead of 74.03 s), coop2-ABYSS-10-boosted (from round 8 ai_0 has 3 more 阿戈尔 and 奥术 layers — 海霓's first-kill trait — and both bots' boss damage moves). The marker rule moves no scenario.
This commit is contained in:
1 parent
4f870013c7
commit
5bc2669407
15 files changed
+162
-58
No files matched your search
@@ -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');
|
||||
|
||||
@@ -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)`);
|
||||
|
||||
@@ -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 联防');
|
||||
|
||||
+12
-12
@@ -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",
|
||||
|
||||
@@ -1424,32 +1424,32 @@
|
||||
},
|
||||
{
|
||||
"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,"fa4268ad",2207,"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 1/316, steadShip 1/343, suntShip 1/302, swiftShip 0/300, victoriaShip 1/316, visiShip 0/300, yanShip 0/310",12,12,0,99]
|
||||
},
|
||||
{
|
||||
"round": 11,
|
||||
"ai_0": [1,400,12,0,2,5,8,"e2bf7b5d",2634,"arcaneShip 1/323, deputShip 0/304, egirShip 1/345, 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/329, raidShip 1/360, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 1/315, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",34,34,0,105],
|
||||
"ai_0": [1,400,12,0,2,5,8,"e2bf7b5d",2634,"arcaneShip 1/326, deputShip 0/304, egirShip 1/346, 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/329, raidShip 1/358, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/334, suntShip 0/300, swiftShip 1/315, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",34,34,0,105],
|
||||
"ai_1": [1,400,12,0,1,5,8,"5dc25201",2235,"arcaneShip 0/302, deputShip 1/320, egirShip 0/300, emptyShip 0/300, indomShip 1/310, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/313, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/304, soloShip 1/318, steadShip 1/350, suntShip 1/304, swiftShip 0/300, victoriaShip 1/320, visiShip 0/300, yanShip 0/310",34,34,0,111]
|
||||
},
|
||||
{
|
||||
"round": 12,
|
||||
"ai_0": [1,400,14,0,0,6,8,"e09e9634",2679,"arcaneShip 1/326, deputShip 0/304, egirShip 1/351, 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/342, raidShip 1/370, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 0/300, swiftShip 1/320, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",6,14,8,119],
|
||||
"ai_0": [1,400,14,0,0,6,8,"e09e9634",2679,"arcaneShip 1/329, deputShip 0/304, egirShip 1/352, 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/342, raidShip 1/368, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/334, suntShip 0/300, swiftShip 1/320, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",6,14,8,119],
|
||||
"ai_1": [1,400,13,0,2,6,8,"13f2f54b",2259,"arcaneShip 0/302, deputShip 1/322, 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 1/317, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/304, soloShip 1/320, steadShip 1/358, suntShip 1/306, swiftShip 0/300, victoriaShip 1/324, visiShip 0/300, yanShip 0/310",15,15,0,124]
|
||||
},
|
||||
{
|
||||
"round": 13,
|
||||
"ai_0": [1,400,12,0,0,6,8,"871ba326",3034,"arcaneShip 1/333, deputShip 0/304, egirShip 1/369, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/333, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/354, raidShip 1/376, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/340, suntShip 1/300, swiftShip 1/325, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",41,41,0,130],
|
||||
"ai_0": [1,400,12,0,0,6,8,"871ba326",3028,"arcaneShip 1/336, deputShip 0/304, egirShip 1/368, emptyShip 0/300, indomShip 0/300, investShip 0/300, kazimierzShip 1/333, kjeragShip 0/302, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/354, raidShip 1/372, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/300, soloShip 1/304, steadShip 1/336, suntShip 1/300, swiftShip 1/325, victoriaShip 0/300, visiShip 0/300, yanShip 0/300",41,41,0,130],
|
||||
"ai_1": [1,400,14,0,2,6,8,"0e053b02",2595,"arcaneShip 0/302, deputShip 1/324, egirShip 0/300, emptyShip 0/300, indomShip 1/318, investShip 0/300, kazimierzShip 0/300, kjeragShip 0/300, lateranoShip 0/300, maniShip 0/300, miraShip 0/300, preciShip 1/319, raidShip 0/300, sargonShip 0/300, siracusaShip 0/300, skillfulShip 0/304, soloShip 1/322, steadShip 1/366, suntShip 2/308, swiftShip 0/300, victoriaShip 1/332, visiShip 1/306, yanShip 0/310",41,41,0,170]
|
||||
}
|
||||
],
|
||||
@@ -1464,9 +1464,9 @@
|
||||
"title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"},
|
||||
"trophies": 8,
|
||||
"reward": 425,
|
||||
"stats": {"activatedLayers":3054,"bossDamage":2348544,"dmgDealt":11081151,"gold":156,"itemsEquipped":15,"kills":288,"leaks":8,"lpLost":0,"merges":6,"perfectRounds":12,"refreshes":28},
|
||||
"stats": {"activatedLayers":3048,"bossDamage":2124287,"dmgDealt":10786825,"gold":156,"itemsEquipped":15,"kills":288,"leaks":8,"lpLost":0,"merges":6,"perfectRounds":12,"refreshes":28},
|
||||
"lineup": ["4_09_b@11,5","4_14_a@11,8","5_07_a@10,4[1_01_e_a]","2_18_a@10,5","1_19_b@10,8[4_04_e_b+1_02_e_b]","3_09_a@9,7[2_01_e_a+3_08_e_a]","4_20_a@9,8","3_05_a@9,9[4_07_e_a+5_02_e_a]"],
|
||||
"bonds": ["arcaneShip 1/333","deputShip 0/304","egirShip 1/369","emptyShip 0/300","indomShip 0/300","investShip 0/300","kazimierzShip 1/333","kjeragShip 0/302","lateranoShip 0/300","maniShip 0/300","miraShip 0/300","preciShip 1/364","raidShip 1/376","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/300","soloShip 1/304","steadShip 1/340","suntShip 1/300","swiftShip 1/335","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
|
||||
"bonds": ["arcaneShip 1/336","deputShip 0/304","egirShip 1/368","emptyShip 0/300","indomShip 0/300","investShip 0/300","kazimierzShip 1/333","kjeragShip 0/302","lateranoShip 0/300","maniShip 0/300","miraShip 0/300","preciShip 1/364","raidShip 1/372","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/300","soloShip 1/304","steadShip 1/336","suntShip 1/300","swiftShip 1/335","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
|
||||
},
|
||||
"ai_1": {
|
||||
"alive": true,
|
||||
@@ -1478,7 +1478,7 @@
|
||||
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
|
||||
"trophies": 8,
|
||||
"reward": 425,
|
||||
"stats": {"activatedLayers":2623,"bossDamage":4589976,"dmgDealt":19161995,"gold":197,"itemsEquipped":35,"kills":283,"leaks":1,"lpLost":0,"merges":6,"perfectRounds":12,"refreshes":35},
|
||||
"stats": {"activatedLayers":2623,"bossDamage":4814553,"dmgDealt":19429576,"gold":197,"itemsEquipped":35,"kills":283,"leaks":1,"lpLost":0,"merges":6,"perfectRounds":12,"refreshes":35},
|
||||
"lineup": ["1_13_b@11,5[4_06_e_b+4_09_e_a]","6_11_a@11,8[3_08_e_a+5_01_e_a]","6_08_a@10,3[1_05_e_b+2_01_e_b]","3_16_b@10,4[3_10_e_b+2_03_e_b]","4_01_a@10,7[3_01_e_a+6_09_e_a]","4_07_b@10,8[3_10_e_a+5_09_e_a]","6_01_a@9,8[3_05_e_b+3_02_e_b]","1_06_b@9,9[3_11_e_a+2_03_e_b]"],
|
||||
"bonds": ["arcaneShip 0/302","deputShip 1/328","egirShip 0/300","emptyShip 0/300","indomShip 1/322","investShip 0/300","kazimierzShip 0/300","kjeragShip 0/300","lateranoShip 1/304","maniShip 1/304","miraShip 0/300","preciShip 1/323","raidShip 0/300","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/304","soloShip 0/322","steadShip 1/390","suntShip 1/312","swiftShip 0/300","victoriaShip 1/340","visiShip 0/306","yanShip 0/310"]
|
||||
}
|
||||
|
||||
@@ -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})`);
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in new issue
Block a user