diff --git a/docs/SIM.md b/docs/SIM.md index 16a03c93..45d84c7b 100644 --- a/docs/SIM.md +++ b/docs/SIM.md @@ -663,7 +663,7 @@ the source's side): |---|---|---| | `burn` 灼燃 | 1200 arts + RES −20, 10 s lock | 7000 元素伤害 + RES −20, 10 s lock | | `neural` 神经 | stun 10 s, then 1000 true (10 s lock) | 3 `palsy` (none with 麻痹免疫), then 6000 元素伤害, 10 s lock | -| `apoptosis` 凋亡 | 15 s: 阻回 (`noSp`: no SP gain of any kind, skills.js) + 静默 (no skill activation), −1 SP/s, 100 arts/s | 15 s: 50 % weaken recovering over the burst, 800 元素伤害/s | +| `apoptosis` 凋亡 | 15 s: 阻回 (`noSp`: no SP gain of any kind, skills.js) + 静默 (no skill activation), −1 技力/s — of `spTotal`, stored charges included (PRTS 技能 可充能 "当持有者的技力流失时,充能次数也会实时降低"; `setSpTotal`, a running timed skill untouched; PR #262), 100 arts/s | 15 s: 50 % weaken recovering over the burst, 800 元素伤害/s | | `erosion` 侵蚀 | permanent DEF −100 (stacking `erosionDown`) then 800 phys, 10 s lock | permanent DEF −120 then 5000 元素伤害, 8 s lock | | `necrosis` (legacy spare gauge) | 12 s: 100 true/s, ATK −20 % | same | diff --git a/server/sim/damage.js b/server/sim/damage.js index d6f170fd..72e95d92 100644 --- a/server/sim/damage.js +++ b/server/sim/damage.js @@ -478,12 +478,16 @@ function resolveBurst(battle, source, target, el) { }, }); } else { - // 15 s of 阻回 ("停止并阻止任意形式的技力回复": noSp) + 静默 (no skill activation), −1 SP and 100 arts damage per second + // 15 s of 阻回 ("停止并阻止任意形式的技力回复": noSp) + 静默 (no skill activation), −1 SP and 100 arts damage per second. + // The loss is of the official 技力 (Skill.spTotal: the stored charges × cost + the SP towards the next) — PRTS 技能 + // 可充能 "当持有者的技力流失时,充能次数也会实时降低": taking it from the partial bar alone left a full skill every + // charge it had (a one-charge skill stayed ready through the burst; PR #262). setSpTotal rebuilds the charges + // silently (no spGain) and leaves a running timed skill alone, whose SP was spent at its cast. lock(c.duration, { flags: { silence: true, noSp: true }, interval: 1, onTick: () => { const sk = target.skill; - if (sk && !sk.noSkill && sk.kind !== 'passive' && !(sk.active && sk.isTimed) && sk.sp > 0) sk.sp = Math.max(0, sk.sp - c.spLossPerSec); + if (sk && !sk.noSkill && sk.kind !== 'passive' && !(sk.active && sk.isTimed) && sk.spTotal > 0) sk.setSpTotal(Math.max(0, sk.spTotal - c.spLossPerSec)); hit(c.dps, c.dpsType); }, }); diff --git a/test/content/feedback6-apoptosis-sp.test.js b/test/content/feedback6-apoptosis-sp.test.js new file mode 100644 index 00000000..0bb80e7b --- /dev/null +++ b/test/content/feedback6-apoptosis-sp.test.js @@ -0,0 +1,65 @@ +// PR #262 (#261 its closed duplicate): an operator's 凋亡 burst — PRTS 元素 "立即获得等时长的阻回、静默,该阻回、静默持续期间 +// 每秒损失1点技力并受到100点无来源法术持续伤害" — drains the official 技力, stored charges included: PRTS 技能 可充能 "当持有者 +// 的技力流失时,充能次数也会实时降低". The drain took only the SP towards the next charge, so a full skill (sp = cost with +// every charge stored) kept all its charges — a one-charge skill stayed ready through the whole burst. An active timed +// skill is left alone (its SP was spent at the cast; Skill.setSpTotal leaves it too). +import { test } from 'node:test'; +import assert from 'node:assert/strict'; +import { makeBattle, chessRec, checkInvariants } from '../helpers/battleHarness.js'; +import { hasGeneratedData } from '../../server/sim/simdata.js'; + +const REAL = { skip: !hasGeneratedData() }; +const SNOW = 'chess_char_3_11_b'; // 精锐 雪猎: S2 风雪连弩, MANUAL, 可充能2次, 14 SP per charge + +function arena(units, defs = {}) { + const h = makeBattle({ defs, units, autoFinish: false, timeLimit: 120, hooks: ['spGain', 'damaged'] }); + h.step(); + return h; +} +const burst = (h, u) => { + h.b.dealDamage(null, u, { type: 'element', element: 'apoptosis', amount: u.gaugeMax }); + assert.ok(u.findBuff('apoptosisBurst'), '凋亡 bursts'); +}; + +test('PR #262: 凋亡 drains a charge skill\'s stored charges — 精锐 雪猎 with both charges loses one at the first second and is empty after 15', REAL, () => { + const h = arena([{ chessId: SNOW, row: 10, col: 4 }]); + const u = h.unit(SNOW), sk = u.skill; + assert.equal(sk.maxCharges, 2); + const cost = sk.spCost; + sk.setSpTotal(2 * cost); + assert.deepEqual([sk.charges, sk.sp, sk.spTotal], [2, cost, 2 * cost], 'both charges stored'); + burst(h, u); + h.run(1.01); + assert.deepEqual([sk.charges, sk.sp, sk.spTotal], [1, cost - 1, 2 * cost - 1], 'one second: −1 技力, the second charge goes'); + assert.equal(sk.ready, true, 'one charge left'); + h.run(14); + // (the burst ends with its 15th second: the time SP of the ticks since then is back) + assert.equal(sk.charges, 0, '15 seconds: −15 技力 — the last charge gone too'); + assert.ok(Math.abs(sk.spTotal - (2 * cost - 15)) < 0.1, `${sk.spTotal} ≈ ${2 * cost - 15}`); + assert.equal(sk.ready, false); + assert.equal(sk.activations, 0, '静默: no cast through the burst'); + assert.ok(!u.findBuff('apoptosisBurst'), 'the burst is over'); + checkInvariants(h.b); +}); + +test('PR #262: a full one-charge skill is no longer ready after the first second of 凋亡; an active timed skill keeps its state', () => { + const op = chessRec({ id: 't_apo', stats: { maxHp: 1e5, spRecovery: 0 }, skill: { spCost: 20, initSp: 0, duration: 30, durationType: 'NONE' } }); + const h = arena([{ chessId: 't_apo', row: 10, col: 4, uid: 1 }, { chessId: 't_apo', row: 10, col: 6, uid: 2 }], { chess: { t_apo: op } }); + const a = h.unit(1), b = h.unit(2); + a.skill.setSpTotal(20); + assert.equal(a.skill.ready, true); + burst(h, a); + h.run(1.01); + assert.deepEqual([a.skill.charges, a.skill.sp, a.skill.ready], [0, 19, false], 'the ready charge is part of the 技力 it loses'); + h.run(14); + assert.equal(a.skill.spTotal, 5, '−15 技力 in all'); + assert.equal(h.hooksOf('spGain').length, 0, 'the drain is no SP gain (no spGain hook)'); + // a running timed skill: its SP was spent at the cast — nothing to drain, and it runs on (the burst silences new casts only) + b.skill.setSpTotal(20); + assert.ok(b.skill.activate('test')); + const before = [b.skill.active, b.skill.charges, b.skill.sp]; + burst(h, b); + h.run(3); + assert.deepEqual([b.skill.active, b.skill.charges, b.skill.sp], before); + checkInvariants(h.b); +}); diff --git a/test/golden/diy.json b/test/golden/diy.json index b38a0fc4..b452fd5f 100644 --- a/test/golden/diy.json +++ b/test/golden/diy.json @@ -2382,7 +2382,7 @@ "hooks": [1,129,6242,303,303,643,724,1632,21,124,15,15,0,5917,2,46,105,103,1,21,0,13,0], "events": {"atk":309,"deploy":21,"die":21,"dmg":681,"engage":10,"fx":124,"heal":41,"leak":103,"skill":30,"spawn":120,"status":46}, "fx": {"aoe":24,"beam":20,"burst":13,"crit":2,"explode":1,"healField":10,"shield":9,"thorns":45}, - "snaps": "8af17d6a 024bce8c e0452b2c 5af87abd 42a1f8a9 0b71523e 3fd3e515 fa3770c9 2ca7b522 c32eaf65 dffbf1b7 224a00a2 994934f9 5bc28beb 05894548 582c0f90 dd02f272 cbdb633c 2fb767c6 ad6a50e0 205812fb" + "snaps": "8af17d6a c4ee14aa b0c6352a 4663534b ad4f6c57 79103640 6a18ed37 6ce034df 01e7e370 1a22aca7 2ab6744d 07e795ec 55eb2147 66c813ad 16426e3e 9e7597da 454aaf0c ba882526 bb829c2c 99b4e6c6 a4e6b5a1" }, "diy-059": { "about": "5_diy1_b=shu/S1/002_shu 5_diy2_b=shu/S2/002_shu 5_diy1_b=shu/S3/002_shu 6_diy1_a=shu/S1 6_diy2_a=shu/S2 6_diy1_a=shu/S3 6_diy2_b=shu/S1 6_diy1_b=shu/S2 6_diy2_b=shu/S3 6_diy1_b=shu/S1/002_shu 6_diy2_b=shu/S2/002_shu 6_diy1_b=shu/S3/002_shu", @@ -2396,35 +2396,35 @@ "time": 230, "ticks": 6900, "reason": "timeout", - "killed": 39, + "killed": 47, "total": 96, "unspawned": 0, "bossHpLeft": null, "rngDraws": 0, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":39,"total":96,"perfect":false,"leaks":57,"leaksUncounted":0,"coins":0,"dmg":234243,"bossDmg":0,"heal":203629,"deaths":18,"layerGains":{}}}, + "players": {"p1":{"killed":47,"total":96,"perfect":false,"leaks":49,"leaksUncounted":0,"coins":0,"dmg":231786,"bossDmg":0,"heal":217108,"deaths":15,"layerGains":{}}}, "units": [ - ["p1",1,"op","chess_char_5_diy1_b",0,"uniequip_002_shu",0,0,103,2,14695,21669,15436,64,11], - ["p1",2,"op","chess_char_5_diy2_b",1,"uniequip_002_shu",0,0,119,0,7297,21517,15906,36,1], - ["p1",3,"op","chess_char_5_diy1_b",2,"uniequip_002_shu",3070,1,120,6,14925,16583,5503,77,1], - ["p1",4,"op","chess_char_6_diy1_a",0,null,0,0,99,1,7880,21342,8555,56,6], - ["p1",5,"op","chess_char_6_diy2_a",1,null,0,0,101,0,5224,32777,48418,50,2], - ["p1",6,"op","chess_char_6_diy1_a",2,null,0,0,77,2,11366,9710,12836,42,1], - ["p1",7,"op","chess_char_6_diy2_b",0,"none",2791.49,1,107,5,36418,40843,15790,135,9], - ["p1",8,"op","chess_char_6_diy1_b",1,"none",0,0,102,2,16600,20626,10010,73,1], - ["p1",9,"op","chess_char_6_diy2_b",2,"none",0,0,5,5,15654,5050,26206,69,2], - ["p1",10,"op","chess_char_6_diy1_b",0,"uniequip_002_shu",0,0,8,0,14640,10510,10285,43,6], - ["p1",11,"op","chess_char_6_diy2_b",1,"uniequip_002_shu",0,0,10,6,39992,33225,14891,106,1], - ["p1",12,"op","chess_char_6_diy1_b",2,"uniequip_002_shu",3180,1,116,7,49553,20305,19793,109,2], + ["p1",1,"op","chess_char_5_diy1_b",0,"uniequip_002_shu",0,0,106,1,16402,16000,9569,59,5], + ["p1",2,"op","chess_char_5_diy2_b",1,"uniequip_002_shu",2945.74,1,119,0,5494,19342,17088,32,2], + ["p1",3,"op","chess_char_5_diy1_b",2,"uniequip_002_shu",3070,1,120,5,16030,16314,5378,80,1], + ["p1",4,"op","chess_char_6_diy1_a",0,null,2313,1,100,2,12751,26007,6577,66,2], + ["p1",5,"op","chess_char_6_diy2_a",1,null,2057.85,1,103,1,13344,39122,47357,75,2], + ["p1",6,"op","chess_char_6_diy1_a",2,null,0,0,77,2,11366,9681,12807,42,1], + ["p1",7,"op","chess_char_6_diy2_b",0,"none",2183.12,1,102,6,34558,41766,13074,133,5], + ["p1",8,"op","chess_char_6_diy1_b",1,"none",0,0,99,2,16300,33752,26299,85,2], + ["p1",9,"op","chess_char_6_diy2_b",2,"none",0,0,5,5,16102,3554,24484,71,2], + ["p1",10,"op","chess_char_6_diy1_b",0,"uniequip_002_shu",0,0,8,1,6712,7983,4179,20,1], + ["p1",11,"op","chess_char_6_diy2_b",1,"uniequip_002_shu",0,0,10,5,35380,29094,14012,94,1], + ["p1",12,"op","chess_char_6_diy1_b",2,"uniequip_002_shu",3180,1,115,9,47347,18313,36285,106,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] ], - "enemies": {"enemy_1229_darmy":[27,13,14,45139,72535],"enemy_1229_darmy_2":[57,26,31,120688,198119],"enemy_9007_acelem":[12,0,11,69460,101381]}, - "hooks": [1,120,6900,1449,1449,4412,4696,22580,57,113,43,42,0,15690,0,93,96,56,1,57,0,39,0], - "events": {"atk":1500,"deploy":21,"die":57,"dmg":4696,"engage":12,"fx":181,"heal":328,"leak":56,"skill":85,"spawn":111,"status":105}, - "fx": {"beam":18,"burst":39,"healField":47,"teleport":77}, - "snaps": "8dc1b37a b5460f3d 3555fcc6 db56014a a0553a57 f4dca0ac f05a71e9 77e33494 98645a14 e2eefd2d bd5020fc d9664555 4c789e18 d251cfc2 3e54ab89 a00b133e 02012e0d 11dc3504 389257ff 0e7213e4 96b7c324 1b69e292 0f8b3ea2" + "enemies": {"enemy_1229_darmy":[27,15,12,48739,79249],"enemy_1229_darmy_2":[57,32,23,133695,210887],"enemy_9007_acelem":[12,0,10,58192,72262]}, + "hooks": [1,120,6900,1513,1513,4343,4631,22639,62,107,26,25,0,15564,0,93,96,45,1,62,0,37,0], + "events": {"atk":1572,"deploy":21,"die":62,"dmg":4631,"engage":12,"fx":189,"heal":335,"leak":45,"skill":51,"spawn":111,"status":101}, + "fx": {"beam":18,"burst":37,"healField":49,"teleport":85}, + "snaps": "8dc1b37a b5460f3d 3ef6a531 1b763d75 2ca58274 c2fef8fd afccd50e 9e6a1580 6921be5e a89eb8c3 950cf27b 18a4160c e6764ecc cf15dcc9 dbfe2e1c fd2de4b2 aaaf0692 702a1a56 289559cc 2f1168ca 69dba497 ce110259 f0b47a01" }, "diy-060": { "about": "5_diy1_a=pallas/S1 5_diy2_a=pallas/S2 5_diy1_a=pallas/S3 5_diy2_b=pallas/S1 5_diy1_b=pallas/S2 5_diy2_b=pallas/S3 5_diy1_b=pallas/S1/002_pallas 5_diy2_b=pallas/S2/002_pallas 5_diy1_b=pallas/S3/002_pallas 5_diy2_b=pallas/S1/003_pallas 5_diy1_b=pallas/S2/003_pallas 5_diy2_b=pallas/S3/003_pallas", diff --git a/test/golden/fields.json b/test/golden/fields.json index be5ee8d0..9f773474 100644 --- a/test/golden/fields.json +++ b/test/golden/fields.json @@ -375,7 +375,7 @@ "hooks": [1,42,6000,387,387,643,1580,796,20,24,80,78,20,17921,1173,2,19,0,1,139,0,1,0], "events": {"atk":405,"deploy":17,"die":24,"dmg":733,"engage":8,"fx":203,"heal":59,"skill":158,"spawn":36,"status":179}, "fx": {"anchor":1,"aoe":3,"beam":6,"burst":1,"candle":3,"ember":3,"explode":104,"healAoe":34,"overload":4,"phase":12,"revive":1,"splash":20,"substitute":1,"summon":6,"swap":1,"telegraph":1,"teleport":2}, - "snaps": "87076623 3c36dd04 03a89072 745a7c6b 24a96213 0ed332a6 26e97a3b 2b49b7d6 376df693 78dab18f 1b931756 f174873b d4541524 71b41d30 2da111bb 5c2d56c1 fa32d0c4 f6866cb6 7c0b0632 9a7cccfc" + "snaps": "87076623 3c36dd04 03a89072 745a7c6b 24a96213 0ed332a6 26e97a3b 2b49b7d6 4deb0556 087cdcb6 79fbf5f7 dfe3d106 fdaa7bd5 af470bb9 c87c0fc2 ed37f880 df193341 1e30dddf 21a08fc7 5270e9dd" }, "boss-boss_4-pair": { "about": "盐风主教昆图斯 pair pool 8400000: 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", @@ -1283,8 +1283,8 @@ "enemy_9022_acdumm": [1,0,0,478,0], "enemy_9023_acdums": [12,12,0,25367,120] }, - "hooks": [1,53,6000,1112,1250,2538,2725,6368,26,28,66,63,0,29865,1406,6,18,0,1,28,0,10,0], - "events": {"atk":1217,"deploy":33,"die":28,"dmg":2714,"engage":14,"fx":1020,"heal":66,"skill":129,"spawn":42,"status":675}, + "hooks": [1,53,6000,1112,1250,2538,2725,6368,26,28,66,63,0,29862,1406,6,18,0,1,28,0,10,0], + "events": {"atk":1217,"deploy":33,"die":28,"dmg":2714,"engage":14,"fx":1020,"heal":66,"skill":129,"spawn":42,"status":683}, "fx": { "beam": 13, "blink": 2, @@ -1321,7 +1321,7 @@ "weightless": 5, "zone": 76 }, - "snaps": "a3593c93 05df9199 329883cc 83065c46 6d189e2d d27e20b7 d0119d66 53c297b8 408cec99 65434e27 1d704b57 5517a58b dc7344d6 58d4ad2b b8585956 3bb8237c 89be2434 4474d986 12d9ba25 a4ab8999" + "snaps": "a3593c93 05df9199 329883cc 83065c46 6d189e2d d27e20b7 d0119d66 53c297b8 408cec99 65434e27 1d704b57 5517a58b dc7344d6 58d4ad2b b8585956 eedd57cd 2c69cc89 3e330a00 d5d56836 2efc2732" }, "hidden-boss_10-solo": { "about": "假想敌:管 solo pool 7600000: chess_char_4_17_b chess_char_4_18_b chess_char_4_23_b chess_char_4_19_b chess_char_4_22_b chess_char_4_20_b chess_char_4_21_b chess_char_4_24_b chess_char_4_25_b chess_char_4_26_b", @@ -1339,32 +1339,32 @@ "total": 13, "unspawned": 0, "bossHpLeft": 7156236, - "rngDraws": 28, + "rngDraws": 27, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":12,"total":13,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":595215,"bossDmg":443764,"heal":73194,"deaths":0,"layerGains":{}}}, + "players": {"p1":{"killed":12,"total":13,"perfect":false,"leaks":1,"leaksUncounted":0,"coins":0,"dmg":595215,"bossDmg":443764,"heal":72505,"deaths":0,"layerGains":{}}}, "units": [ ["p1",1,"op","chess_char_4_17_b",1,"uniequip_002_hsguma",3513,1,4,1,1,0,0,1,0], - ["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",7440.8,1,6,0,5,3861,4102,5,1], - ["p1",3,"op","chess_char_4_23_b",2,"uniequip_002_gvial2",4147.8,1,7,4,193323,7944,2803,230,5], + ["p1",2,"op","chess_char_4_18_b",1,"uniequip_002_mudrok",7440.8,1,6,0,5,3861,4169,5,0], + ["p1",3,"op","chess_char_4_23_b",2,"uniequip_002_gvial2",4147.8,1,7,4,193323,7934,2790,230,5], ["p1",4,"op","chess_char_4_19_b",2,"uniequip_002_flamtl",3600.6,1,5,0,0,2336,0,0,0], - ["p1",5,"op","chess_char_4_22_b",2,"uniequip_002_svrash",3905.8,1,8,7,206512,35880,6134,154,3], + ["p1",5,"op","chess_char_4_22_b",2,"uniequip_002_svrash",3905.8,1,8,7,206512,35241,6004,154,3], ["p1",6,"op","chess_char_4_20_b",2,"uniequip_002_fartth",1419,1,1,0,170086,0,0,70,7], - ["p1",7,"op","chess_char_4_21_b",1,"uniequip_002_plosis",2920.8,1,9,0,0,4595,39389,67,2], + ["p1",7,"op","chess_char_4_21_b",1,"uniequip_002_plosis",2920.8,1,9,0,0,4595,39464,67,2], ["p1",8,"op","chess_char_4_24_b",1,"uniequip_002_billro",2178,1,2,0,25288,0,0,20,1], - ["p1",9,"op","chess_char_4_25_b",2,"uniequip_002_cetsyr",1671,1,10,0,0,16053,3215,0,3], - ["p1",10,"op","chess_char_4_26_b",0,"uniequip_002_bldsk",1522,1,3,0,0,2241,17551,29,6] + ["p1",9,"op","chess_char_4_25_b",2,"uniequip_002_cetsyr",1671,1,10,0,0,15953,3078,0,3], + ["p1",10,"op","chess_char_4_26_b",0,"uniequip_002_bldsk",1522,1,3,0,0,2241,17000,28,6] ], "enemies": { "enemy_1005_yokai_3": [1,0,1,13187,65325], "enemy_9010_acpupp": [2,2,0,25403,86026], "enemy_9021_acduml_2": [1,0,0,0,443764], "enemy_9022_acdumm": [1,0,0,1006,0], - "enemy_9023_acdums": [10,10,0,29635,100] + "enemy_9023_acdums": [10,10,0,28891,100] }, - "hooks": [1,25,6000,614,614,1220,1745,4474,12,13,28,26,0,15177,45,8,15,1,1,18,0,7,0], - "events": {"atk":746,"deploy":10,"die":12,"dmg":1740,"engage":6,"fx":464,"heal":136,"leak":1,"skill":56,"spawn":25,"status":248}, - "fx": {"bandage":6,"beam":15,"burst":7,"ember":2,"explode":188,"featherArrow":7,"garrisonGrant":1,"healField":2,"jungleSoul":5,"mote":68,"phase":29,"redistribute":40,"reweave":3,"rockslide":1,"sandChainsCharged":1,"shieldBreak":7,"slash":60,"spGift":9,"summon":8,"telegraph":2,"truesilver":3}, - "snaps": "e9089456 d56595f6 94862b5d c7e389c2 97042251 346900c6 d3f1fdf3 ee72f858 3559a133 032bf766 7d5d0f98 ab1e397a ca88665f 19e0cc43 4f90670f aa7bdb4e f43775ca a84c46d1 705ff5fd 5b7831a7" + "hooks": [1,25,6000,613,613,1210,1727,4456,12,13,27,25,0,15178,45,7,15,1,1,18,0,7,0], + "events": {"atk":746,"deploy":10,"die":12,"dmg":1722,"engage":6,"fx":460,"heal":135,"leak":1,"skill":54,"spawn":25,"status":248}, + "fx": {"bandage":6,"beam":15,"burst":7,"ember":2,"explode":185,"featherArrow":7,"garrisonGrant":1,"healField":2,"jungleSoul":5,"mote":68,"phase":29,"redistribute":40,"reweave":3,"sandChainsCharged":1,"shieldBreak":7,"slash":60,"spGift":9,"summon":8,"telegraph":2,"truesilver":3}, + "snaps": "e9089456 d56595f6 94862b5d c7e389c2 97042251 346900c6 d3f1fdf3 ee72f858 76fb6eac 826bd52d 00497c63 de189efc 37b5cbcd ab1762e2 8644257f 4db1c850 efe502ae b7764884 f14f9be1 89f56bcc" }, "unite-1": { "about": "联防 1 helper(s), 11 leaked: chess_char_6_03_b chess_char_6_06_b chess_char_6_07_b chess_char_6_01_b chess_char_6_02_b chess_char_6_04_b chess_char_6_05_b chess_char_6_08_b token_10017_skadi2_dedant",