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 5de800cd..f2005cfa 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 @@ -63,7 +63,10 @@ export default { if (z.type === 'guard') { const inZone = (a) => Math.abs(a.tileR - z.r) <= 1 && Math.abs(a.tileC - z.c) <= 1; const allies = battle.alliesFor(unit).filter(inZone); - for (const a of allies) battle.addBuff(a, { key: 'thorn2:bastion', duration: AURA_DUR, mods: mods({ defFlat: num(bb.def) }) }); + // one DEF buff per alchemy unit, so two units on one ally add up (+60 +60; PRTS 度算浪波 备注 「效果均可叠加」, + // GitHub #388 — one shared key let the last unit's buff replace the other's) + z.defKey ??= `thorn2:bastion:${unit.id}:${unit.mem.bastionSeq = (unit.mem.bastionSeq ?? 0) + 1}`; + for (const a of allies) battle.addBuff(a, { key: z.defKey, duration: AURA_DUR, mods: mods({ defFlat: num(bb.def) }) }); if (z.acc >= 1 - 1e-9) { z.acc -= 1; const heal = unit.s.atk * num(bb.hp_recovery_per_sec_ratio); diff --git a/test/content/kits_alt_t5.test.js b/test/content/kits_alt_t5.test.js index 1b201a5f..066f6ac3 100644 --- a/test/content/kits_alt_t5.test.js +++ b/test/content/kits_alt_t5.test.js @@ -1028,6 +1028,36 @@ test('引星棘刺 S1 度算浪波: an alchemy unit on the lowest-HP ally: DEF + } }); +test('引星棘刺 S1 度算浪波: two alchemy units on one ally add their DEF (PRTS 备注 「效果均可叠加」, GitHub #388)', () => { + // two 引星棘刺 (a normal and an elite: +60 and +75) throw at the same lowest-HP ally; one shared buff key used to let the + // last unit's DEF replace the other's (+75 instead of +135) while both heals already landed + const [na, el] = pair('15'); + const h = run({ + defs: { chess: { t_low: ally('t_low', { stats: { def: 100 } }) } }, + units: [entry(na, 'skchr_thorn2_1', { row: 10, col: 3 }), entry(el, 'skchr_thorn2_1', { row: 11, col: 3 }), { chessId: 't_low', row: 10, col: 5 }], + enemies: [], + }); + const a = sel(h, na, 'skchr_thorn2_1'), b = sel(h, el, 'skchr_thorn2_1'); + const low = h.unit('t_low'); + h.step(); + low.hp = low.s.maxHp * 0.3; + for (const u of [a, b]) u.skill.gainSp(1000); + h.runUntil(() => [a, b].every((u) => (u.mem.zones || []).some((z) => z.type === 'guard')), 10); + h.run(1.1); + const [za, zb] = [a, b].map((u) => u.mem.zones.find((z) => z.type === 'guard')); + assert.deepEqual([za.r, za.c, zb.r, zb.c], [10, 5, 10, 5], 'both on the lowest-HP ally'); + assert.equal(low.s.def, 100 + bbOf(a).def + bbOf(b).def, '+60 +75'); + assert.ok(low.hp > low.s.maxHp * 0.3, 'and they restore its HP'); + // one unit runs out: the other's DEF stays + mute(h, a); mute(h, b); + h.run(Math.max(0, za.dur - za.t) + 0.6); + assert.ok(!a.mem.zones.includes(za) && b.mem.zones.includes(zb), 'the elite\'s unit (7 s) outlasts the normal one (6 s)'); + assert.equal(low.s.def, 100 + bbOf(b).def, 'its DEF stays alone'); + h.run(zb.dur); + assert.equal(low.s.def, 100, 'no DEF bonus afterwards'); + 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 f51cf68d..1b31793a 100644 --- a/test/golden/roster.json +++ b/test/golden/roster.json @@ -2017,64 +2017,64 @@ "round": 12, "seed": 3754088384, "waveId": "act1autochess_h05", - "time": 210.5, - "ticks": 6315, + "time": 211.6, + "ticks": 6348, "reason": "cleared", - "killed": 46, + "killed": 64, "total": 167, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 418, + "rngDraws": 743, "errors": {"count":0,"kinds":[]}, "players": { "p1": { - "killed": 46, + "killed": 64, "total": 167, "perfect": false, - "leaks": 121, + "leaks": 103, "leaksUncounted": 0, "coins": 2, - "dmg": 412266, + "dmg": 557616, "bossDmg": 0, - "heal": 39432, - "deaths": 29, + "heal": 70704, + "deaths": 22, "layerGains": {"indomShip":65} } }, "units": [ - ["p1",1,"op","chess_char_5_11_a",0,null,2474.56,1,200,2,22853,11105,5555,42,5], - ["p1",2,"op","chess_char_5_19_a",0,null,3221.7,1,202,3,42457,18975,143,16,2], - ["p1",3,"op","chess_char_5_13_a",0,null,0,0,163,10,104087,26324,70,36,1], - ["p1",4,"op","chess_char_5_14_a",0,null,1732,1,201,2,8120,5409,1482,23,3], - ["p1",5,"op","chess_char_5_06_b",0,"uniequip_003_etlchi",0,0,157,14,130469,13814,5951,32,8], - ["p1",6,"op","chess_char_5_17_a",0,null,0,0,198,0,9636,19979,192,19,6], - ["p1",7,"op","chess_char_5_12_a",1,null,0,0,3,3,14164,3044,75,13,2], - ["p1",8,"op","chess_char_5_15_a",0,null,926,1,203,6,18667,926,14185,84,25], - ["p1",9,"op","chess_char_5_20_a",0,null,0,0,187,0,7091,3476,152,15,1], - ["p1",10,"op","chess_char_5_21_a",0,null,0,0,190,0,5581,7990,180,9,0], - ["p1",11,"op","chess_char_5_22_a",0,null,1237,1,204,6,46595,1389,0,72,2], - ["p1",12,"op","chess_char_5_23_a",0,null,0,0,156,0,0,5131,11429,21,8], + ["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], ["-","~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] ], "enemies": { - "enemy_1005_yokai_3": [1,0,1,4843,11508], - "enemy_1009_lurker": [72,16,56,703,105924], + "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,24,27,16056,139867], + "enemy_1019_jshoot_2": [51,30,21,17762,168939], "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,13143,13996], - "enemy_1404_msnip": [36,4,32,76406,127059], - "enemy_1516_jakill": [1,0,1,6954,7274], - "enemy_9011_acrefr": [1,0,1,0,5226] + "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] }, - "hooks": [1,204,6315,955,955,3544,3574,1860,75,197,63,63,0,22106,192,109,167,121,1,80,13,0,6], - "events": {"atk":1040,"bounty":1,"deploy":35,"die":76,"dmg":3536,"engage":12,"fx":118,"heal":363,"layer":13,"leak":121,"skill":126,"spawn":182,"status":263}, - "fx": {"aoe":3,"dodge":6,"dollEnd":4,"garrison":13,"healAoe":5,"hpShare":1,"palsy":1,"reborn":2,"revive":8,"shield":35,"sp":8,"substitute":5,"summon":1,"swap":1,"zone":25}, - "snaps": "0092f82c d956b3ce a0ea1881 5a64de8a 599b4202 9e1ae601 5374146f 16bd3aaf fde61ed2 91162832 b910803a ac839a60 a1563b88 f4c5c089 2603620b 128b4ac4 3c6b3ca2 b40bc0ae ad9e9e42 6f2dd105 b73c731d" + "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" }, "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":139288,"deaths":1,"layerGains":{}}}, + "players": {"p1":{"killed":82,"total":104,"perfect":false,"leaks":22,"leaksUncounted":0,"coins":6,"dmg":4801724,"bossDmg":0,"heal":98672,"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,10165,49823,194,31], - ["p1",3,"op","chess_char_5_19_b",0,"none",3682,1,11,5,218886,7679,577,124,5], - ["p1",4,"op","chess_char_5_13_b",0,"uniequip_003_ghost2",3448.92,1,13,4,163179,41498,641,210,5], - ["p1",5,"op","chess_char_5_14_b",0,"none",3217.16,1,15,0,16840,27606,11049,217,16], + ["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",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",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,75108,166,128], + ["p1",10,"op","chess_char_5_15_b",0,"none",1907.5,1,12,0,58039,0,36694,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,16850,933397], - "enemy_1381_winman_2": [39,31,7,37691,1724781], - "enemy_1387_winshd": [30,22,5,75259,1942830], + "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_1425_lrcmra_2": [1,0,1,1682,43433], "enemy_2009_csaudc": [1,0,1,0,14091] }, - "hooks": [1,120,6900,2592,2592,3942,3943,6279,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":1084,"leak":18,"skill":740,"spawn":119,"status":797}, + "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}, "fx": {"aoe":16,"crit":21,"dodge":6,"ember":1,"healAoe":31,"hpShare":5,"sp":140,"zone":148}, - "snaps": "de3bd2e2 3bc7daf8 18ea893d 1ba5ff71 e9295c82 a68eee00 eca0d338 0a422d3c a30fc3a9 d6b53fa1 e4292430 9a138543 6f59d994 c998b7e9 26b9bbcd 2f9a6a6f 437b79cf acf535b3 9e8b5733 b227076b c64de105 4080fab7 3d4e320a" + "snaps": "de3bd2e2 9ce456ee bcde1796 81851dcd 51a35e80 50098249 40a84907 cbda70fd a91a07cd 50f01226 20db1b07 0b0c9a0a cee1a934 dc30669d 6b6d29b1 b0624ef2 f6a4355c 68c2d268 368b7d82 03af8242 2387ed85 0421556c d1e4bd7f" }, "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",