feedback5 WE2: 黑键 S2 casts at full SP once a placeable tile of his range is free, no enemy needed (#23)

PRTS 黑键 S2 备注 "攻击范围内不存在可部署位时,技能不会被触发" (skill prefab _minTileNum 1):
the kit casts it (trigger NEVER + a tick: ready, able to act, one free deployable tile
in his range — hasRemnantTile, no rng) instead of the data's DEFAULT waiting for an
enemy. Checked and kept: 温蒂's cannon (summons follow the basic strategy, PRTS
"对于拥有手动释放技能的召唤物,亦会强制开启技能"), 凯尔希·思衡托 S2 (a medic's target is an
injured ally; the owner's ACTIVE_RANGE on her y-11).
Golden: diy-114, diy-115, diy-116 moved — the scenarios fielding 黑键 S2 (his S2 fires at
full SP from the battle start).
This commit is contained in:
sganggs committed 2026-10-06 15:25:07 +08:00
1 parent ac6f712142
commit 708719f382
4 files changed
+144 -105

No files matched your search

+1 -1
View File
@@ -312,7 +312,7 @@ Duration end cleans the window and emits `skillEnd`; it leaves zero charges and
Redeployment opens a new full window. Permanent passives retain `passive`; first-kill recasts of 缄默德克萨斯 explicitly
restart a full window. Special timed kits and their effect rules are described in SIM §7.2.
Auto-trigger rules (`skillTrigger.rule` in data — the official 技能策略, PRTS 卫戍协议/帮助 §作战阶段 技能操作; §20.2): `DEFAULT` (SP ready AND about to attack/heal AND an enemy/injured ally inside the **initial** range, or an enemy the unit blocks; with `trigger.allies` + `hpAtMost` an ally of the skill grid at or below that HP ratio — 塞雷娅 S1 急救, whose cast replaces that attack and is withdrawn with its charge if the ally recovers first), `SKILL_RANGE` (a MANUAL skill with a 技能范围 of its own, not an attack-range change: any living enemy, stealthed ones included, on the skill range, checked every tick — "仅在技能范围内存在敌人(无视其不可选中)时释放技能"; 13 skills / 26 records by the official rule, 14 / 28 in the data with 余 S2's deviation, §22.10), `ACTIVE_RANGE` (the owner's deliberate deviation of 2026-10-05, 0.2.0: a MANUAL skill on the basic strategy — or, by the owner's further decisions of the same day, on the `SEARCH` row, and 深巡 S2 on top of its §21.29 DEFAULT — whose attack range while it runs strictly contains the operator's own range — its rangeId grid, or the own range grown by `ability_range_forward_extend` — checks the DEFAULT condition on that running range every tick, no attack needed; `customRangeGrid` = the running range, `rawRule` the official row (DEFAULT, SEARCH, 深巡's TAKE_DAMAGE); 39 skills / 78 records, of them 薄绿 S1, 蜜蜡 S1, 卡涅利安 S3, 玛恩纳 S2 and 安洁莉娜 S3 from SEARCH; 烛煌 S2 / S3, whose ranges do not contain her 3-1, keep DEFAULT), `TAKE_DAMAGE` (on taking damage — any damage, 无来源 included, never a 流失; every MANUAL 重装 skill, §21.12 — but the six of the deliberate deviation, §21.29: 深巡 / 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 are `DEFAULT`, `rawRule` keeping the official TAKE_DAMAGE — 深巡 S2 then `ACTIVE_RANGE` on its 3-2; and 余 S2, `SKILL_RANGE` on its x-1 (§22.10); the 重装 of data/backups.json — the 补位 stand-ins 预备干员-重装 / Mechanist and every 自选 重装 — cast with an enemy in range, `DEFAULT` (or `ACTIVE_RANGE` when the skill's running range is larger), by the owner's decisions of 2026-10-05), `SP_FULL` (immediately — 执旗手 / 战术家 / 吟游者 MANUAL skills, AUTO DP skills such as 焰尾 S1, 凛御银灰 S1 (伺夜 S1 / S2 too, but only while his pack is on the field — PRTS 备注 「仅场上存在狼群时可触发技能」, the kit's own cast; the owner's decision of 2026-10-05 for S1; S1 also while the pack sits in its 战术点形态, which the cast ends — S2 waits for it to come back [ASSUMED]), and, by their kits, AUTO skills whose effects act on allies only: 引星棘刺 S1, 浊心斯卡蒂 S2, 纯烬艾雅法拉 S1 — the owner's decision of 2026-10-05 for the last), `CUSTOM_RANGE` (enemy inside the custom grid), `SEARCH` (an enemy inside the initial range, checked every tick — no attack needed; 解放者 / 阵法术师 MANUAL skills and 安洁莉娜 S2, those without a larger running range), `GDGLOW_SKILL_2` (a valid target anywhere on the field: 荒芜拉普兰德, 纯烬艾雅法拉 S3), special ids. The class rows cover **every MANUAL skill** of the class and never an AUTO skill (AUTO skills keep their own rule — an inference: PRTS names whole classes; the data's `skillIndex 0` / `-1` sentinel argues the other way, §20.2). **Operation cooldown**: the engine auto-casts a MANUAL skill no sooner than `AUTO_OP_COOLDOWN` (3 s) after its previous cast and after the unit's battle-start deployment ("自动操作具有3s冷却,在完成一次操作或作战开始时部署的单位将进入冷却"; `Battle._deploy` initial, `battle.flags.startOpCooldown`); kits with an automatic cast of their own check `skill.opCooling`; a pending "next attack" never takes a second charge. Permanent passive skills are always on; finite deployment effects use the duration lifecycle above.
Auto-trigger rules (`skillTrigger.rule` in data — the official 技能策略, PRTS 卫戍协议/帮助 §作战阶段 技能操作; §20.2): `DEFAULT` (SP ready AND about to attack/heal AND an enemy/injured ally inside the **initial** range, or an enemy the unit blocks; with `trigger.allies` + `hpAtMost` an ally of the skill grid at or below that HP ratio — 塞雷娅 S1 急救, whose cast replaces that attack and is withdrawn with its charge if the ally recovers first), `SKILL_RANGE` (a MANUAL skill with a 技能范围 of its own, not an attack-range change: any living enemy, stealthed ones included, on the skill range, checked every tick — "仅在技能范围内存在敌人(无视其不可选中)时释放技能"; 13 skills / 26 records by the official rule, 14 / 28 in the data with 余 S2's deviation, §22.10), `ACTIVE_RANGE` (the owner's deliberate deviation of 2026-10-05, 0.2.0: a MANUAL skill on the basic strategy — or, by the owner's further decisions of the same day, on the `SEARCH` row, and 深巡 S2 on top of its §21.29 DEFAULT — whose attack range while it runs strictly contains the operator's own range — its rangeId grid, or the own range grown by `ability_range_forward_extend` — checks the DEFAULT condition on that running range every tick, no attack needed; `customRangeGrid` = the running range, `rawRule` the official row (DEFAULT, SEARCH, 深巡's TAKE_DAMAGE); 39 skills / 78 records, of them 薄绿 S1, 蜜蜡 S1, 卡涅利安 S3, 玛恩纳 S2 and 安洁莉娜 S3 from SEARCH; 烛煌 S2 / S3, whose ranges do not contain her 3-1, keep DEFAULT), `TAKE_DAMAGE` (on taking damage — any damage, 无来源 included, never a 流失; every MANUAL 重装 skill, §21.12 — but the six of the deliberate deviation, §21.29: 深巡 / 雷蛇 S2, 号角 S2 / S3 and 灰毫 S1 / S2 are `DEFAULT`, `rawRule` keeping the official TAKE_DAMAGE — 深巡 S2 then `ACTIVE_RANGE` on its 3-2; and 余 S2, `SKILL_RANGE` on its x-1 (§22.10); the 重装 of data/backups.json — the 补位 stand-ins 预备干员-重装 / Mechanist and every 自选 重装 — cast with an enemy in range, `DEFAULT` (or `ACTIVE_RANGE` when the skill's running range is larger), by the owner's decisions of 2026-10-05), `SP_FULL` (immediately — 执旗手 / 战术家 / 吟游者 MANUAL skills, AUTO DP skills such as 焰尾 S1, 凛御银灰 S1 (伺夜 S1 / S2 too, but only while his pack is on the field — PRTS 备注 「仅场上存在狼群时可触发技能」, the kit's own cast; the owner's decision of 2026-10-05 for S1; S1 also while the pack sits in its 战术点形态, which the cast ends — S2 waits for it to come back [ASSUMED]; 黑键 S2 荒芜回响 likewise only while one placeable tile of his range is free, no enemy needed — PRTS 备注 「攻击范围内不存在可部署位时,技能不会被触发」, its kit's cast, 0.2.0), and, by their kits, AUTO skills whose effects act on allies only: 引星棘刺 S1, 浊心斯卡蒂 S2, 纯烬艾雅法拉 S1 — the owner's decision of 2026-10-05 for the last), `CUSTOM_RANGE` (enemy inside the custom grid), `SEARCH` (an enemy inside the initial range, checked every tick — no attack needed; 解放者 / 阵法术师 MANUAL skills and 安洁莉娜 S2, those without a larger running range), `GDGLOW_SKILL_2` (a valid target anywhere on the field: 荒芜拉普兰德, 纯烬艾雅法拉 S3), special ids. The class rows cover **every MANUAL skill** of the class and never an AUTO skill (AUTO skills keep their own rule — an inference: PRTS names whole classes; the data's `skillIndex 0` / `-1` sentinel argues the other way, §20.2). **Operation cooldown**: the engine auto-casts a MANUAL skill no sooner than `AUTO_OP_COOLDOWN` (3 s) after its previous cast and after the unit's battle-start deployment ("自动操作具有3s冷却,在完成一次操作或作战开始时部署的单位将进入冷却"; `Battle._deploy` initial, `battle.flags.startOpCooldown`); kits with an automatic cast of their own check `skill.opCooling`; a pending "next attack" never takes a second charge. Permanent passive skills are always on; finite deployment effects use the duration lifecycle above.
**SkillSpec** (authored per chess in `sim/content/kits/tierN.js`; values come from the chess's skill blackboard at its level — normal Lv4, elite Lv7 — so a spec is a *function of the blackboard*):
```js
+23 -3
View File
@@ -39,7 +39,10 @@
// (PRTS "大幅度缩短(*0.2)": batMod's ratio reading), every attack attack@atk_scale × ATK; the energies released meanwhile
// use that scale too (备注 "该技能的“每次攻击的攻击倍率”会实时应用在特性积攒的“攻击能量”抛射物上") × the energy scale.
// `attack@cnt` (1) has no text [unused].
// - S2 荒芜回响 (AUTO, instant, data DEFAULT — an AUTO skill whose effect acts on enemies keeps the data rule): spends every
// - S2 荒芜回响 (AUTO, instant): cast at full SP as soon as one placeable tile of his attack range is free — no enemy needed
// (PRTS 备注 "攻击范围内不存在可部署位时,技能不会被触发"; the skill prefab's `_trigger._minTileNum` 1 — O20's report; 0.2.0 WE2:
// until then the data's DEFAULT waited for an enemy in his range; `trigger: 'NEVER'` + this kit's cast, the pattern of
// 伺夜's conditional casts): spends every
// stored energy (elite ones first: 备注 "可以消耗并优先消耗第一天赋储存的额外能量") and places energies + 1 旧日残影 on free
// placeable tiles of his attack range (部署位置 全部位), in the 备注's order: tiles holding a selectable ground enemy (the
// best of them first by his target order — 仇恨值 [ASSUMED: the engine's default operator order]), then the tiles nearest
@@ -88,6 +91,15 @@ export const eliteOrLeader = (e) => !!e && (!!e.isBoss || e.def?.rank === 'ELITE
/** His stored energies (per deployment): `n` normal, `e` elite, `q` the volleys in flight per target id. */
const stateOf = (unit) => unit.trait.ebn ?? (unit.trait.ebn = { n: 0, e: 0, q: new Map() });
/** A tile 荒芜回响 may place a 旧日残影 on: inside the field, deployable (全部位) and free (Battle.isReservedTile). */
const remnantTileOk = (battle, r, c) => battle.grid.inRect(r, c) && battle.grid.canStand(r, c, { ranged: true }) && !battle.isReservedTile(r, c);
/** Whether `unit`'s attack range holds one tile 荒芜回响 may use (its cast condition; no rng, unlike remnantTiles). */
function hasRemnantTile(battle, unit) {
for (const k of unit.rangeKeys || []) if (remnantTileOk(battle, Math.floor(k / COLS), k % COLS)) return true;
return false;
}
/**
* The tiles 荒芜回响 may place 旧日残影 on (PRTS 备注 order): free deployable tiles of `unit`'s attack range — first those
* holding a selectable ground enemy, by the best of them in his target order; then by the distance to the nearest
@@ -97,8 +109,7 @@ function remnantTiles(battle, unit) {
const tiles = [];
for (const k of unit.rangeKeys || []) {
const r = Math.floor(k / COLS), c = k % COLS;
if (!battle.grid.inRect(r, c) || !battle.grid.canStand(r, c, { ranged: true }) || battle.isReservedTile(r, c)) continue;
tiles.push([r, c]);
if (remnantTileOk(battle, r, c)) tiles.push([r, c]);
}
if (!tiles.length) return tiles;
const foes = battle.enemies.filter((e) => canTargetEnemy(unit, e, GROUND));
@@ -231,6 +242,7 @@ export default {
},
[S2]: {
kind: 'instant',
trigger: 'NEVER', // the kit's cast (install): full SP and one free placeable tile in his range
onStart({ battle, unit, skill }) {
const tiles = remnantTiles(battle, unit);
if (!tiles.length) { skill.addCharge(1); return; } // "攻击范围内不存在可部署位时,技能不会被触发"
@@ -260,6 +272,14 @@ export default {
},
},
install(battle, unit) {
// S2 荒芜回响: cast at full SP with one free placeable tile in his range, no enemy needed (see the header)
if (unit.skill?.id === S2) {
battle.on('tick', () => {
const sk = unit.skill;
if (!sk || !sk.ready || sk.active || !up(unit) || !unit.canAct || unit.s.flags.silence) return;
if (hasRemnantTile(battle, unit)) sk.activate('SP_FULL');
}, { owner: unit });
}
// MSC-Y: ASPD while any energy is stored
const aspd = num(hidden.attack_speed);
if (aspd) toggleBuff(battle, unit, 'trait:ebnhlz:stored', () => { const v = stateOf(unit); return v.n + v.e > 0; }, { aspd });
+27 -11
View File
@@ -76,7 +76,7 @@ function storeUp(h, u, n, e, max = 60) {
return log;
}
test('黑键 in every 自选 form: his operator kit (all three skills authored), the form\'s stats + module attributes, 3-14, ranged arts every 3 s that hits air units, blocks 1, ground-targetable, the data\'s DEFAULT triggers, 空 bond, no 特质', () => {
test('黑键 in every 自选 form: his operator kit (all three skills authored), the form\'s stats + module attributes, 3-14, ranged arts every 3 s that hits air units, blocks 1, ground-targetable, the data\'s DEFAULT triggers (S2: the kit casts it), 空 bond, no 特质', () => {
assert.equal(OPERATOR_KITS[EBN], KITS[EBN]);
for (const f of FORMS_ALL) {
const [tier, elite, mod] = f;
@@ -88,7 +88,7 @@ test('黑键 in every 自选 form: his operator kit (all three skills authored),
[form.stats.maxHp + (m?.attr.maxHp ?? 0), form.stats.atk + (m?.attr.atk ?? 0), form.stats.def + (m?.attr.def ?? 0), form.stats.res + (m?.attr.res ?? 0), 100 + (m?.attr.aspd ?? 0)], `${label(f)}: stats`);
assert.deepEqual([u.s.blockCnt, u.profile.attack, u.profile.dmgType, u.profile.canHitFly, u.base.bat], [1, 'ranged', 'arts', true, 3], `${label(f)}: 秘术师`);
assert.deepEqual(u.liveRangeGrid, form.rangeGrid, `${label(f)}: 3-14`);
assert.equal(u.skill.rule, 'DEFAULT', `${label(f)}: the data's trigger`);
assert.equal(u.skill.rule, skill === 1 ? 'NEVER' : 'DEFAULT', `${label(f)}: the data's trigger (S2: the kit's own cast)`);
assert.deepEqual([u.def.bonds, u.def.raw.garrisonIds], [['emptyShip'], []], `${label(f)}: bonds / 特质`);
assert.ok(!u.s.flags.liftoff && !u.s.flags.camou && !u.s.flags.stealth, `${label(f)}: ground enemies target him`);
done(h);
@@ -292,16 +292,29 @@ test('S1 渐快急板 (MANUAL, data DEFAULT): 5 s, range 4-1, attack interval ×
}
});
test('S2 荒芜回响 (AUTO, data DEFAULT): spends every energy (elite first) on energies + 1 旧日残影 on free tiles of his range — the enemy\'s tile first, then the nearest; fewer tiles ⇒ fewer spent; no free tile ⇒ no cast (the charge back)', () => {
test('S2 荒芜回响 (AUTO: full SP and one free placeable tile in his range, no enemy needed — PRTS 备注, prefab _minTileNum 1): spends every energy (elite first) on energies + 1 旧日残影 on free tiles of his range — the enemy\'s tile first, then the nearest; fewer tiles ⇒ fewer spent; no free tile ⇒ no cast', () => {
for (const [tier, elite, mod] of [[5, false, null], [6, true, MX]]) {
const sk = skillOf(tier, elite, S2);
assert.deepEqual([sk.skillType, sk.bb.atk_scale, sk.bb.force, sk.spCost, sk.initSp], ['AUTO', elite ? 2 : 1.7, 1, elite ? 14 : 15, 0]);
// no enemy on the field: it casts as soon as its SP is full
{
const { h, u } = field({ tier, elite, mod, skill: 1 });
assert.equal(u.skill.rule, 'NEVER', 'the kit casts it');
let before = stored(u);
for (let i = 0; i < (sk.spCost + 1) * 30 && u.skill.activations === 0; i++) { before = stored(u); h.step(); }
assert.equal(u.skill.activations, 1, 'cast at full SP with no enemy anywhere');
approx(h.b.time, sk.spCost, `T${tier}: at ${sk.spCost} s`, 0.2);
assert.equal(h.b.allyUnits.filter((t) => t.kind === 'token' && t.defId === REMNANT && t.alive).length, before.n + before.e + 1, 'the energies stored meanwhile + 1 remnants');
assert.deepEqual(stored(u), { n: 0, e: 0 }, 'every energy spent');
done(h);
}
const { h, u } = field({ tier, elite, mod, skill: 1 });
const N = traitOf(tier, elite, mod).times;
holdSkill(u);
storeUp(h, u, N, 1);
u.skill.gainSp(999);
const e = h.spawn('enemy_dummy', { pos: [10, 7] });
assert.ok(h.runUntil(() => u.skill.activations === 1, 5), 'cast with an enemy in range');
u.skill.gainSp(999);
assert.ok(h.runUntil(() => u.skill.activations === 1, 5), 'cast');
const rem = h.b.allyUnits.filter((t) => t.kind === 'token' && t.defId === REMNANT);
assert.equal(rem.length, N + 2, `${N} + 1 energies + 1 remnants`);
assert.deepEqual([rem[0].tileR, rem[0].tileC], [10, 7], 'the enemy\'s tile first');
@@ -315,27 +328,30 @@ test('S2 荒芜回响 (AUTO, data DEFAULT): spends every energy (elite first) on
// the flat stage's edge (col 2: RANGED tiles; cols 0–1 none): facing LEFT from (10, 2) no tile of his range is free
{
const { h, u } = field({ tier: 5, skill: 1, row: 10, col: 2, dir: 'LEFT' });
holdSkill(u);
storeUp(h, u, 3, 1);
u.skill.gainSp(999);
h.spawn('enemy_dummy', { pos: [10, 1] });
assert.ok(h.runUntil(() => u.skill.activations >= 1, 5), 'the DEFAULT condition holds (an enemy in range)');
assert.equal(h.b.allyUnits.filter((t) => t.kind === 'token').length, 0, 'no placeable tile: no remnant');
assert.ok(u.skill.ready, 'the charge is back');
u.skill.gainSp(999);
h.run(5);
assert.equal(u.skill.activations, 0, 'no placeable tile: no cast, an enemy in range notwithstanding');
assert.equal(h.b.allyUnits.filter((t) => t.kind === 'token').length, 0, 'no remnant');
assert.ok(u.skill.ready, 'the charge waits');
done(h);
}
// fewer free tiles than energies + 1: facing LEFT from (10, 3) only (10, 2) and (11, 2) are placeable
{
const { h, u } = field({ tier: 5, skill: 1, row: 10, col: 3, dir: 'LEFT' });
holdSkill(u);
storeUp(h, u, 3, 1);
u.skill.gainSp(999);
let atEnd = null;
h.b.on('skillEnd', (c) => { if (c.unit === u) atEnd = stored(u); });
h.spawn('enemy_dummy', { pos: [10, 2] });
u.skill.gainSp(999);
assert.ok(h.runUntil(() => u.skill.activations === 1, 5));
const rem = h.b.allyUnits.filter((t) => t.kind === 'token' && t.defId === REMNANT);
assert.deepEqual(rem.map((t) => [t.tileR, t.tileC]), [[10, 2], [11, 2]], 'the enemy\'s tile, then the other free one');
assert.deepEqual(atEnd, { n: 3, e: 0 }, 'one energy spent — the elite one first');
assert.ok(h.runUntil(() => energyHits(h, u).length === 3, 2), 'the attack that follows releases the three left');
assert.ok(h.runUntil(() => energyHits(h, u).length === 3, 4), 'his next attack (3 s interval) releases the three left');
done(h);
}
});
+93 -90
View File
@@ -4867,45 +4867,45 @@
"time": 205.67,
"ticks": 6170,
"reason": "cleared",
"killed": 124,
"total": 189,
"killed": 121,
"total": 183,
"unspawned": 0,
"bossHpLeft": null,
"rngDraws": 8,
"errors": {"count":0,"kinds":[]},
"players": {"p1":{"killed":124,"total":189,"perfect":false,"leaks":65,"leaksUncounted":0,"coins":0,"dmg":549243,"bossDmg":0,"heal":0,"deaths":16,"layerGains":{}}},
"players": {"p1":{"killed":121,"total":183,"perfect":false,"leaks":62,"leaksUncounted":0,"coins":0,"dmg":524053,"bossDmg":0,"heal":0,"deaths":17,"layerGains":{}}},
"units": [
["p1",1,"op","chess_char_6_diy1_a",0,null,1884,1,191,8,54401,1884,0,59,2],
["p1",2,"op","chess_char_6_diy2_a",1,null,0,0,210,41,38926,3768,0,48,2],
["p1",3,"op","chess_char_6_diy1_a",2,null,1884,1,218,11,57866,1884,0,43,1],
["p1",4,"op","chess_char_6_diy2_b",0,"none",2216,1,196,14,85238,2216,0,68,2],
["p1",5,"op","chess_char_6_diy1_b",1,"none",0,0,153,18,110415,4432,0,41,1],
["p1",6,"op","chess_char_6_diy2_b",2,"none",0,0,182,13,101208,4432,0,48,1],
["p1",1,"op","chess_char_6_diy1_a",0,null,1884,1,190,7,74139,1884,0,56,2],
["p1",2,"op","chess_char_6_diy2_a",1,null,0,0,204,35,51212,3768,0,38,2],
["p1",3,"op","chess_char_6_diy1_a",2,null,0,0,193,8,36822,3768,0,38,1],
["p1",4,"op","chess_char_6_diy2_b",0,"none",2216,1,212,5,23864,2216,0,45,2],
["p1",5,"op","chess_char_6_diy1_b",1,"none",0,0,153,18,103390,4432,0,41,1],
["p1",6,"op","chess_char_6_diy2_b",2,"none",0,0,182,14,109015,4432,0,46,1],
["p1",7,"op","chess_char_5_diy1_a",0,null,1359,1,4,0,0,0,0,0,0],
["p1",8,"op","chess_char_5_diy2_a",1,null,1359,1,5,2,31646,0,0,53,53],
["p1",9,"op","chess_char_5_diy1_a",2,null,1359,1,154,0,39160,1359,0,42,3],
["p1",10,"op","chess_char_5_diy2_b",0,"none",0,0,180,2,9770,3140,0,25,2],
["p1",11,"op","chess_char_5_diy1_b",1,"none",0,0,175,0,6679,3140,0,21,4],
["p1",12,"op","chess_char_5_diy2_b",2,"none",0,0,141,4,9738,3140,0,12,1],
["p1",8,"op","chess_char_5_diy2_a",1,null,1359,1,5,3,28459,0,0,52,0],
["p1",9,"op","chess_char_5_diy1_a",2,null,1359,1,176,0,49348,1359,0,39,2],
["p1",10,"op","chess_char_5_diy2_b",0,"none",0,0,181,4,14787,3140,0,38,3],
["p1",11,"op","chess_char_5_diy1_b",1,"none",0,0,174,1,9156,3140,0,21,4],
["p1",12,"op","chess_char_5_diy2_b",2,"none",0,0,141,4,11236,3140,0,12,1],
["-","~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],
["p1","~1","token","token_10024_ebnhlz_rcube",null,null,1000,0,37,0,2623,0,0,0,null],
["p1","~2","token","token_10024_ebnhlz_rcube",null,null,1000,0,53,0,1,0,0,0,null],
["p1","~3","token","token_10024_ebnhlz_rcube",null,null,1000,0,71,0,1572,0,0,0,null],
["p1","~4","token","token_10024_ebnhlz_rcube",null,null,1000,0,83,0,0,0,0,0,null]
["p1","~1","token","token_10024_ebnhlz_rcube",null,null,1000,0,37,0,1572,0,0,0,null],
["p1","~2","token","token_10024_ebnhlz_rcube",null,null,1000,0,52,0,0,0,0,0,null],
["p1","~3","token","token_10024_ebnhlz_rcube",null,null,1000,0,67,0,6859,0,0,0,null],
["p1","~4","token","token_10024_ebnhlz_rcube",null,null,1000,0,81,0,4195,0,0,0,null]
],
"enemies": {
"enemy_1197_sfshu": [15,11,4,2272,51823],
"enemy_1197_sfshu_2": [39,21,18,6413,151033],
"enemy_1198_msfshu": [33,26,7,0,81],
"enemy_1198_msfshu_2": [63,54,9,0,225],
"enemy_9010_acpupp": [39,12,27,16255,412992]
"enemy_1197_sfshu": [15,10,5,1799,50834],
"enemy_1197_sfshu_2": [39,20,19,6094,139516],
"enemy_1198_msfshu": [30,26,4,0,79],
"enemy_1198_msfshu_2": [60,54,6,0,217],
"enemy_9010_acpupp": [39,11,28,18930,401042]
},
"hooks": [1,218,6170,550,550,2484,2286,0,140,209,72,69,61,11555,18,37,189,65,1,153,0,0,0],
"events": {"atk":913,"deploy":26,"die":144,"dmg":2286,"engage":11,"fx":143,"leak":65,"skill":141,"spawn":208,"status":408},
"fx": {"aoe":4,"dash":3,"displace":8,"ember":13,"pull":8,"shieldBreak":37,"summon":36,"takeoff":9,"telegraph":13,"volley":12},
"snaps": "97d774f4 d56f2c40 38cfa54f 7e2be674 45424794 b549bc6d d02f3886 8eef35d8 186b734d ef22c4fe 6eed958f 1c82384a 2d257b7e e4c0bf84 b322c2f5 561c30ac c139ed4b 0f61007b e04f8bf8 c8e87b59 3c8fbdd4"
"hooks": [1,212,6170,507,507,2408,2252,0,138,204,19,17,61,12292,18,39,183,62,1,150,0,0,0],
"events": {"atk":827,"deploy":26,"die":142,"dmg":2252,"engage":11,"fx":136,"leak":62,"skill":36,"spawn":202,"status":382},
"fx": {"aoe":4,"dash":3,"displace":8,"ember":12,"pull":8,"revive":1,"shieldBreak":28,"summon":34,"takeoff":9,"telegraph":12,"volley":17},
"snaps": "97d774f4 3a87e9c0 6315b127 d1ff957b 8b0cf599 ffcafc10 f97c63e0 b090bfcf 503cb562 30e78f94 453e3e4b 5c62e222 794d1210 f8da69f3 40109745 bfd2d8ad 9529555d def80e98 4395baef ad6ed566 87adb778"
},
"diy-115": {
"about": "5_diy1_b=ebnhlz/S1/002_ebnhlz 5_diy2_b=ebnhlz/S2/002_ebnhlz 5_diy1_b=ebnhlz/S3/002_ebnhlz 5_diy2_b=ebnhlz/S1/003_ebnhlz 5_diy1_b=ebnhlz/S2/003_ebnhlz 5_diy2_b=ebnhlz/S3/003_ebnhlz 5_diy1_b=ebnhlz/S1/004_ebnhlz 5_diy2_b=ebnhlz/S2/004_ebnhlz 5_diy1_b=ebnhlz/S3/004_ebnhlz 6_diy1_a=ebnhlz/S1 6_diy2_a=ebnhlz/S2 6_diy1_a=ebnhlz/S3",
@@ -4916,59 +4916,61 @@
"round": 12,
"seed": 2479968306,
"waveId": "act1autochess_h05",
"time": 193.8,
"ticks": 5814,
"time": 193.6,
"ticks": 5808,
"reason": "cleared",
"killed": 195,
"total": 246,
"killed": 197,
"total": 243,
"unspawned": 0,
"bossHpLeft": null,
"rngDraws": 0,
"errors": {"count":0,"kinds":[]},
"players": {"p1":{"killed":195,"total":246,"perfect":false,"leaks":51,"leaksUncounted":0,"coins":0,"dmg":515319,"bossDmg":0,"heal":0,"deaths":9,"layerGains":{}}},
"players": {"p1":{"killed":197,"total":243,"perfect":false,"leaks":46,"leaksUncounted":0,"coins":0,"dmg":532641,"bossDmg":0,"heal":0,"deaths":8,"layerGains":{}}},
"units": [
["p1",1,"op","chess_char_5_diy1_b",0,"uniequip_002_ebnhlz",1570,1,10,7,61901,0,0,45,5],
["p1",2,"op","chess_char_5_diy2_b",1,"uniequip_002_ebnhlz",1570,1,11,9,35088,0,0,28,25],
["p1",3,"op","chess_char_5_diy1_b",2,"uniequip_002_ebnhlz",1570,1,1,9,12719,0,0,24,4],
["p1",4,"op","chess_char_5_diy2_b",0,"uniequip_003_ebnhlz",1650,1,3,21,55599,0,0,72,7],
["p1",5,"op","chess_char_5_diy1_b",1,"uniequip_003_ebnhlz",1650,1,5,7,56916,0,0,60,33],
["p1",6,"op","chess_char_5_diy2_b",2,"uniequip_003_ebnhlz",1650,1,7,12,124221,0,0,54,4],
["p1",2,"op","chess_char_5_diy2_b",1,"uniequip_002_ebnhlz",1570,1,11,9,33720,0,0,27,0],
["p1",3,"op","chess_char_5_diy1_b",2,"uniequip_002_ebnhlz",1570,1,1,11,16041,0,0,24,4],
["p1",4,"op","chess_char_5_diy2_b",0,"uniequip_003_ebnhlz",1650,1,3,15,56353,0,0,77,7],
["p1",5,"op","chess_char_5_diy1_b",1,"uniequip_003_ebnhlz",1650,1,5,10,52596,0,0,60,6],
["p1",6,"op","chess_char_5_diy2_b",2,"uniequip_003_ebnhlz",1650,1,7,13,127550,0,0,51,4],
["p1",7,"op","chess_char_5_diy1_b",0,"uniequip_004_ebnhlz",1570,1,9,0,0,0,0,0,3],
["p1",8,"op","chess_char_5_diy2_b",1,"uniequip_004_ebnhlz",1570,1,12,6,63692,0,0,49,11],
["p1",9,"op","chess_char_5_diy1_b",2,"uniequip_004_ebnhlz",0,0,194,2,8623,3140,0,8,2],
["p1",10,"op","chess_char_6_diy1_a",0,null,0,0,172,10,12844,2718,0,33,2],
["p1",11,"op","chess_char_6_diy2_a",1,null,1025.48,1,275,3,14668,3052,0,17,7],
["p1",12,"op","chess_char_6_diy1_a",2,null,0,0,269,0,16023,4077,0,12,1],
["p1","~1","token","token_10024_ebnhlz_rcube",null,null,1000,0,29,0,10534,0,0,0,null],
["p1","~2","token","token_10024_ebnhlz_rcube",null,null,1000,0,32,0,0,0,0,0,null],
["p1","~3","token","token_10024_ebnhlz_rcube",null,null,1000,0,56,0,7762,0,0,0,null],
["p1","~4","token","token_10024_ebnhlz_rcube",null,null,1000,0,78,1,4611,0,0,0,null],
["p1","~5","token","token_10024_ebnhlz_rcube",null,null,1000,0,87,0,0,0,0,0,null],
["p1","~6","token","token_10024_ebnhlz_rcube",null,null,1000,0,106,0,7762,0,0,0,null],
["p1","~7","token","token_10024_ebnhlz_rcube",null,null,1000,0,128,0,0,0,0,0,null],
["p1","~8","token","token_10024_ebnhlz_rcube",null,null,1000,0,133,0,2772,0,0,0,null],
["p1","~9","token","token_10024_ebnhlz_rcube",null,null,1000,0,150,0,2219,0,0,0,null],
["p1","~10","token","token_10024_ebnhlz_rcube",null,null,1000,0,162,0,0,0,0,0,null],
["p1","~11","token","token_10024_ebnhlz_rcube",null,null,1000,0,169,1,4611,0,0,0,null],
["p1","~12","token","token_10024_ebnhlz_rcube",null,null,1000,0,197,0,2218,0,0,0,null],
["p1","~13","token","token_10024_ebnhlz_rcube",null,null,1000,0,219,0,0,0,0,0,null],
["p1","~14","token","token_10024_ebnhlz_rcube",null,null,1000,0,220,0,2772,0,0,0,null],
["p1","~15","token","token_10024_ebnhlz_rcube",null,null,1000,0,240,0,2776,0,0,0,null],
["p1","~16","token","token_10024_ebnhlz_rcube",null,null,1000,1,254,0,0,0,0,0,null],
["p1","~17","token","token_10024_ebnhlz_rcube",null,null,1000,0,256,0,4990,0,0,0,null]
["p1",8,"op","chess_char_5_diy2_b",1,"uniequip_004_ebnhlz",1570,1,12,8,66486,0,0,49,13],
["p1",9,"op","chess_char_5_diy1_b",2,"uniequip_004_ebnhlz",0,0,225,5,6116,3140,0,10,2],
["p1",10,"op","chess_char_6_diy1_a",0,null,0,0,164,8,12174,2718,0,31,2],
["p1",11,"op","chess_char_6_diy2_a",1,null,1025.48,1,275,5,13604,3052,0,16,0],
["p1",12,"op","chess_char_6_diy1_a",2,null,81.61,1,270,2,15684,3995,0,14,1],
["p1","~1","token","token_10024_ebnhlz_rcube",null,null,1000,0,29,0,0,0,0,0,null],
["p1","~2","token","token_10024_ebnhlz_rcube",null,null,1000,0,30,1,12752,0,0,0,null],
["p1","~3","token","token_10024_ebnhlz_rcube",null,null,1000,0,55,0,5544,0,0,0,null],
["p1","~4","token","token_10024_ebnhlz_rcube",null,null,1000,0,70,0,4990,0,0,0,null],
["p1","~5","token","token_10024_ebnhlz_rcube",null,null,1000,0,72,0,0,0,0,0,null],
["p1","~6","token","token_10024_ebnhlz_rcube",null,null,1000,0,92,0,4990,0,0,0,null],
["p1","~7","token","token_10024_ebnhlz_rcube",null,null,1000,0,122,0,12197,0,0,0,null],
["p1","~8","token","token_10024_ebnhlz_rcube",null,null,1000,0,125,0,0,0,0,0,null],
["p1","~9","token","token_10024_ebnhlz_rcube",null,null,1000,0,138,0,2772,0,0,0,null],
["p1","~10","token","token_10024_ebnhlz_rcube",null,null,1000,0,155,0,2221,0,0,0,null],
["p1","~11","token","token_10024_ebnhlz_rcube",null,null,1000,0,160,0,0,0,0,0,null],
["p1","~12","token","token_10024_ebnhlz_rcube",null,null,1000,0,171,0,4990,0,0,0,null],
["p1","~13","token","token_10024_ebnhlz_rcube",null,null,1000,0,204,0,9425,0,0,0,null],
["p1","~14","token","token_10024_ebnhlz_rcube",null,null,1000,0,216,0,0,0,0,0,null],
["p1","~15","token","token_10024_ebnhlz_rcube",null,null,1000,0,223,0,2772,0,0,0,null],
["p1","~16","token","token_10024_ebnhlz_rcube",null,null,1000,0,243,0,2776,0,0,0,null],
["p1","~17","token","token_10024_ebnhlz_rcube",null,null,1000,1,254,0,0,0,0,0,null],
["p1","~18","token","token_10024_ebnhlz_rcube",null,null,1000,0,257,0,4990,0,0,0,null],
["p1","~19","token","token_10024_ebnhlz_rcube",null,null,1000,0,272,0,0,0,0,0,null]
],
"enemies": {
"enemy_1195_sfyin": [45,24,21,8753,152906],
"enemy_1196_msfyin": [48,44,4,0,90],
"enemy_1197_sfshu": [39,30,9,4234,206523],
"enemy_1198_msfshu": [90,76,14,0,242],
"enemy_1195_sfyin": [45,30,15,8741,173581],
"enemy_1196_msfyin": [60,51,9,0,105],
"enemy_1197_sfshu": [39,25,14,4164,201605],
"enemy_1198_msfshu": [75,70,5,0,216],
"enemy_1199_sfjin": [12,12,0,0,186325],
"enemy_1200_msfjin": [12,9,3,0,348]
"enemy_1200_msfjin": [12,9,3,0,346]
},
"hooks": [1,281,5814,450,450,1977,2088,0,204,271,104,102,0,27867,0,31,246,51,1,204,0,0,0],
"events": {"atk":450,"deploy":35,"die":220,"dmg":2088,"engage":11,"fx":189,"leak":51,"skill":206,"spawn":275},
"fx": {"aoe":11,"displace":13,"pull":13,"summon":83,"volley":69},
"snaps": "b588f908 018cc7d1 02df24b0 d7fb7008 01901fca 88a112ed f0544f8d 91caefd2 24dd8e93 26798334 2b5c19c3 091cb2b8 45da698c 1d8e5f22 91d224aa a413c6ff af6b4e5f d69eff16 da950540 179fa098"
"hooks": [1,280,5808,450,450,1944,2063,0,205,269,47,45,0,28772,0,29,243,46,1,205,0,0,0],
"events": {"atk":450,"deploy":37,"die":223,"dmg":2063,"engage":11,"fx":197,"leak":46,"skill":92,"spawn":274},
"fx": {"aoe":13,"displace":15,"pull":15,"summon":86,"volley":68},
"snaps": "b588f908 30b58fc4 0067aae8 073e6898 0cbd5145 a0736062 6e599248 f14345d4 7c4901d1 2f52111e a8cc7280 ac1fd796 f60de3a9 9b4b7177 cc02ceba e6974a52 cf27fc35 a4a00c5a a7501807 6a48f2bc"
},
"diy-116": {
"about": "6_diy1_b=ebnhlz/S1 6_diy2_b=ebnhlz/S2 6_diy1_b=ebnhlz/S3 6_diy2_b=ebnhlz/S1/002_ebnhlz 6_diy1_b=ebnhlz/S2/002_ebnhlz 6_diy2_b=ebnhlz/S3/002_ebnhlz 6_diy1_b=ebnhlz/S1/003_ebnhlz 6_diy2_b=ebnhlz/S2/003_ebnhlz 6_diy1_b=ebnhlz/S3/003_ebnhlz 6_diy2_b=ebnhlz/S1/004_ebnhlz 6_diy1_b=ebnhlz/S2/004_ebnhlz 6_diy2_b=ebnhlz/S3/004_ebnhlz",
@@ -4986,31 +4988,32 @@
"total": 123,
"unspawned": 0,
"bossHpLeft": null,
"rngDraws": 5,
"rngDraws": 6,
"errors": {"count":0,"kinds":[]},
"players": {"p1":{"killed":1,"total":123,"perfect":false,"leaks":122,"leaksUncounted":0,"coins":0,"dmg":271272,"bossDmg":0,"heal":0,"deaths":19,"layerGains":{}}},
"players": {"p1":{"killed":1,"total":123,"perfect":false,"leaks":122,"leaksUncounted":0,"coins":0,"dmg":286822,"bossDmg":0,"heal":0,"deaths":19,"layerGains":{}}},
"units": [
["p1",1,"op","chess_char_6_diy1_b",0,"none",1570,1,147,0,23015,3140,0,31,2],
["p1",2,"op","chess_char_6_diy2_b",1,"none",0,0,123,0,19192,3140,0,10,1],
["p1",3,"op","chess_char_6_diy1_b",2,"none",1570,1,134,0,52931,1570,0,26,2],
["p1",4,"op","chess_char_6_diy2_b",0,"uniequip_002_ebnhlz",0,0,146,0,15092,3140,0,15,1],
["p1",5,"op","chess_char_6_diy1_b",1,"uniequip_002_ebnhlz",0,0,82,0,13594,3140,0,7,1],
["p1",6,"op","chess_char_6_diy2_b",2,"uniequip_002_ebnhlz",0,0,78,0,9982,3140,0,6,0],
["p1",7,"op","chess_char_6_diy1_b",0,"uniequip_003_ebnhlz",0,0,74,0,14427,3490,0,4,0],
["p1",8,"op","chess_char_6_diy2_b",1,"uniequip_003_ebnhlz",0,0,7,0,14109,1745,0,5,1],
["p1",9,"op","chess_char_6_diy1_b",2,"uniequip_003_ebnhlz",0,0,9,0,19195,1745,0,7,1],
["p1",10,"op","chess_char_6_diy2_b",0,"uniequip_004_ebnhlz",0,0,79,0,8532,3140,0,4,0],
["p1",11,"op","chess_char_6_diy1_b",1,"uniequip_004_ebnhlz",0,0,4,1,20024,1570,0,6,1],
["p1",12,"op","chess_char_6_diy2_b",2,"uniequip_004_ebnhlz",0,0,6,0,34442,1570,0,6,1],
["p1","~1","token","token_10024_ebnhlz_rcube",null,null,1000,0,27,0,15400,0,0,0,null],
["p1","~2","token","token_10024_ebnhlz_rcube",null,null,1000,0,28,0,4454,0,0,0,null],
["p1","~3","token","token_10024_ebnhlz_rcube",null,null,1000,0,29,0,6883,0,0,0,null]
["p1",1,"op","chess_char_6_diy1_b",0,"none",1570,1,148,1,25031,3140,0,31,2],
["p1",2,"op","chess_char_6_diy2_b",1,"none",0,0,124,0,18799,3140,0,10,2],
["p1",3,"op","chess_char_6_diy1_b",2,"none",1570,1,135,0,49295,1570,0,24,2],
["p1",4,"op","chess_char_6_diy2_b",0,"uniequip_002_ebnhlz",0,0,147,0,16828,3140,0,16,1],
["p1",5,"op","chess_char_6_diy1_b",1,"uniequip_002_ebnhlz",0,0,83,0,13594,3140,0,7,1],
["p1",6,"op","chess_char_6_diy2_b",2,"uniequip_002_ebnhlz",0,0,79,0,9982,3140,0,6,0],
["p1",7,"op","chess_char_6_diy1_b",0,"uniequip_003_ebnhlz",0,0,75,0,14427,3490,0,4,0],
["p1",8,"op","chess_char_6_diy2_b",1,"uniequip_003_ebnhlz",0,0,7,0,16808,1745,0,7,0],
["p1",9,"op","chess_char_6_diy1_b",2,"uniequip_003_ebnhlz",0,0,9,0,22161,1745,0,7,1],
["p1",10,"op","chess_char_6_diy2_b",0,"uniequip_004_ebnhlz",0,0,80,0,8532,3140,0,4,0],
["p1",11,"op","chess_char_6_diy1_b",1,"uniequip_004_ebnhlz",0,0,4,0,18212,1570,0,4,1],
["p1",12,"op","chess_char_6_diy2_b",2,"uniequip_004_ebnhlz",0,0,6,0,39389,1570,0,8,1],
["p1","~1","token","token_10024_ebnhlz_rcube",null,null,1000,0,26,0,4454,0,0,0,null],
["p1","~2","token","token_10024_ebnhlz_rcube",null,null,1000,0,27,0,17360,0,0,0,null],
["p1","~3","token","token_10024_ebnhlz_rcube",null,null,1000,0,28,0,4876,0,0,0,null],
["p1","~4","token","token_10024_ebnhlz_rcube",null,null,1000,0,37,0,7074,0,0,0,null]
],
"enemies": {"enemy_1006_shield_3":[21,0,21,8166,127088],"enemy_1043_zomsbr":[66,1,65,14521,60428],"enemy_1402_tgshd_2":[36,0,36,7843,83756]},
"hooks": [1,147,6528,189,189,333,355,10424,20,145,11,11,0,8727,0,21,123,122,1,20,0,1,0],
"events": {"atk":189,"deploy":24,"die":23,"dmg":355,"engage":12,"fx":96,"leak":122,"skill":22,"spawn":138,"status":36},
"fx": {"aoe":3,"burst":1,"displace":5,"expose":67,"pull":5,"summon":3,"volley":12},
"snaps": "389ca6e3 c8f155a4 e2e7a3b2 2f4c8838 6a9c72f0 8c585b7e a26f5d0c 80f56fed a04d35ab 88374c55 043f03c3 acc9e8b4 6dc5a029 a28ee86b d72cad57 77ed9536 4cd333ad 94a7e729 29475fd8 b7079863 f08523df a6844f3a"
"enemies": {"enemy_1006_shield_3":[21,0,21,8025,133387],"enemy_1043_zomsbr":[66,1,65,13522,62006],"enemy_1402_tgshd_2":[36,0,36,8983,91429]},
"hooks": [1,148,6528,187,187,341,362,10129,20,146,11,11,0,8777,0,22,123,122,1,20,0,1,0],
"events": {"atk":187,"deploy":25,"die":24,"dmg":362,"engage":12,"fx":108,"leak":122,"skill":22,"spawn":139,"status":38},
"fx": {"aoe":4,"burst":1,"displace":6,"expose":74,"pull":6,"summon":4,"volley":13},
"snaps": "389ca6e3 d4a0046f e8e318e4 2dfb6564 d6b9ac5b 05f87e6d 4fddc6c0 abdaf56e 564d85ec f523de7f 8fc91296 e8062bef a97ba650 2328edb5 b076db9a 504c2000 80dda69d 2e369d1e 56349199 70fdf2ec 97f6afb9 059a1cef"
},
"diy-117": {
"about": "5_diy1_a=mgllan/S1 5_diy2_a=mgllan/S2 5_diy1_a=mgllan/S3 5_diy2_b=mgllan/S1 5_diy1_b=mgllan/S2 5_diy2_b=mgllan/S3 5_diy1_b=mgllan/S1/002_mgllan 5_diy2_b=mgllan/S2/002_mgllan 5_diy1_b=mgllan/S3/002_mgllan 5_diy2_b=mgllan/S1/003_mgllan 5_diy1_b=mgllan/S2/003_mgllan 5_diy2_b=mgllan/S3/003_mgllan",