From ac4231846ffcaa28538999faf781fbaa21dd6dbb Mon Sep 17 00:00:00 2001 From: sganggs Date: Thu, 8 Oct 2026 21:53:51 +0800 Subject: [PATCH 1/2] =?UTF-8?q?feedback7=20R22-LATE:=20=E7=94=BB=E5=8D=B7?= =?UTF-8?q?=20never=20puts=20the=20copied=20items=20on=20the=20copy=20?= =?UTF-8?q?=E2=80=94=20they=20are=20gained=20unequipped=20into=20the=20han?= =?UTF-8?q?d=20/=20temp=20like=20any=20item;=20golden:=20unchanged?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PRTS 卫戍协议:盟约 PRTS盟约记录, 法术编纂集, 画卷 备注: 「选择策略<夕>时可获得
使用后销毁,获得的装备为未装备状态」. Without a promotion the 画卷 handler still equipped every copied item that did not merge (an advanced item, a 变形同构体) onto the copy in the hand (the promotion case was fixed for #389). Now each copied item is only gained (ctx.grantItem → acquireItem): the hand, overflow temp, and with both full it is destroyed with the usual toast 「整备区已满,获得的装备已销毁」, as for any gained item. A copied normal item that completes a pair still merges at once (the golden in the hand), and the copy itself still follows the chess gain rules (a full hand and temp refuse the scroll: HAND_FULL, the scroll kept). Full-hand check: a full hand with 3 free temp slots holds the copy and both copied advanced items; with 2 free slots the copy and one item fit and the other is destroyed with the toast (before, both rode on the copy). Docs: META.md (Arts list), research/04-items.md (画卷 copy). The content test that pinned the old behaviour (test/content/items.test.js: 变形同构体 "the copy wears it too") now expects it in the hand. Tests: test/match/scroll-copy-merge.test.js +3 (no promotion, normal and elite targets with advanced items; the full hand at 3 / 2 free temp slots) — all 3 fail on the parent; every test mentioning 画卷: 177 pass. Golden unchanged. --- docs/META.md | 2 +- docs/research/04-items.md | 2 +- server/sim/content/items/meta.js | 21 ++++++-------- test/content/items.test.js | 7 +++-- test/match/scroll-copy-merge.test.js | 41 ++++++++++++++++++++++++++++ 5 files changed, 56 insertions(+), 17 deletions(-) diff --git a/docs/META.md b/docs/META.md index e685fdee..03966198 100644 --- a/docs/META.md +++ b/docs/META.md @@ -458,7 +458,7 @@ bilibili BV1vzyVBuEN9 ≈ 8:24 / BV1Qkw1zMEoR ≈ 7:25, pointed out in PR #2 — is not consumed: PRTS 下半 记录 备注 "生效时,原干员销毁,获得一名高一阶的随机初始干员(最高六阶)", PRTS 卫戍协议/帮助 "佩戴的 装备无法手动卸除,在失去该干员(干员出售、销毁、合并等)…时自动卸除", players re-inject it every round; player feedback after 0.1.0), 画卷 (copy the operator in range with its -items), 教鞭 / “神秘顾客” (a random bounty is added). +items — the copied items arrive unequipped in the hand, PRTS 画卷 备注 "获得的装备为未装备状态"), 教鞭 / “神秘顾客” (a random bounty is added). **教鞭 / “神秘顾客” stay a random bounty (deliberate).** The official Arts open a personal 悬赏 choice ("选择一项(特殊)悬赏任务进行挑战", `choice_event hunter_band_1`). The server applies a random bounty instead: content diff --git a/docs/research/04-items.md b/docs/research/04-items.md index 9d8c1530..740a78d3 100644 --- a/docs/research/04-items.md +++ b/docs/research/04-items.md @@ -352,7 +352,7 @@ Combo check: `equip_chess_id` in blackboard is the partner's id WITHOUT the `_a/ - Buff keys: 画卷 `trap_copy_front_char{}`; 教鞭 `trap_create_self_choice{choice_event=hunter_band_1}`; 神秘顾客 additionally `trap_disney_special{count=1}`. - `hunter_band_1` (choiceType PERSONAL_CHOOSE, "悬赏决策") pool is server-side. [ASSUMED] offer 3 random `enemyeffect_b_*` bounties (e.g. 碎骨·悬赏 +1, 萨卡兹百夫长·悬赏 +2, 泥岩·悬赏 +4, 锏·悬赏 +5, “复仇者”·悬赏 +6 funds; buff `add_enemy_kill_gain_coin{count,enemy_id,coin,round=1}`): adds 1 enemy to your next battle, killer gets `coin` funds. -- 画卷 copy: duplicates the operator (same chess id incl. elite `_b`) AND clones its equipped items into the copy [DATA desc "包括精锐状态和装备"]; copy goes to hand [ASSUMED]; if hand full -> temporary hand. +- 画卷 copy: duplicates the operator (same chess id incl. elite `_b`) AND its equipped items [DATA desc "包括精锐状态和装备"]; the copied items arrive unequipped (PRTS 画卷 备注 "使用后销毁,获得的装备为未装备状态"), gained like any item — the hand, overflow temp (destroyed with the usual toast when both are full); copy goes to hand [ASSUMED]; if hand full -> temporary hand. ## 8. Item sources other than the shop [DATA] diff --git a/server/sim/content/items/meta.js b/server/sim/content/items/meta.js index ea90ac93..786dff53 100644 --- a/server/sim/content/items/meta.js +++ b/server/sim/content/items/meta.js @@ -116,12 +116,14 @@ export function registerMeta(registry) { })); } - // 画卷 — trap_copy_front_char: copy the operator in range (elite status included) with its equipment. A copied - // normal item that completes a pair with an owned one merges at once and the golden stays in the hand (research 04 - // addendum "两个同名道具(无论是否被装备)会自动合并…并自动返回整备区"); the built-in equipped that golden on the copy. - // A copy that completes a three-copy merge (GitHub #389, PR #390): the elite wears nothing — the promotion returns the - // copies' equipment to the hand (PRTS 帮助 "在失去该干员(…合并等)…时自动卸除") — and the copied items stay in the hand - // too (PRTS 画卷 备注 "获得的装备为未装备状态"), a copied normal item merging with the returned original. + // 画卷 — trap_copy_front_char: copy the operator in range (elite status included) and its equipment. The copied items + // are gained unequipped, like any gained item — the hand, overflow temp, destroyed with the usual toast when both are + // full — never put on the copy (PRTS 画卷 备注 "使用后销毁,获得的装备为未装备状态"; until 0.2.2 a copied item that did + // not merge was equipped onto the copy). A copied normal item that completes a pair with an owned one merges at once, + // the golden in the hand (research 04 addendum "两个同名道具(无论是否被装备)会自动合并…并自动返回整备区"). A copy that + // completes a three-copy merge (GitHub #389, PR #390): the promotion returns the copies' equipment to the hand too + // (PRTS 帮助 "在失去该干员(…合并等)…时自动卸除"), so the elite wears nothing and a copied normal item merges with the + // returned original. wrap(registry, 'chess_item_6_02_m', () => ({ onArt(ctx, ev) { const target = (ev.targets || []).find((p) => p && p.kind === 'chess'); @@ -132,12 +134,7 @@ export function registerMeta(registry) { const itemIds = (target.items || []).map((it) => it.id); const copy = ctx.grantChess(target.id, { requirePool: false, source: 'item:chess_item_6_02_m' }); if (!copy) { ev.error = 'HAND_FULL'; return; } - const promoted = copy.id !== target.id; - for (const itemId of itemIds) { - const got = ctx.grantItem(itemId, { source: 'item:chess_item_6_02_m' }); - const holder = got && !promoted ? ctx.piece(copy.uid) : null; - if (got && got.id === itemId && holder && holder.kind === 'chess') ctx.equipDirect(got.uid, holder.uid); - } + for (const itemId of itemIds) ctx.grantItem(itemId, { source: 'item:chess_item_6_02_m' }); }, })); diff --git a/test/content/items.test.js b/test/content/items.test.js index 6762f225..2a23cb79 100644 --- a/test/content/items.test.js +++ b/test/content/items.test.js @@ -1121,10 +1121,11 @@ test('画卷 (Art): copies the operator on the tile / in front with its elite st const copy = ps.hand.find((p) => p && p.kind === 'chess'); assert.equal(copy && copy.id, DATA.chess[cid].goldenId, 'elite copy in the hand'); // the copied 激光发射器 pairs with the original's (items merge "无论是否被装备") ⇒ the golden goes to the hand; - // 变形同构体 never merges ⇒ the copy wears it too - assert.deepEqual(copy.items.map((x) => x.id), [A('6_09')]); + // 变形同构体 never merges ⇒ its copy waits in the hand too, unequipped (PRTS 画卷 备注 "获得的装备为未装备状态"; + // until 0.2.2 the copy wore it) + assert.deepEqual(copy.items.map((x) => x.id), [], 'the copy wears nothing'); assert.deepEqual(ps.find(target.uid).piece.items.map((x) => x.id), [A('6_09')]); - assert.deepEqual(handIds(ps, 'item'), [B('3_03')], 'merged golden in the hand (regression: was equipped on the copy)'); + assert.deepEqual(handIds(ps, 'item').slice().sort(), [B('3_03'), A('6_09')].sort(), 'the merged golden and the copied 变形同构体 in the hand'); const art2 = giveItem(m, ps, 'chess_item_6_02_m'); assert.equal(m.handle('p_0', { t: 'g.art', itemUid: art2.uid, row: 11, col: 7 }).error, 'BAD_TARGET', 'no operator in range'); cover('chess_item_6_02_m'); diff --git a/test/match/scroll-copy-merge.test.js b/test/match/scroll-copy-merge.test.js index ca4a597c..795b38e6 100644 --- a/test/match/scroll-copy-merge.test.js +++ b/test/match/scroll-copy-merge.test.js @@ -111,3 +111,44 @@ test('Picture Scroll: a full hand and temp without promotion keeps the refused s assert.deepEqual(ps.privateView(), before); h.invariants(); }); + +// PRTS 画卷 备注 「使用后销毁,获得的装备为未装备状态」: without a promotion too, the copied items are gained like any item — +// the hand, overflow temp — and never put on the copy (until 0.2.2 a copy that did not merge was equipped onto it) +const ADV = [HAMMER, SHIELD].map((id) => id.replace(/_a$/, '_b')); +const looseItems = (ps) => [...ps.hand, ...ps.temp].filter((p) => p?.kind === 'item').map((p) => p.id).sort(); +for (const golden of [false, true]) { + test(`Picture Scroll: one ${golden ? 'elite' : 'normal'} target — the copied (advanced) items arrive unequipped in the hand`, (t) => { + const { h, m, ps, target, cast } = prep(t, { copies: 1, golden, items: ADV }); + assert.deepEqual(cast(), OK); + const copy = ps.allChess().find((p) => p.id === target.id && p !== target); + assert.ok(copy, 'the copy was gained'); + assert.deepEqual(copy.items, [], 'the copy wears nothing'); + assert.deepEqual(target.items.map((p) => p.id).sort(), [...ADV].sort(), 'the target keeps its own'); + assert.deepEqual(looseItems(ps), [...ADV].sort(), 'the copied items wait in the hand'); + assert.equal(m.gd.chess(copy.id).isGolden, golden); + h.invariants(); + }); +} + +test('Picture Scroll: a full hand — the copy and its items overflow into temp; an item with no slot left is destroyed like any gained item', (t) => { + for (const free of [3, 2]) { + const { h, ps, target, cast } = prep(t, { copies: 1, items: ADV }); + while (ps.hand.some((p) => p == null)) assert.ok(ps.acquireItem(FILLER)); + while (ps.temp.filter((p) => p == null).length > free) assert.ok(ps.acquireItem(FILLER)); + const toasts = () => h.allTo('p_0', 'm.toast').map((x) => JSON.stringify(x)); + const before = toasts().length; + assert.deepEqual(cast(), OK); + const copy = ps.allChess().find((p) => p.id === target.id && p !== target); + const where = copy ? ps.find(copy.uid)?.area : null; + assert.ok(where === 'temp' || where === 'hand', `free ${free}: the copy was gained into temp (the hand fills from temp once the scroll left)`); + assert.deepEqual(copy.items, [], `free ${free}: the copy wears nothing`); + assert.deepEqual(target.items.map((p) => p.id).sort(), [...ADV].sort()); + const got = looseItems(ps).filter((id) => id !== FILLER); + if (free === 3) assert.deepEqual(got, [...ADV].sort(), 'room for the copy and both items'); + else { + assert.equal(got.length, 1, 'room for the copy and one item: the other is destroyed'); + assert.ok(toasts().slice(before).some((s) => s.includes('整备区已满,获得的装备已销毁')), 'with the usual toast'); + } + h.invariants(); + } +}); From 03688c82977842c6c52251eca407a4466c637994 Mon Sep 17 00:00:00 2001 From: sganggs Date: Thu, 8 Oct 2026 21:57:48 +0800 Subject: [PATCH 2/2] =?UTF-8?q?feedback7=20R22-LATE:=20=E5=BC=95=E6=98=9F?= =?UTF-8?q?=E6=A3=98=E5=88=BA=20S1=20=E5=BA=A6=E7=AE=97=E6=B5=AA=E6=B3=A2?= =?UTF-8?q?=20breaks=20an=20HP-ratio=20tie=20by=20the=20latest=20deploymen?= =?UTF-8?q?t;=20golden:=20roster-033,=20roster-034=20move?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PRTS 引星棘刺 技能1 度算浪波 备注: 「※优先选择生命比例最低>最晚部署的我方单位(不含装置职业单位)」. The kit took the ally with the lowest HP ratio but broke a tie by more blocking, then the nearer one, then the unit id. A tie now goes to the latest deployment (the highest deploySeq: a redeployed operator counts from its new deployment), the id last. 「不含装置职业单位」 was already met: alliesInGrid never returns a device. Golden: roster-033 (a normal 引星棘刺 with S1) and roster-034 (an elite one) move — at the start every ally is at full HP, so the first units now land on the latest deployed ally instead of the nearest one (033: killed 64 → 47, leaks 103 → 120; 034: 5_14_b damage taken 14691 → 11676 …). Tests: test/content/kits_alt_t5.test.js +1 (two allies at 50 %: the later deployment, though farther, gets the unit; a lower ratio still wins) — fails on the parent; all 引星棘刺 tests pass (9). --- .../kits/ops/chess_char_5_15-thorn2.js | 4 +- test/content/kits_alt_t5.test.js | 27 ++++++ test/golden/roster.json | 94 +++++++++---------- 3 files changed, 77 insertions(+), 48 deletions(-) diff --git a/server/sim/content/kits/ops/chess_char_5_15-thorn2.js b/server/sim/content/kits/ops/chess_char_5_15-thorn2.js index f2005cfa..7e016d5c 100644 --- a/server/sim/content/kits/ops/chess_char_5_15-thorn2.js +++ b/server/sim/content/kits/ops/chess_char_5_15-thorn2.js @@ -96,7 +96,9 @@ export default { // (GitHub #124 「引星棘刺一技能不会在满技力时自动释放」) trigger: { rule: 'SP_FULL' }, onStart({ battle, unit }) { - const t = battle.alliesInGrid(unit).filter((a) => a.hp > 0).sort((a, b) => a.hpRatio - b.hpRatio || b.blocking.length - a.blocking.length || dist(a, unit) - dist(b, unit) || a.id - b.id)[0]; + // PRTS 备注 「※优先选择生命比例最低>最晚部署的我方单位(不含装置职业单位)」: the lowest HP ratio, a tie to the + // latest deployment (alliesInGrid has no devices); until 0.2.2 a tie went to more blocking, then the nearer + const t = battle.alliesInGrid(unit).filter((a) => a.hp > 0).sort((a, b) => a.hpRatio - b.hpRatio || b.deploySeq - a.deploySeq || a.id - b.id)[0]; if (!t) return; const z = { type: 'guard', r: t.tileR, c: t.tileC, x: t.x, y: t.y, t: 0, acc: 0, dur: num(bb.projectile_delay_time, 6) + extend(battle, unit) }; (unit.mem.zones ??= []).push(z); diff --git a/test/content/kits_alt_t5.test.js b/test/content/kits_alt_t5.test.js index 066f6ac3..b88f73d3 100644 --- a/test/content/kits_alt_t5.test.js +++ b/test/content/kits_alt_t5.test.js @@ -1058,6 +1058,33 @@ test('引星棘刺 S1 度算浪波: two alchemy units on one ally add their DEF done(h); }); +test('引星棘刺 S1 度算浪波: at an HP-ratio tie the unit goes to the latest deployed ally (PRTS 备注 「优先选择生命比例最低>最晚部署的我方单位」)', () => { + for (const id of pair('15')) { + const h = run({ + defs: { chess: { t_first: ally('t_first'), t_last: ally('t_last') } }, + // t_first stands nearer to her, t_last deploys after it (until 0.2.2 a tie went to more blocking, then the nearer) + units: [entry(id, 'skchr_thorn2_1', { row: 10, col: 3 }), { chessId: 't_first', row: 11, col: 4 }, { chessId: 't_last', row: 9, col: 5 }], + enemies: [], + }); + const u = sel(h, id, 'skchr_thorn2_1'); + const first = h.unit('t_first'), last = h.unit('t_last'); + h.step(); + assert.ok(last.deploySeq > first.deploySeq, 't_last is the later deployment'); + first.hp = first.s.maxHp * 0.5; last.hp = last.s.maxHp * 0.5; + cast(h, u); + const z = u.mem.zones.find((x) => x.type === 'guard'); + assert.deepEqual([z.r, z.c], [9, 5], 'the latest deployed of the two at 50 %'); + // the lowest ratio still comes first + last.hp = last.s.maxHp; first.hp = first.s.maxHp * 0.4; + const n0 = u.skill.activations; + u.skill.gainSp(1000); + assert.ok(h.runUntil(() => u.skill.activations > n0, 15), 'cast again'); + const z2 = u.mem.zones.filter((x) => x.type === 'guard').at(-1); + assert.deepEqual([z2.r, z2.c], [11, 4], 'a lower ratio beats a later deployment'); + done(h); + } +}); + test('引星棘刺 S1 度算浪波 (AUTO): fires as soon as its SP is full, no enemy needed (GitHub #124)', () => { for (const id of pair('15')) { const h = run({ diff --git a/test/golden/roster.json b/test/golden/roster.json index 1b31793a..b4cee968 100644 --- a/test/golden/roster.json +++ b/test/golden/roster.json @@ -2017,64 +2017,64 @@ "round": 12, "seed": 3754088384, "waveId": "act1autochess_h05", - "time": 211.6, - "ticks": 6348, + "time": 218.83, + "ticks": 6565, "reason": "cleared", - "killed": 64, + "killed": 47, "total": 167, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 743, + "rngDraws": 474, "errors": {"count":0,"kinds":[]}, "players": { "p1": { - "killed": 64, + "killed": 47, "total": 167, "perfect": false, - "leaks": 103, + "leaks": 120, "leaksUncounted": 0, "coins": 2, - "dmg": 557616, + "dmg": 368976, "bossDmg": 0, - "heal": 70704, - "deaths": 22, - "layerGains": {"indomShip":65} + "heal": 52135, + "deaths": 28, + "layerGains": {"indomShip":20} } }, "units": [ - ["p1",1,"op","chess_char_5_11_a",0,null,3628.8,1,202,7,21979,14938,7385,45,7], - ["p1",2,"op","chess_char_5_19_a",0,null,3039.97,1,187,3,49875,12485,583,27,3], - ["p1",3,"op","chess_char_5_13_a",0,null,1688.93,1,164,14,171901,31272,434,62,2], - ["p1",4,"op","chess_char_5_14_a",0,null,1732,1,178,2,12009,13967,4721,36,4], - ["p1",5,"op","chess_char_5_06_b",0,"uniequip_003_etlchi",0,0,154,14,154449,14484,6617,36,9], - ["p1",6,"op","chess_char_5_17_a",0,null,2250,1,200,2,22144,18671,332,42,11], - ["p1",7,"op","chess_char_5_12_a",1,null,1381.61,1,3,3,14760,3280,625,14,3], - ["p1",8,"op","chess_char_5_15_a",0,null,926,1,4,4,32726,0,31335,138,41], - ["p1",9,"op","chess_char_5_20_a",0,null,1108,1,188,0,9556,4207,545,25,2], - ["p1",10,"op","chess_char_5_21_a",0,null,0,0,192,0,5581,8133,323,9,0], - ["p1",11,"op","chess_char_5_22_a",0,null,1237,1,5,14,60089,4530,155,94,4], - ["p1",12,"op","chess_char_5_23_a",0,null,1422,1,185,0,0,11350,17630,30,16], + ["p1",1,"op","chess_char_5_11_a",0,null,2073.56,1,199,5,23095,13739,7417,49,7], + ["p1",2,"op","chess_char_5_19_a",0,null,2282.43,1,200,6,57898,16657,205,29,3], + ["p1",3,"op","chess_char_5_13_a",0,null,2723.22,1,201,10,68452,11801,205,34,1], + ["p1",4,"op","chess_char_5_14_a",0,null,0,0,174,2,9395,6983,2049,27,3], + ["p1",5,"op","chess_char_5_06_b",0,"uniequip_003_etlchi",0,0,151,11,110341,13501,5755,28,7], + ["p1",6,"op","chess_char_5_17_a",0,null,2250,1,203,0,12679,31166,324,24,7], + ["p1",7,"op","chess_char_5_12_a",1,null,0,0,3,5,13312,2896,205,12,2], + ["p1",8,"op","chess_char_5_15_a",0,null,0,0,197,4,15326,1954,16704,63,20], + ["p1",9,"op","chess_char_5_20_a",0,null,0,0,166,0,5953,4317,228,15,1], + ["p1",10,"op","chess_char_5_21_a",0,null,0,0,185,0,4781,7890,180,8,0], + ["p1",11,"op","chess_char_5_22_a",0,null,1237,1,202,4,45835,1237,0,68,2], + ["p1",12,"op","chess_char_5_23_a",0,null,0,0,188,0,0,6936,18846,32,11], ["-","~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], - ["p1","~1","token","token_10015_dusk_drgn",null,null,1226.94,0,38,0,2547,787,17,8,null] + ["p1","~1","token","token_10015_dusk_drgn",null,null,1037.85,0,38,0,1910,976,17,6,null] ], "enemies": { - "enemy_1005_yokai_3": [1,0,1,5320,11751], - "enemy_1009_lurker": [72,19,53,789,144011], - "enemy_10159_mntrjn": [1,0,1,0,25020], - "enemy_1019_jshoot_2": [51,30,21,17762,168939], + "enemy_1005_yokai_3": [1,0,1,4470,9218], + "enemy_1009_lurker": [72,18,54,909,95221], + "enemy_10159_mntrjn": [1,0,1,0,25185], + "enemy_1019_jshoot_2": [51,21,30,17841,122795], "enemy_1118_lidbox_2": [1,1,0,39,14774], "enemy_1196_msfyin": [1,1,0,0,3], - "enemy_1252_lysytb_2": [1,0,1,206,12737], - "enemy_1364_spnaxe_2": [1,0,1,10239,9744], - "enemy_1404_msnip": [36,13,23,96816,214197], - "enemy_1516_jakill": [1,0,1,6933,2413], - "enemy_9011_acrefr": [1,0,1,0,5382] + "enemy_1252_lysytb_2": [1,0,1,304,7837], + "enemy_1364_spnaxe_2": [1,0,1,8971,8027], + "enemy_1404_msnip": [36,6,30,79966,128372], + "enemy_1516_jakill": [1,0,1,7554,5712], + "enemy_9011_acrefr": [1,0,1,0,2713] }, - "hooks": [1,202,6348,1215,1215,4186,4215,5403,86,190,102,100,0,30920,253,140,167,103,1,91,13,0,7], - "events": {"atk":1321,"bounty":1,"deploy":33,"die":87,"dmg":4129,"engage":12,"fx":185,"heal":720,"layer":13,"leak":103,"skill":202,"spawn":182,"status":389}, - "fx": {"aoe":4,"crit":8,"dodge":7,"dollEnd":3,"garrison":13,"healAoe":7,"hpShare":2,"palsy":2,"reborn":2,"revive":9,"shield":67,"sp":12,"substitute":5,"summon":1,"swap":2,"zone":41}, - "snaps": "0092f82c d956b3ce a0ea1881 5a64de8a 599b4202 2f6b144a 8a4b2d63 f4bc7bf0 d8f52b83 5247b31d 2e6c6f38 e0538118 c645338e 0523d4c6 bfb16991 a871f36d 24e1d3fa 4f310cd6 0b4b5914 a0261983 358e7016 ce3f7688" + "hooks": [1,203,6565,1004,1004,3305,3328,2470,75,196,64,63,0,21601,205,120,167,120,1,77,4,0,11], + "events": {"atk":1084,"bounty":1,"deploy":34,"die":76,"dmg":3278,"engage":12,"fx":97,"heal":418,"layer":4,"leak":120,"skill":127,"spawn":182,"status":251}, + "fx": {"aoe":3,"crit":2,"dodge":11,"dollEnd":1,"garrison":4,"healAoe":7,"hpShare":1,"palsy":1,"reborn":2,"revive":7,"shield":29,"sp":5,"substitute":2,"summon":1,"swap":1,"zone":20}, + "snaps": "0092f82c 10f6cd5a 79f24953 8778cb3f 5bc04332 6c3c9351 7f048832 5dfafc44 5eabad8d 751eb802 ba739a4c 544464f7 abaaec7c 6bd184b5 aca79702 894abaef 203b4092 1e473bac 4e053885 44ca1766 a54f5762 b9106885" }, "roster-034": { "about": "pass 1 band 6: chess_char_5_08_b chess_char_5_11_b chess_char_5_19_b chess_char_5_13_b chess_char_5_14_b chess_char_5_07_b chess_char_5_17_b chess_char_5_10_b chess_char_5_12_b chess_char_5_15_b chess_char_5_20_b chess_char_5_21_b", @@ -2094,18 +2094,18 @@ "bossHpLeft": null, "rngDraws": 619, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":82,"total":104,"perfect":false,"leaks":22,"leaksUncounted":0,"coins":6,"dmg":4801724,"bossDmg":0,"heal":98672,"deaths":1,"layerGains":{}}}, + "players": {"p1":{"killed":82,"total":104,"perfect":false,"leaks":22,"leaksUncounted":0,"coins":6,"dmg":4801724,"bossDmg":0,"heal":95286,"deaths":1,"layerGains":{}}}, "units": [ ["p1",1,"op","chess_char_5_08_b",0,"uniequip_003_horn",2381.35,1,7,25,1560529,36004,1132,96,83], - ["p1",2,"op","chess_char_5_11_b",0,"uniequip_003_demkni",4194.43,1,10,2,85198,10006,49858,194,31], - ["p1",3,"op","chess_char_5_19_b",0,"none",3682,1,11,5,218886,6726,577,124,5], + ["p1",2,"op","chess_char_5_11_b",0,"uniequip_003_demkni",3778.92,1,10,2,85198,10027,50152,194,31], + ["p1",3,"op","chess_char_5_19_b",0,"none",3682,1,11,5,218886,6749,688,124,5], ["p1",4,"op","chess_char_5_13_b",0,"uniequip_003_ghost2",3448.92,1,13,4,163179,14903,517,210,5], - ["p1",5,"op","chess_char_5_14_b",0,"none",3260.35,1,15,0,16840,14691,8936,217,16], + ["p1",5,"op","chess_char_5_14_b",0,"none",3260.35,1,15,0,16840,11676,6934,217,16], ["p1",6,"op","chess_char_5_07_b",0,"uniequip_003_surtr",2680,1,8,4,292063,15460,635,104,49], ["p1",7,"op","chess_char_5_17_b",0,"uniequip_003_f12yin",2337.47,1,100,6,203715,3444,325,86,35], ["p1",8,"op","chess_char_5_10_b",0,"uniequip_003_lisa",1470,1,4,5,177131,0,0,116,6], ["p1",9,"op","chess_char_5_12_b",1,"uniequip_003_dusk",1667,1,5,22,1559480,0,0,91,5], - ["p1",10,"op","chess_char_5_15_b",0,"none",1907.5,1,12,0,58039,0,36694,166,128], + ["p1",10,"op","chess_char_5_15_b",0,"none",1907.5,1,12,0,58039,0,34903,166,128], ["p1",11,"op","chess_char_5_20_b",0,"uniequip_003_aglina",1352,1,14,5,208929,1794,0,138,6], ["p1",12,"op","chess_char_5_21_b",0,"none",3330.35,1,6,4,257734,0,0,50,3], ["-","~1","device","trap_1105_accrate",null,null,100,0,1,0,0,0,0,0,null], @@ -2119,16 +2119,16 @@ "enemy_1165_duhond_2": [1,1,0,114,24767], "enemy_1204_msfhu": [1,1,0,0,12], "enemy_1288_duskls": [1,1,0,3189,30964], - "enemy_1381_winman": [27,23,4,7117,933397], - "enemy_1381_winman_2": [39,31,7,28243,1724781], - "enemy_1387_winshd": [30,22,5,53819,1942830], + "enemy_1381_winman": [27,23,4,7088,933397], + "enemy_1381_winman_2": [39,31,7,27104,1724781], + "enemy_1387_winshd": [30,22,5,52016,1942830], "enemy_1425_lrcmra_2": [1,0,1,1682,43433], "enemy_2009_csaudc": [1,0,1,0,14091] }, - "hooks": [1,120,6900,2592,2592,3942,3943,5375,83,102,372,368,0,35187,5677,97,104,18,1,84,0,0,6], - "events": {"atk":3006,"bounty":3,"deploy":13,"die":84,"dmg":3929,"engage":12,"fx":368,"heal":672,"leak":18,"skill":740,"spawn":119,"status":797}, + "hooks": [1,120,6900,2592,2592,3942,3943,5155,83,102,372,368,0,35187,5677,97,104,18,1,84,0,0,6], + "events": {"atk":3006,"bounty":3,"deploy":13,"die":84,"dmg":3929,"engage":12,"fx":368,"heal":649,"leak":18,"skill":740,"spawn":119,"status":797}, "fx": {"aoe":16,"crit":21,"dodge":6,"ember":1,"healAoe":31,"hpShare":5,"sp":140,"zone":148}, - "snaps": "de3bd2e2 9ce456ee bcde1796 81851dcd 51a35e80 50098249 40a84907 cbda70fd a91a07cd 50f01226 20db1b07 0b0c9a0a cee1a934 dc30669d 6b6d29b1 b0624ef2 f6a4355c 68c2d268 368b7d82 03af8242 2387ed85 0421556c d1e4bd7f" + "snaps": "de3bd2e2 be5ffcf3 ba9e1ffc 3ba9de3e 3da96118 ff4a3ebc c5e92a17 85066da3 2751fd4e 8c1f2e7f d432f52b 0e333c14 87acebfb 46b5bd60 bdec67a1 91221e13 889c009d 1a98e02a 9a2fe072 4b712c72 d7f2a6f9 cc12a67e f216a8cb" }, "roster-035": { "about": "pass 1 band 6: chess_char_6_03_a chess_char_6_06_a chess_char_6_07_a chess_char_5_22_b chess_char_5_23_b chess_char_6_01_a chess_char_6_02_a chess_char_6_04_a chess_char_6_05_a chess_char_6_08_a chess_char_6_09_a chess_char_6_11_a token_10017_skadi2_dedant token_10030_mlyss_wtrman",