feedback7 R22-FIELDS: the Hidden Core 铳's 碎铳之簧 chase the casting gun for the whole 5 s of 末日布道 instead of stopping on arrival; each gun keeps its data timer, the later call takes the springs (PR #347 by @CXUtk, its pair stagger and lock not taken); golden: hidden-boss_9-pair, hidden-boss_9-solo, coop2-ABYSS-10-boosted
PR #347 by @CXUtk, applied with changes. Kept: 追逐模式 lasts the gain's whole 5 s — PRTS 假想敌:铳 末日布道 "令全场的 “碎铳之簧”获得5秒增益…增益期间切换为追逐模式", “碎铳之簧” 追逐模式 "持续追踪令其进入该形态的场上的假想敌:铳移动" (no arrival clause, unlike the 铳's own 冲锋模式, which ends "到达目标所在位置后"); data skill 2: cooldown 45, initCooldown 20, dog_duration 5, move_speed 8. kitSpring no longer ends the chase when it reaches the gun or comes within 1 tile; with no gun left on the field the spring holds still until the gain ends (until 0.2.1 that ended the chase at once). Not taken (the maintainer's decision on the Grok triage): the second gun's half-cooldown first-call delay and the cond that refused a call while any spring was chasing — neither is in the data, and the lock contradicts the handbook's 「持续召唤场上所有“碎铳之簧”向自身移动」 (a call takes every spring to its caster). Both guns keep their data timers, so on a pair field the mirrored gun's call, a tick after the first, retargets the springs for a new 5 s. Measured (notes repro-347.mjs): a spring 0.2 tile from the gun chased 0.03 s, one 5 tiles away 2.97 s; now 5.03 s both. Tests: test/content/hidden-gun-pursuit.test.js (new, 5; the arena harness and two tests are the PR's): the full 5 s next to a moving gun and with no gun left fail on the parent; the pair timing (20 s after each gun's spawn, then every 45 s, the two calls a tick apart), a mid-chase call retargeting the springs for a new 5 s and the solo timing guard against the stagger / lock. test/sim/feedback1e-healers.test.js E2 audit: the fields whose leaders / parts a healer must block run 200 s instead of 120 — on the solo 铳 field the springs now first meet a healer at 145 s (at 21 s until now). Golden (on top of the portal commit): - fields hidden-boss_9-pair: the springs spend 5 s invulnerable per call, so they take less (actrpa 855522 → 722451, actrpb 798033 → 660498, actrpc 1384683 → 1168947) and pass less on; leader left 3511007 → 3747749; p2's deaths 7 → 12 (longer tramples); still 8 / 8 kills, no leak. - fields hidden-boss_9-solo: leader left 1932856 → 2011732; the springs take less; 隐德来希's candles (5601_entlec, an enemy-side summon) 6 → 8. - matches coop2-ABYSS-10-boosted (hidden boss_9): still cleared at 800 LP; the seats' leader damage shifts (7523075 / 6369365 → 6992346 / 6900614).
This commit is contained in:
1 parent
a87cc1e9fd
commit
f2aec39e93
6 files changed
+265
-98
No files matched your search
+5
-1
@@ -205,7 +205,11 @@ Leader parts (`tag:'part'`) pass damage to their leader with `loseHp(leader, sha
|
||||
(无来源, credited to the attacker's `bossDamage`): `PART_TRANSFER` 1 for 斩胄之剑 / 破胄之锤 (`BLADE_TRANSFER`, the same
|
||||
constant) and 碎铳之簧 (PRTS "受到伤害时令假想敌:胄/铳受到等量的无来源生命流失"; DESIGN §20.10, §20.13). Content may replace a part mid-battle: every 剑/锤 sortie (content/bosses.js `kitBlade`)
|
||||
ends by spawning a new 初始模式 copy on its level branch route (`left_hand_origin` / `right_hand_origin`) with the old
|
||||
HP, then `kill(old, null)` — uncounted, no bounty; the client sees a `die` and a `spawn`.
|
||||
HP, then `kill(old, null)` — uncounted, no bounty; the client sees a `die` and a `spawn`. The Hidden Core 铳's 【末日布道】
|
||||
puts every 碎铳之簧 into 追逐模式 for its whole 5 s gain (`dog_duration`; invulnerable, no ordinary attacks): the spring
|
||||
keeps following the casting gun after reaching it (PR #347; until 0.2.1 arrival or 1 tile ended the chase), and each
|
||||
gun casts on its own data timer (20 s after it spawns, then every 45 s), so on a pair field the later call retargets
|
||||
every spring to that gun for a new 5 s (PRTS: 「持续召唤场上所有“碎铳之簧”向自身移动」).
|
||||
|
||||
WALK legs pathfind on the stage grid inside the rect with the official flow field (grid.js: 4-direction SPFA from the
|
||||
destination, crates cost 1000, then Bresenham line-of-sight smoothing — research 08 §3.4). The official route stays
|
||||
|
||||
@@ -639,8 +639,11 @@ function kitGun(ab, e, b) {
|
||||
});
|
||||
if (s2) list.push({
|
||||
cd: s2.cd, icd: s2.icd, cond: (b2) => b2.enemies.some((o) => o.alive && isSpring(o)),
|
||||
fire(b2, e2) { // 【末日布道】 springs dash to 铳, invulnerable, trampling operators
|
||||
// PRTS “碎铳之簧” 追逐模式 "不进行普通攻击": `disarm` for the dash (until 0.1.3 it kept shooting while it ran)
|
||||
fire(b2, e2) { // 【末日布道】 springs chase 铳 for the whole 5 s gain, invulnerable, trampling operators (kitSpring)
|
||||
// PRTS “碎铳之簧” 追逐模式 "不进行普通攻击": `disarm` for the dash (until 0.1.3 it kept shooting while it ran).
|
||||
// Each gun casts on its own data timer, and a cast takes every spring — on a pair field the later of the two
|
||||
// calls retargets them all to its gun (handbook 「持续召唤场上所有“碎铳之簧”向自身移动」; no stagger, no lock while
|
||||
// a chase runs: PR #347's pair coordination is not taken, the data has neither)
|
||||
for (const sp of b2.enemies) {
|
||||
if (!sp.alive || !isSpring(sp) || !sp.mem.ab) continue;
|
||||
sp.mem.ab.dash = { until: b2.time + (s2.bb.dog_duration ?? 0), mul: 1 + (s2.bb.move_speed ?? 0), gun: e2, hit: new Set() };
|
||||
@@ -708,11 +711,16 @@ function kitSpring(ab, e) {
|
||||
if (!P.up && P.downAt != null && b.time - P.downAt >= regen) raise(b);
|
||||
const d = e2.mem.ab.dash;
|
||||
if (!d) return;
|
||||
// 追逐模式 lasts the whole gain (PRTS 末日布道 "令全场的“碎铳之簧”获得5秒增益…增益期间切换为追逐模式"; “碎铳之簧”
|
||||
// 追逐模式 "持续追踪令其进入该形态的场上的假想敌:铳移动" — no arrival clause, unlike the 铳's own 冲锋模式): reaching
|
||||
// the gun does not end it, the spring keeps following the gun until the 5 s are over (PR #347 by @CXUtk; until
|
||||
// 0.2.1 it ended on arrival or within 1 tile). The casting gun dead: the nearest other gun; none left on the
|
||||
// field: it holds still, the gain running on.
|
||||
const g = d.gun && d.gun.alive ? d.gun : gun(b);
|
||||
const arrived = !g || stepToward(e2, g.x, g.y, e2.s.moveSpeed * d.mul * MOVE_SCALE * dt) || hypot(g.x - e2.x, g.y - e2.y) < 1;
|
||||
if (g) stepToward(e2, g.x, g.y, e2.s.moveSpeed * d.mul * MOVE_SCALE * dt);
|
||||
// 追逐模式 "对进入自身0.35半径范围内的我方单位(包括飞行单位)造成一次攻击力100%的物理普通伤害" (until 0.1.3: radius 0.5)
|
||||
for (const u of areaAllies(b, e2, e2.x, e2.y, CHARGE_RADIUS)) if (!d.hit.has(u)) { d.hit.add(u); hurt(b, e2, u, e2.s.atk, 'phys'); }
|
||||
if (arrived || b.time >= d.until) { e2.mem.ab.dash = null; b.removeBuff(e2, 'boss:dash'); if (e2.route) e2.route.pts = null; }
|
||||
if (b.time >= d.until) { e2.mem.ab.dash = null; b.removeBuff(e2, 'boss:dash'); if (e2.route) e2.route.pts = null; }
|
||||
},
|
||||
},
|
||||
// while shielded, every (spCost+1)-th attack (enemy SP +1 per attack, as 粉碎攻坚手's official text) adds the shield's
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
// 隐秘核心铳's 【末日布道】 (PR #347 by @CXUtk): every 碎铳之簧 chases the casting gun for the gain's whole 5 s — PRTS 末日布道
|
||||
// "令全场的“碎铳之簧”获得5秒增益:移动速度+800%,无敌,增益期间切换为追逐模式", “碎铳之簧” 追逐模式 "持续追踪令其进入该形态的场上的
|
||||
// 假想敌:铳移动" (no arrival clause). Until 0.2.1 reaching the gun (or 1 tile from it) ended the chase. Each gun casts on its
|
||||
// own data timer (initCooldown 20, cooldown 45 — no stagger between the two guns of a pair field, no lock while a chase
|
||||
// runs: the data has neither, and the handbook's 「向自身」 means the later call takes the springs).
|
||||
import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs';
|
||||
import { makeBattle, chessRec, checkInvariants } from '../helpers/battleHarness.js';
|
||||
import * as enemies from '../../server/sim/content/enemies.js';
|
||||
import * as bosses from '../../server/sim/content/bosses.js';
|
||||
|
||||
const W = JSON.parse(fs.readFileSync(new URL('../../data/waves.json', import.meta.url), 'utf8'));
|
||||
const E = JSON.parse(fs.readFileSync(new URL('../../data/enemies.json', import.meta.url), 'utf8'));
|
||||
const GUN = 'enemy_9017_achunt_2';
|
||||
const SPRING = 'enemy_9020_actrpc';
|
||||
const wall = chessRec({ id: 'pursuit_wall', profession: 'TANK', stats: { maxHp: 1e9, atk: 0, def: 1000, blockCnt: 3 }, rangeGrid: [[0, 0]], skill: null });
|
||||
|
||||
/** The real h08_02(_s) template (leader + parts only, or no spawns with `manual`), one non-attacking wall per side. */
|
||||
function arena({ solo = false, manual = false, cooldown = null } = {}) {
|
||||
const tpl = structuredClone(W[solo ? 'act1autochess_h08_02_s' : 'act1autochess_h08_02']);
|
||||
tpl.spawns = manual ? [] : tpl.spawns.filter((s) => s.tag === 'boss' || s.tag === 'part');
|
||||
if (cooldown != null) {
|
||||
tpl.overrides[GUN] ??= { skills: structuredClone(E[GUN].skills) };
|
||||
const skill = tpl.overrides[GUN].skills.find((s) => s.prefabKey === '2');
|
||||
skill.initCooldown = 0;
|
||||
skill.cooldown = cooldown;
|
||||
}
|
||||
return makeBattle({
|
||||
kind: 'hidden', waveTemplate: tpl, content: 'generic', extraContent: [enemies, bosses], seed: 7,
|
||||
autoFinish: false, timeLimit: 300, recordEvents: false, hooks: [],
|
||||
defs: { chess: { pursuit_wall: wall } }, kits: { pursuit_wall: () => ({ trait: { noAttack: true } }) },
|
||||
sharedBoss: { hp: 1e12, maxHp: 1e12, damage(pid, n) { this.hp -= n; } },
|
||||
players: [
|
||||
{ playerId: 'p1', seat: 0, side: 'L', colOffset: 0, units: [{ uid: 1, chessId: 'pursuit_wall', row: 3, col: 5, abs: true }] },
|
||||
...solo ? [] : [{ playerId: 'p2', seat: 1, side: 'R', colOffset: 8, units: [{ uid: 2, chessId: 'pursuit_wall', row: 3, col: 15, abs: true }] }],
|
||||
],
|
||||
setup(b) { b.enemyOverrides = tpl.overrides; b.opts.waveTemplate = tpl; b.opts.bossMirror = !manual; },
|
||||
});
|
||||
}
|
||||
|
||||
/** Every 【末日布道】 call (a new chase object on the spring): { time, gun }. */
|
||||
function recordCalls(h) {
|
||||
const calls = [];
|
||||
let last = null;
|
||||
h.b.on('tick', () => {
|
||||
const d = h.enemies().find((e) => e.defId === SPRING)?.mem.ab.dash;
|
||||
if (!d || d === last) return;
|
||||
last = d;
|
||||
calls.push({ time: h.b.time, gun: d.gun });
|
||||
});
|
||||
return calls;
|
||||
}
|
||||
|
||||
test('隐秘核心铳 pair: each gun calls on its own data timer (20 s after it spawns, then every 45 s); the later call takes the springs', () => {
|
||||
const h = arena();
|
||||
const spawned = new Map();
|
||||
h.b.on('enemySpawn', (c) => { if (c.enemy.defId === GUN) spawned.set(c.enemy, h.b.time); });
|
||||
const calls = recordCalls(h);
|
||||
h.run(150);
|
||||
assert.equal(spawned.size, 2, 'the pair field has two guns (the mirrored one)');
|
||||
const skill = W.act1autochess_h08_02.overrides[GUN].skills.find((s) => s.prefabKey === '2');
|
||||
for (const [gun, t0] of spawned) {
|
||||
const own = calls.filter((c) => c.gun === gun).map((c) => c.time);
|
||||
assert.equal(own.length, 3, 'three calls each in 150 s');
|
||||
assert.ok(Math.abs(own[0] - t0 - skill.initCooldown) < h.TICK * 2, `first call ${skill.initCooldown} s after its spawn`);
|
||||
for (let i = 1; i < own.length; i++) assert.ok(Math.abs(own[i] - own[i - 1] - skill.cooldown) < h.TICK * 2, `then every ${skill.cooldown} s`);
|
||||
}
|
||||
// the two mirrored guns call within a tick or two of each other (no half-cooldown stagger), the later one wins
|
||||
for (let i = 1; i < calls.length; i += 2) assert.ok(calls[i].time - calls[i - 1].time < h.TICK * 3, 'the two calls come together');
|
||||
assert.equal(h.b.errorCount, 0);
|
||||
checkInvariants(h.b);
|
||||
});
|
||||
|
||||
test('隐秘核心铳: reaching a moving gun keeps pursuit, invulnerability and disarm for the full 5 s', () => {
|
||||
const h = arena({ solo: true, manual: true, cooldown: 45 });
|
||||
h.step();
|
||||
const gun = h.spawn(GUN, { pos: [3, 5], tag: 'boss', mods: { speedMul: 0 } });
|
||||
const spring = h.spawn(SPRING, { pos: [3, 4.8], tag: 'part' });
|
||||
h.step(2);
|
||||
const d = spring.mem.ab.dash;
|
||||
assert.ok(d, 'arriving next to the gun does not end the chase');
|
||||
h.run(1);
|
||||
gun.x = 6;
|
||||
const oldX = spring.x;
|
||||
h.run(1);
|
||||
assert.ok(spring.x > oldX, 'it keeps following the gun when the gun moves');
|
||||
assert.equal(spring.mem.ab.dash, d);
|
||||
assert.ok(spring.s.flags.invulnerable && spring.s.flags.disarm);
|
||||
h.run(d.until - h.b.time - h.TICK * 2);
|
||||
assert.equal(spring.mem.ab.dash, d, 'still chasing just before the 5 s are over');
|
||||
assert.ok(spring.s.flags.invulnerable && spring.s.flags.disarm);
|
||||
h.run(h.TICK * 4);
|
||||
assert.equal(spring.mem.ab.dash, null, 'over once the gain ends');
|
||||
assert.ok(!spring.s.flags.invulnerable && !spring.s.flags.disarm);
|
||||
assert.equal(h.b.errorCount, 0);
|
||||
});
|
||||
|
||||
test('隐秘核心铳: the other gun\'s call during a chase retargets every spring to that gun for a new 5 s', () => {
|
||||
const h = arena({ manual: true, cooldown: 45 });
|
||||
h.step();
|
||||
const left = h.spawn(GUN, { pos: [3, 5], tag: 'boss', mods: { speedMul: 0 } });
|
||||
const right = h.spawn(GUN, { pos: [3, 15], tag: 'boss', mods: { speedMul: 0 } });
|
||||
const call = right.mem.ab.list.find((a) => a.cd === 45 && a.fire);
|
||||
call.left = 999; // the right gun's call is not ready yet
|
||||
const spring = h.spawn(SPRING, { pos: [3, 10], tag: 'part' });
|
||||
h.step(2);
|
||||
const first = spring.mem.ab.dash;
|
||||
assert.ok(first && first.gun === left, 'the first call takes the spring to the left gun');
|
||||
h.run(1);
|
||||
assert.equal(spring.mem.ab.dash, first, 'chasing the left gun');
|
||||
call.left = 0; // the right gun's call comes ready mid-chase
|
||||
h.step(2);
|
||||
const second = spring.mem.ab.dash;
|
||||
assert.ok(second && second !== first && second.gun === right, 'the later call takes the spring at once');
|
||||
assert.ok(Math.abs(second.until - h.b.time - 5) < h.TICK * 3, 'for a new 5 s');
|
||||
const oldX = spring.x;
|
||||
h.run(1);
|
||||
assert.ok(spring.x > oldX, 'it now runs to the right gun');
|
||||
assert.ok(spring.s.flags.invulnerable && spring.s.flags.disarm);
|
||||
assert.equal(h.b.errorCount, 0);
|
||||
});
|
||||
|
||||
test('隐秘核心铳: with no gun left on the field the spring holds still, invulnerable and disarmed, until the gain ends', () => {
|
||||
const h = arena({ solo: true, manual: true, cooldown: 45 });
|
||||
h.step();
|
||||
const gun = h.spawn(GUN, { pos: [3, 5], tag: 'boss', mods: { speedMul: 0 } });
|
||||
const spring = h.spawn(SPRING, { pos: [3, 1], tag: 'part' });
|
||||
h.step(2);
|
||||
const d = spring.mem.ab.dash;
|
||||
assert.ok(d, 'chasing');
|
||||
h.b.kill(gun, null);
|
||||
h.step();
|
||||
const at = [spring.x, spring.y];
|
||||
h.run(1);
|
||||
assert.deepEqual([spring.x, spring.y], at, 'no gun to follow: it stands');
|
||||
assert.equal(spring.mem.ab.dash, d, 'the chase is not over');
|
||||
assert.ok(spring.s.flags.invulnerable && spring.s.flags.disarm);
|
||||
h.run(d.until - h.b.time + h.TICK * 2);
|
||||
assert.equal(spring.mem.ab.dash, null);
|
||||
assert.ok(!spring.s.flags.invulnerable);
|
||||
assert.equal(h.b.errorCount, 0);
|
||||
});
|
||||
|
||||
test('隐秘核心铳: solo keeps the template initial cooldown and repeated call timing', () => {
|
||||
const h = arena({ solo: true });
|
||||
const calls = recordCalls(h);
|
||||
h.run(100);
|
||||
assert.equal(calls.length, 2);
|
||||
const tpl = W.act1autochess_h08_02_s;
|
||||
const spawnTime = tpl.spawns.find((s) => s.tag === 'boss').time;
|
||||
const skill = (tpl.overrides[GUN]?.skills ?? E[GUN].skills).find((s) => s.prefabKey === '2');
|
||||
assert.ok(Math.abs(calls[0].time - spawnTime - skill.initCooldown) < h.TICK * 2);
|
||||
assert.ok(Math.abs(calls[1].time - calls[0].time - skill.cooldown) < h.TICK * 2);
|
||||
assert.equal(h.b.errorCount, 0);
|
||||
});
|
||||
+87
-90
@@ -1111,107 +1111,106 @@
|
||||
"killed": 8,
|
||||
"total": 8,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 3511007,
|
||||
"rngDraws": 1705,
|
||||
"bossHpLeft": 3747749,
|
||||
"rngDraws": 1619,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {
|
||||
"p1": {"killed":8,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1689940,"bossDmg":698535,"heal":15297,"deaths":5,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":3810677,"bossDmg":1348791,"heal":109383,"deaths":7,"layerGains":{}}
|
||||
"p1": {"killed":8,"total":8,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":1664353,"bossDmg":722232,"heal":20932,"deaths":5,"layerGains":{}},
|
||||
"p2": {"killed":0,"total":0,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":3117516,"bossDmg":1090251,"heal":121649,"deaths":12,"layerGains":{}}
|
||||
},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",6348.28,1,67,0,9,7512,6537,1,3],
|
||||
["p1",2,"op","chess_char_6_06_b",2,"uniequip_002_pepe",2695.89,1,11,0,8762,1179,0,9,1],
|
||||
["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",1406.57,1,17,0,35012,3869,0,15,2],
|
||||
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",1165.15,1,7,2,1312507,1285,0,58,8],
|
||||
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",0,0,9,0,19135,12418,0,23,1],
|
||||
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",1104.58,1,55,0,35830,11463,444,0,4],
|
||||
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",2451.4,1,13,0,67894,0,0,0,10],
|
||||
["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,19,0,30095,0,7111,86,3],
|
||||
["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",0,0,21,1,150260,13231,0,28,28],
|
||||
["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,60,0,22306,8566,349,73,3],
|
||||
["p1",1,"op","chess_char_6_03_b",2,"uniequip_002_yu",5902.25,1,15,0,2317,10287,12324,32,3],
|
||||
["p1",2,"op","chess_char_6_06_b",2,"uniequip_002_pepe",2893.32,1,11,0,20047,281,0,22,1],
|
||||
["p1",3,"op","chess_char_6_07_b",2,"uniequip_002_siege2",1834.75,1,17,0,42326,1612,0,24,2],
|
||||
["p1",4,"op","chess_char_6_01_b",2,"uniequip_002_lemuen",430.19,1,7,1,1229734,2143,0,58,8],
|
||||
["p1",5,"op","chess_char_6_02_b",2,"uniequip_002_sbell2",1329.31,1,9,0,34472,14154,0,46,2],
|
||||
["p1",6,"op","chess_char_6_04_b",2,"uniequip_002_skadi2",0,0,66,0,35830,9923,233,0,3],
|
||||
["p1",7,"op","chess_char_6_05_b",2,"uniequip_002_pasngr",2451.4,1,13,0,69036,0,0,0,11],
|
||||
["p1",8,"op","chess_char_6_08_b",2,"uniequip_002_reed2",1668,1,19,0,26444,0,7415,77,2],
|
||||
["p1",9,"op","chess_char_6_09_b",0,"uniequip_002_cello",0,0,21,1,174620,13925,0,30,30],
|
||||
["p1",10,"op","chess_char_6_11_b",2,"uniequip_002_mlyss",1893,1,60,0,22306,9359,349,73,2],
|
||||
["p1",11,"token","token_10017_skadi2_dedant",null,null,138,0,28,0,0,0,0,0,null],
|
||||
["p1",12,"token","token_10030_mlyss_wtrman",null,null,0,0,24,0,0,1640,318,4,1],
|
||||
["p2",13,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",0,0,66,4,730725,36055,0,338,3],
|
||||
["p2",14,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",203.08,1,58,0,450324,11985,0,58,5],
|
||||
["p2",15,"op","chess_char_5_01_b",1,"uniequip_002_excu2",0,0,65,0,41071,8230,3308,52,2],
|
||||
["p2",16,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",3430.93,1,59,1,771816,24776,0,77,3],
|
||||
["p2",17,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",2886.8,1,8,0,378435,1696,0,78,3],
|
||||
["p2",18,"op","chess_char_6_13_b",1,"uniequip_002_angel2",2215,1,14,0,1014033,6744,2745,288,6],
|
||||
["p2",19,"op","chess_char_6_14_b",2,"uniequip_002_lumen",3038.4,1,20,0,0,0,7939,78,1],
|
||||
["p2",20,"op","chess_char_6_16_b",2,"uniequip_002_halo2",1439,1,10,0,105424,0,0,132,4],
|
||||
["p2",21,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",1690.1,1,41,0,234825,7508,0,60,4],
|
||||
["p2",22,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",1592.1,1,25,0,0,14000,95391,82,2],
|
||||
["p2",13,"op","chess_char_6_15_b",2,"uniequip_002_qiubai",2052.07,1,68,4,561677,30058,0,292,3],
|
||||
["p2",14,"op","chess_char_6_19_b",2,"uniequip_002_blkkgt",0,0,59,0,341242,18065,0,56,4],
|
||||
["p2",15,"op","chess_char_5_01_b",1,"uniequip_002_excu2",0,0,65,0,3198,6795,1515,24,1],
|
||||
["p2",16,"op","chess_char_6_17_b",2,"uniequip_002_nearl2",0,0,55,1,514814,17168,0,62,3],
|
||||
["p2",17,"op","chess_char_6_12_b",1,"uniequip_002_rosmon",942.17,1,8,0,674333,8720,0,73,3],
|
||||
["p2",18,"op","chess_char_6_13_b",1,"uniequip_002_angel2",0,0,14,0,769354,8634,2644,263,5],
|
||||
["p2",19,"op","chess_char_6_14_b",2,"uniequip_002_lumen",3038.4,1,20,0,0,0,15762,80,1],
|
||||
["p2",20,"op","chess_char_6_16_b",2,"uniequip_002_halo2",0,0,10,0,97174,1439,0,119,3],
|
||||
["p2",21,"op","chess_char_6_18_b",2,"uniequip_002_whitw2",0,0,62,0,132239,19665,0,24,3],
|
||||
["p2",22,"op","chess_char_6_20_b",2,"uniequip_002_agoat2",1183.78,1,25,0,0,15377,101728,82,2],
|
||||
["-","~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],
|
||||
["-","~3","device","trap_1105_accrate",null,null,100,1,3,0,0,0,0,0,null],
|
||||
["-","~4","device","trap_1105_accrate",null,null,100,1,4,0,0,0,0,0,null],
|
||||
["-","~5","device","trap_1105_accrate",null,null,100,1,5,0,0,0,0,0,null],
|
||||
["-","~6","device","trap_1105_accrate",null,null,100,1,6,0,0,0,0,0,null],
|
||||
["p2","~1","token","token_10019_nearl2_sword",null,null,4710.39,0,47,0,6744,3570,0,5,null],
|
||||
["p1","~1","token","token_10030_mlyss_wtrman",null,null,0,0,48,0,1670,1538,0,22,1],
|
||||
["p1","~2","token","token_10030_mlyss_wtrman",null,null,0,0,49,0,220,3142,0,9,null],
|
||||
["p1","~3","token","token_10030_mlyss_wtrman",null,null,0,0,51,0,463,1322,0,7,null],
|
||||
["p1","~1","token","token_10040_siege2_vlion",null,null,3730,0,53,0,4750,270,0,10,null],
|
||||
["p1","~1","token","token_10017_skadi2_dedant",null,null,138,0,56,0,0,0,0,0,null],
|
||||
["p2","~2","token","token_10019_nearl2_sword",null,null,0,0,57,0,68925,6922,0,11,null],
|
||||
["p1","~4","token","token_10030_mlyss_wtrman",null,null,1172,1,61,0,1025,710,538,7,1],
|
||||
["p1","~2","token","token_10017_skadi2_dedant",null,null,100,0,62,0,0,0,0,0,null],
|
||||
["p1","~2","token","token_10040_siege2_vlion",null,null,3942.24,0,63,0,0,76,0,0,null],
|
||||
["p2","~3","token","token_10019_nearl2_sword",null,null,3290.4,0,64,0,8355,3008,0,21,null],
|
||||
["p1","~3","token","token_10017_skadi2_dedant",null,null,100,1,68,0,0,0,0,0,null]
|
||||
["p2","~1","token","token_10019_nearl2_sword",null,null,2916.93,0,47,0,6778,5363,0,21,null],
|
||||
["p1","~1","token","token_10030_mlyss_wtrman",null,null,0,0,48,1,1801,1538,0,22,1],
|
||||
["p1","~2","token","token_10030_mlyss_wtrman",null,null,0,0,49,0,207,3142,0,9,null],
|
||||
["p1","~3","token","token_10030_mlyss_wtrman",null,null,0,0,50,0,463,1322,0,7,null],
|
||||
["p1","~1","token","token_10040_siege2_vlion",null,null,3730,0,52,0,4750,270,0,10,null],
|
||||
["p1","~1","token","token_10017_skadi2_dedant",null,null,138,0,57,0,0,0,0,0,null],
|
||||
["p2","~2","token","token_10019_nearl2_sword",null,null,6950.53,0,58,0,0,963,0,0,null],
|
||||
["p1","~4","token","token_10030_mlyss_wtrman",null,null,1322,1,61,0,0,385,293,0,1],
|
||||
["p1","~2","token","token_10040_siege2_vlion",null,null,3897.9,0,63,0,0,137,0,0,null],
|
||||
["p2","~3","token","token_10019_nearl2_sword",null,null,133.02,0,64,0,16707,6165,0,9,null],
|
||||
["p1","~2","token","token_10017_skadi2_dedant",null,null,100,0,67,0,0,0,0,0,null]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_1267_nhpbr_2": [6,6,0,1800,141894],
|
||||
"enemy_9007_acelem": [2,2,0,15725,309587],
|
||||
"enemy_9017_achunt_2": [2,0,0,54791,2088993],
|
||||
"enemy_9018_actrpa": [1,0,0,30160,855522],
|
||||
"enemy_9019_actrpb": [1,0,0,29590,798033],
|
||||
"enemy_9020_actrpc": [1,0,0,20449,1384683]
|
||||
"enemy_1267_nhpbr_2": [6,6,0,1400,141894],
|
||||
"enemy_9007_acelem": [2,2,0,17143,309587],
|
||||
"enemy_9017_achunt_2": [2,0,0,58691,1852251],
|
||||
"enemy_9018_actrpa": [1,0,0,44364,722451],
|
||||
"enemy_9019_actrpb": [1,0,0,28255,660498],
|
||||
"enemy_9020_actrpc": [1,0,0,23012,1168947]
|
||||
},
|
||||
"hooks": [1,66,6000,1799,1799,6944,13382,2834,25,37,99,90,326,47765,2836,14,13,0,1,26,0,13,0],
|
||||
"events": {"atk":2246,"deploy":47,"die":37,"dmg":12926,"engage":25,"fx":2188,"heal":930,"skill":189,"spawn":53,"status":849},
|
||||
"hooks": [1,66,6000,1682,1682,6586,12669,2825,29,42,95,91,286,44763,2551,19,13,0,1,30,0,16,0],
|
||||
"events": {"atk":2097,"deploy":47,"die":42,"dmg":12154,"engage":23,"fx":2024,"heal":885,"skill":186,"spawn":52,"status":769},
|
||||
"fx": {
|
||||
"airstrike": 123,
|
||||
"beam": 31,
|
||||
"airstrike": 88,
|
||||
"beam": 27,
|
||||
"blessing": 1,
|
||||
"blink": 5,
|
||||
"bombard": 72,
|
||||
"bombardShell": 72,
|
||||
"burst": 13,
|
||||
"burst": 16,
|
||||
"camouflage": 1,
|
||||
"copy": 3,
|
||||
"dash": 24,
|
||||
"displace": 1,
|
||||
"dp": 3,
|
||||
"drone": 320,
|
||||
"droneLock": 14,
|
||||
"drones": 4,
|
||||
"extraAttack": 16,
|
||||
"finale": 5,
|
||||
"displace": 20,
|
||||
"dp": 2,
|
||||
"drone": 190,
|
||||
"droneLock": 9,
|
||||
"drones": 3,
|
||||
"extraAttack": 7,
|
||||
"finale": 4,
|
||||
"firewall": 3,
|
||||
"garrisonGrant": 1,
|
||||
"lightning": 116,
|
||||
"lightning": 117,
|
||||
"link": 1141,
|
||||
"lock": 72,
|
||||
"lure": 1,
|
||||
"phase": 12,
|
||||
"lure": 2,
|
||||
"phase": 11,
|
||||
"radiantSword": 3,
|
||||
"revive": 3,
|
||||
"scorchBurst": 1,
|
||||
"shieldBreak": 10,
|
||||
"slash": 55,
|
||||
"snow": 15,
|
||||
"shieldBreak": 9,
|
||||
"slash": 44,
|
||||
"snow": 26,
|
||||
"split": 2,
|
||||
"steal": 6,
|
||||
"storm": 10,
|
||||
"steal": 5,
|
||||
"storm": 11,
|
||||
"summon": 5,
|
||||
"sunBurst": 3,
|
||||
"talent": 5,
|
||||
"tide": 4,
|
||||
"talent": 6,
|
||||
"tide": 3,
|
||||
"wanted": 6,
|
||||
"zone": 6
|
||||
},
|
||||
"snaps": "2a921421 57801ce9 151fd5ae 264faece f8920de3 cef81b6f 47f4a450 cc0a8289 6b7ac4fb 81b93e22 d10e889f 97a33a13 a796916b 202ae19b 16aa629d c7afee38 08c75624 11b64823 c1f874f3 b92e528f"
|
||||
"snaps": "2a921421 57801ce9 151fd5ae 991b7440 79722413 1faab651 85db54ec 88d6f82e 6d938e5f fc881a30 9c294f55 4373e468 af475c5f df3e9b70 b0474d4c 538602b8 4e66de79 e70dcab9 481e5d84 e8e351b1"
|
||||
},
|
||||
"hidden-boss_9-solo": {
|
||||
"about": "假想敌:铳 solo pool 2800000: chess_char_5_08_b chess_char_5_11_b chess_char_5_05_b chess_char_5_06_b chess_char_5_13_b chess_char_5_07_b chess_char_5_02_b chess_char_5_03_b chess_char_5_10_b chess_char_5_12_b",
|
||||
@@ -1228,37 +1227,35 @@
|
||||
"killed": 3,
|
||||
"total": 3,
|
||||
"unspawned": 0,
|
||||
"bossHpLeft": 1932856,
|
||||
"rngDraws": 128,
|
||||
"bossHpLeft": 2011732,
|
||||
"rngDraws": 207,
|
||||
"errors": {"count":0,"kinds":[]},
|
||||
"players": {"p1":{"killed":3,"total":3,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":2753803,"bossDmg":867144,"heal":73158,"deaths":5,"layerGains":{}}},
|
||||
"players": {"p1":{"killed":3,"total":3,"perfect":true,"leaks":0,"leaksUncounted":0,"coins":0,"dmg":2574046,"bossDmg":788268,"heal":101441,"deaths":5,"layerGains":{}}},
|
||||
"units": [
|
||||
["p1",1,"op","chess_char_5_08_b",2,"uniequip_002_horn",2775,1,1,1,368359,8434,0,127,4],
|
||||
["p1",2,"op","chess_char_5_11_b",1,"uniequip_002_demkni",4804.8,1,3,0,1265,3442,23540,46,35],
|
||||
["p1",3,"op","chess_char_5_05_b",2,"uniequip_002_ulpia",11263.65,1,33,0,413261,29216,17173,39,5],
|
||||
["p1",4,"op","chess_char_5_06_b",2,"uniequip_002_etlchi",3747,1,7,1,1380629,16819,16926,201,5],
|
||||
["p1",5,"op","chess_char_5_13_b",1,"uniequip_002_ghost2",3448.92,1,9,0,128392,14229,3714,76,3],
|
||||
["p1",6,"op","chess_char_5_07_b",2,"uniequip_002_surtr",7680,1,35,0,42625,19991,4759,13,3],
|
||||
["p1",7,"op","chess_char_5_02_b",2,"uniequip_002_titi",1439,1,5,0,0,0,0,1,1],
|
||||
["p1",8,"op","chess_char_5_03_b",2,"uniequip_002_blaze2",1148.18,1,6,0,207074,1471,1147,186,6],
|
||||
["p1",9,"op","chess_char_5_10_b",2,"uniequip_002_lisa",1480,1,32,0,14018,13299,5899,28,6],
|
||||
["p1",10,"op","chess_char_5_12_b",0,"uniequip_002_dusk",1787,1,2,1,198179,0,0,53,41],
|
||||
["p1","~1","token","token_10039_ulpia_block",null,null,3290,0,20,0,0,210,0,0,null],
|
||||
["p1","~2","token","token_10039_ulpia_block",null,null,3335,0,28,0,0,165,0,0,null]
|
||||
["p1",1,"op","chess_char_5_08_b",2,"uniequip_002_horn",2757.97,1,1,1,328544,10883,0,121,4],
|
||||
["p1",2,"op","chess_char_5_11_b",1,"uniequip_002_demkni",4784.8,1,3,0,2559,11172,34206,59,38],
|
||||
["p1",3,"op","chess_char_5_05_b",2,"uniequip_002_ulpia",10680.88,1,4,0,391098,51057,37953,64,5],
|
||||
["p1",4,"op","chess_char_5_06_b",2,"uniequip_002_etlchi",1801.92,1,7,0,1462149,23079,21225,197,5],
|
||||
["p1",5,"op","chess_char_5_13_b",1,"uniequip_002_ghost2",3448.92,1,19,1,146526,21512,5080,102,4],
|
||||
["p1",6,"op","chess_char_5_07_b",2,"uniequip_002_surtr",2680,1,23,0,4444,7780,113,7,1],
|
||||
["p1",7,"op","chess_char_5_02_b",2,"uniequip_002_titi",1439,1,5,0,0,0,0,0,0],
|
||||
["p1",8,"op","chess_char_5_03_b",2,"uniequip_002_blaze2",1207.04,1,6,0,32056,265,0,25,1],
|
||||
["p1",9,"op","chess_char_5_10_b",2,"uniequip_002_lisa",1480,1,28,0,0,8783,2863,1,5],
|
||||
["p1",10,"op","chess_char_5_12_b",0,"uniequip_002_dusk",1787,1,2,1,206669,0,0,57,43]
|
||||
],
|
||||
"enemies": {
|
||||
"enemy_10067_ftsjc": [1,1,0,1161,21565],
|
||||
"enemy_5601_entlec": [6,5,0,0,160038],
|
||||
"enemy_9007_acelem": [2,2,0,632,119439],
|
||||
"enemy_9017_achunt_2": [1,0,0,32010,867144],
|
||||
"enemy_9018_actrpa": [1,0,0,14160,440951],
|
||||
"enemy_9019_actrpb": [1,0,0,19148,445768],
|
||||
"enemy_9020_actrpc": [1,0,0,13881,698896]
|
||||
"enemy_5601_entlec": [8,7,0,0,221752],
|
||||
"enemy_9007_acelem": [2,2,0,1897,119439],
|
||||
"enemy_9017_achunt_2": [1,0,0,61863,788268],
|
||||
"enemy_9018_actrpa": [1,0,0,22333,431138],
|
||||
"enemy_9019_actrpb": [1,0,0,16840,403557],
|
||||
"enemy_9020_actrpc": [1,0,0,15204,588326]
|
||||
},
|
||||
"hooks": [1,36,6000,876,876,3337,7978,7359,13,17,109,104,118,25510,1863,10,13,0,1,120,0,2,0],
|
||||
"events": {"atk":1327,"deploy":23,"die":17,"dmg":7399,"engage":10,"fx":851,"heal":385,"skill":213,"spawn":25,"status":317},
|
||||
"fx": {"anchor":5,"aoe":3,"beam":22,"burst":2,"candle":6,"charge":7,"dash":12,"downed":1,"ember":2,"explode":1,"healAoe":35,"link":597,"overload":4,"palsy":3,"phase":12,"reborn":1,"shieldBreak":10,"splash":118,"substitute":3,"swap":3,"teleport":4},
|
||||
"snaps": "9f379cb4 794e9645 d2f1f9f3 6f045130 3ba3cbda c2dffcd7 002617f9 8eb229f1 44fa10f5 02a4f054 024d05f4 4f2b850e 264e7810 e232b25c fb23ac72 ffe30a9a 966d17a8 f21eca66 c335c5c3 dadd437f"
|
||||
"hooks": [1,31,6000,758,758,3651,7974,3912,15,16,106,103,21,22194,1289,14,15,0,1,70,0,8,0],
|
||||
"events": {"atk":1320,"deploy":16,"die":16,"dmg":7575,"engage":9,"fx":765,"heal":611,"skill":209,"spawn":25,"status":228},
|
||||
"fx": {"anchor":5,"aoe":1,"beam":30,"burst":8,"candle":8,"charge":7,"dash":12,"dollEnd":1,"ember":1,"explode":1,"healAoe":38,"link":597,"overload":4,"palsy":3,"phase":11,"reborn":1,"revive":1,"shieldBreak":9,"splash":21,"substitute":4,"swap":2},
|
||||
"snaps": "9f379cb4 794e9645 1eab82b0 9bd21a64 94bcd685 ea068a42 11f6e172 f1d86469 8dae333a a7b0bf9e 854de036 d7f516e9 946585b3 06953c95 f04d0312 832df1bd 4f3fdc1c eec59b6e 4c10a52c 9c930ebb"
|
||||
},
|
||||
"hidden-boss_10-pair": {
|
||||
"about": "假想敌:管 pair pool 15200000: chess_char_5_19_b chess_char_4_01_b chess_char_5_14_b chess_char_5_17_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b chess_char_5_22_b chess_char_5_23_b chess_char_4_02_b | chess_char_4_11_b chess_char_4_04_b chess_char_4_07_b chess_char_4_16_b chess_char_4_09_b chess_char_4_06_b chess_char_4_10_b chess_char_4_12_b chess_char_4_13_b chess_char_4_14_b token_10041_cathy_catsld token_10041_cathy_catsld",
|
||||
|
||||
@@ -1485,7 +1485,7 @@
|
||||
"title": {"id":"comment_1","name":"卫戍之星","picId":"comment_icon_1","text":"对敌方领袖造成伤害最高(仅胜利时)"},
|
||||
"trophies": 8,
|
||||
"reward": 425,
|
||||
"stats": {"activatedLayers":2267,"bossDamage":7523075,"dmgDealt":26462402,"gold":149,"itemsEquipped":23,"kills":290,"leaks":0,"lpLost":0,"merges":6,"perfectRounds":13,"refreshes":16},
|
||||
"stats": {"activatedLayers":2267,"bossDamage":6992346,"dmgDealt":24545248,"gold":149,"itemsEquipped":23,"kills":290,"leaks":0,"lpLost":0,"merges":6,"perfectRounds":13,"refreshes":16},
|
||||
"lineup": ["3_16_b@12,8[3_01_e_a+1_01_e_b]","4_09_b@11,5","3_11_b@11,8[3_02_e_a+6_06_e_a]","1_02_b@10,4[1_02_e_a+4_02_e_a]","5_14_a@10,8[3_03_e_a+1_05_e_a]","6_20_a@9,6","3_20_a@9,8[3_07_e_a+3_08_e_a]","6_05_a@9,9[2_04_e_a+5_02_e_b]"],
|
||||
"bonds": ["arcaneShip 0/316","deputShip 1/312","egirShip 0/300","emptyShip 0/300","indomShip 0/300","investShip 0/300","kazimierzShip 0/302","kjeragShip 1/343","lateranoShip 0/300","maniShip 0/300","miraShip 0/300","preciShip 1/343","raidShip 0/300","sargonShip 0/300","siracusaShip 0/300","skillfulShip 0/319","soloShip 1/310","steadShip 1/341","suntShip 1/310","swiftShip 1/308","victoriaShip 0/300","visiShip 0/300","yanShip 0/300"]
|
||||
},
|
||||
@@ -1499,7 +1499,7 @@
|
||||
"title": {"id":"comment_2","name":"不朽盟约","picId":"comment_icon_2","text":"激活的盟约层数总和最高"},
|
||||
"trophies": 8,
|
||||
"reward": 425,
|
||||
"stats": {"activatedLayers":2301,"bossDamage":6369365,"dmgDealt":22481097,"gold":165,"itemsEquipped":31,"kills":276,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":38},
|
||||
"stats": {"activatedLayers":2301,"bossDamage":6900614,"dmgDealt":23861530,"gold":165,"itemsEquipped":31,"kills":276,"leaks":0,"lpLost":0,"merges":5,"perfectRounds":13,"refreshes":38},
|
||||
"lineup": ["2_10_a@11,5[2_03_e_b+3_09_e_a]","5_03_a@11,8[1_02_e_a+5_02_e_a]","1_06_a@10,3[1_05_e_a+3_02_e_a]","3_16_a@10,4[3_03_e_b+4_04_e_b]","5_06_a@10,8[3_09_e_b+3_09_e_b]","4_21_b@9,6[4_06_e_a+3_10_e_b]","5_02_a@9,8[4_09_e_a+3_06_e_b]","1_17_b@9,9[3_08_e_a+1_01_e_a]"],
|
||||
"bonds": ["arcaneShip 1/327","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 1/404","raidShip 0/300","sargonShip 0/300","siracusaShip 0/300","skillfulShip 1/308","soloShip 0/310","steadShip 0/323","suntShip 1/304","swiftShip 0/300","victoriaShip 1/332","visiShip 0/300","yanShip 0/305"]
|
||||
}
|
||||
|
||||
@@ -247,7 +247,9 @@ test('E2 audit: healers on the lane tiles of every boss / hidden field deal no d
|
||||
const lead = (e) => e.isBoss || e.tag === 'boss' || e.tag === 'part' || LUCIEN.test(e.defId);
|
||||
let healsOnLead = 0;
|
||||
h.b.on('heal', (c) => { if (healers.includes(c.source) && c.amount > 0 && c.source.blocking.some(lead)) healsOnLead++; });
|
||||
for (let i = 0; i < 120 * 30; i++) {
|
||||
// 200 s on the fields whose leaders / parts a healer must block (the solo 铳 field's springs first meet a healer at
|
||||
// 145 s since their 末日布道 chase lasts its whole 5 s — PR #347), 120 s elsewhere
|
||||
for (let i = 0; i < (EXPECT[key] ? 200 : 120) * 30; i++) {
|
||||
h.step();
|
||||
// operators break the 碎铳之簧 shields (unblockable while shielded): a hit of the kind each shield yields to
|
||||
for (const e of h.b.enemies) {
|
||||
|
||||
Reference in new issue
Block a user