From 1576842641c09bfe3b07aa0a98f367c3d8c49ff7 Mon Sep 17 00:00:00 2001 From: sganggs Date: Mon, 5 Oct 2026 17:48:07 +0800 Subject: [PATCH] =?UTF-8?q?feedback5=20WC:=20=E4=BC=BA=E5=A4=9C=20S2=20and?= =?UTF-8?q?=20=E6=B5=8A=E5=BF=83=E6=96=AF=E5=8D=A1=E8=92=82=20S2,=20AUTO?= =?UTF-8?q?=20skills=20that=20act=20on=20allies,=20fire=20without=20an=20e?= =?UTF-8?q?nemy=20(audit=20after=20GitHub=20#124)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Audit of every AUTO time-SP skill with no enemy on the field: 35 never fired. Two need no target and are fixed: 伺夜 S2 领袖的馈赠 — PRTS 备注 「仅场上存在狼群,且狼群未获得此技能的充能时可触发技能」: the kit casts it when ready while the pack stands and holds no unused gift (it waited for 伺夜's own next attack and could overwrite an unused gift); 浊心斯卡蒂 S2 同葬无光之愿 (鼓舞 on allies + trait heal, a toggle) is SP_FULL like 魔王 S1. The rest correctly wait for a target (next-attack / next-heal skills, attack modes, enemy-targeted effects) or are left for the owner (赫默 S2 / 巫恋 S2 summon releases, 纯烬艾雅法拉 S1); the list is in the 0.2.0 doc draft. Golden: roster-039 / roster-040 (伺夜 with S2, normal and elite) moved: S2 now casts whenever the pack holds no gift. --- .../content/kits/ops/chess_char_3_19-vigil.js | 9 ++ .../kits/ops/chess_char_6_04-skadi2.js | 6 +- test/content/kits_alt_t3.test.js | 26 ++++++ test/content/kits_alt_t6.test.js | 17 ++++ test/golden/roster.json | 86 +++++++++---------- 5 files changed, 99 insertions(+), 45 deletions(-) diff --git a/server/sim/content/kits/ops/chess_char_3_19-vigil.js b/server/sim/content/kits/ops/chess_char_3_19-vigil.js index b00b87ac..d2099026 100644 --- a/server/sim/content/kits/ops/chess_char_3_19-vigil.js +++ b/server/sim/content/kits/ops/chess_char_3_19-vigil.js @@ -116,6 +116,11 @@ export default { const dpGain = (battle, unit, n) => { if (n > 0) { battle.addDp(unit.ownerId, n); fx(battle, 'dp', unit, { n }); } }; // S2: the pack's empowered next attack (armed by the cast; ×scale on its hits; a kill pays once) const installGift = (battle, unit) => { + battle.on('tick', () => { // the cast: ready, the pack on the field, no unused gift on it (PRTS 备注) + const sk = unit.skill, w = wolfOf(unit); + if (!alive(unit) || !sk || !sk.ready || sk.active || !unit.canAct || unit.s.flags.silence || !w || w.mem.vigilGift) return; + sk.activate('SP_FULL'); + }, { owner: unit }); battle.on('beforeAttack', (ctx) => { const w = wolfOf(unit); if (!w || ctx.attacker !== w || !w.mem.vigilGift) return; @@ -201,8 +206,12 @@ export default { if (w) addShadow(battle, unit, w); }, }), + // (自动触发, PRTS 备注 「仅场上存在狼群,且狼群未获得此技能的充能时可触发技能」: no enemy needed — the kit casts it as soon + // as it is ready while the pack stands and holds no unused gift (installGift); until 0.2.0 the data's DEFAULT made it + // wait for 伺夜's own next attack, so it never fired with no enemy in his range) skchr_vigil_2: (s) => ({ kind: 'instant', + trigger: 'NEVER', onStart({ battle, unit }) { dpGain(battle, unit, num(s.bb.cost, 0)); const w = wolfOf(unit); diff --git a/server/sim/content/kits/ops/chess_char_6_04-skadi2.js b/server/sim/content/kits/ops/chess_char_6_04-skadi2.js index 25e3ab49..5210b18e 100644 --- a/server/sim/content/kits/ops/chess_char_6_04-skadi2.js +++ b/server/sim/content/kits/ops/chess_char_6_04-skadi2.js @@ -60,8 +60,10 @@ function skadi2(bb, chess, def) { onStart({ battle, unit }) { unit.hp = unit.s.maxHp; battle.fx('heal', { x: unit.x, y: unit.y, id: unit.id }); }, }, // S2 同葬无光之愿 (toggle): 鼓舞 ATK / DEF = atk / def × her ATK / DEF on every other ally of her (+ 海嗣) range, - // trait heal attack@atk_to_hp_recovery_ratio (trait pulse) - skchr_skadi2_2: { kind: 'toggle' }, + // trait heal attack@atk_to_hp_recovery_ratio (trait pulse). 自动触发 with effects on her allies only (nothing to target): + // on as soon as it is ready (SP_FULL, like 魔王 S1 往昔萦绕身旁); until 0.2.0 the data's DEFAULT left it off until an + // enemy came into her (or a 海嗣's) range. + skchr_skadi2_2: { kind: 'toggle', trigger: 'SP_FULL' }, }; return { skills, diff --git a/test/content/kits_alt_t3.test.js b/test/content/kits_alt_t3.test.js index 620825b0..35cbd229 100644 --- a/test/content/kits_alt_t3.test.js +++ b/test/content/kits_alt_t3.test.js @@ -829,6 +829,32 @@ test('3_19 伺夜 S2 领袖的馈赠: +DP, the pack recovers HP, its next attack } }); +test('3_19 伺夜 S2 领袖的馈赠 (自动触发): no enemy needed — cast at full SP while the pack stands and holds no unused gift (PRTS 备注), never without the pack', () => { + for (const id of BOTH('chess_char_3_19_a')) { + const b = SB(id, 'skchr_vigil_2'); + const h = makeBattle({ defs: { chess: noGarrison(id) }, timeLimit: 60, flags: { dpPerSec: 0 }, units: [U(id, 'skchr_vigil_2', 10, 3)] }); + const u = h.unit(id), p = h.b.getPlayer('p1'); + h.run(1); + const w = u.trait.reinforcement; + assert.ok(w && w.alive, 'the pack stands'); + const dp0 = p.dp; + fill(u); + assert.ok(h.runUntil(() => u.skill.activations === 1, 1), 'cast with nobody on the field'); + approx(p.dp, dp0 + b.cost, 1e-6, '+cost DP at once'); + assert.ok(w.mem.vigilGift, 'the pack holds the gift for its next attack'); + fill(u); + h.run(3); + assert.equal(u.skill.activations, 1, '"狼群未获得此技能的充能时可触发": no second cast while the gift is unused'); + // the gift spent (as by a bite), the pack gone: still no cast until a pack stands again + w.mem.vigilGift = null; + for (let i = 0; i < 10 && w.alive; i++) h.b.dealDamage(null, w, { amount: 1e9, type: 'true' }); // a wolf is lost per KO + assert.ok(!u.trait.reinforcement?.alive, 'no pack on the field'); + h.step(2); + assert.equal(u.skill.activations, 1, '"仅场上存在狼群…时可触发": no pack, no cast'); + done(h); + } +}); + test('3_19 伺夜 精锐 module TAC-Y: ×165 % on pack-blocked enemies; "援军阻挡的敌人更容易受到我方的攻击" = those enemies taunt +1 (not the pack); TAC-X guard not applied', () => { const id = 'chess_char_3_19_b', mod = 'uniequip_003_vigil'; const tb = ds.getChess(id, { moduleId: mod }).traitBb; diff --git a/test/content/kits_alt_t6.test.js b/test/content/kits_alt_t6.test.js index 390baaa1..664201d3 100644 --- a/test/content/kits_alt_t6.test.js +++ b/test/content/kits_alt_t6.test.js @@ -366,6 +366,23 @@ test('6_04 浊心斯卡蒂 S2 同葬无光之愿: toggle; 鼓舞 ATK and DEF (at } }); +test('6_04 浊心斯卡蒂 S2 同葬无光之愿 (自动触发, effects on her allies only): on as soon as its SP is full — no enemy needed', () => { + for (const id of both('chess_char_6_04')) { + const sid = 'skchr_skadi2_2'; + const h = run({ + defs: { chess: { ally_a: plain('ally_a', { stats: { maxHp: 1e5, atk: 400, def: 100 } }) } }, + units: [U(id, sid, 10, 4, { carryState: READY }), { chessId: 'ally_a', row: 10, col: 5 }], + }); + const u = h.unit(id), a = h.unit('ally_a'); + usesSkill(u, sid); + assert.equal(u.skill.rule, 'SP_FULL'); + assert.ok(h.runUntil(() => u.skill.active, 2), 'on with nobody on the field (the data DEFAULT waited for an enemy in her range)'); + h.run(1.1); + assert.ok(a.findBuff('inspire') && a.findBuff('inspire:def'), '鼓舞 on the ally beside her'); + done(h); + } +}); + // ================================================================================================================= // 6_05 异客 diff --git a/test/golden/roster.json b/test/golden/roster.json index 7949d82c..fe3a85cd 100644 --- a/test/golden/roster.json +++ b/test/golden/roster.json @@ -2406,41 +2406,41 @@ "time": 170, "ticks": 5100, "reason": "timeout", - "killed": 47, + "killed": 46, "total": 52, "unspawned": 0, "bossHpLeft": null, - "rngDraws": 32, + "rngDraws": 22, "errors": {"count":0,"kinds":[]}, "players": { "p1": { - "killed": 47, + "killed": 46, "total": 52, "perfect": false, - "leaks": 5, + "leaks": 6, "leaksUncounted": 1, "coins": 6, - "dmg": 437959, + "dmg": 434676, "bossDmg": 0, - "heal": 13283, - "deaths": 1, - "layerGains": {"miraShip":3,"raidShip":26} + "heal": 12994, + "deaths": 2, + "layerGains": {"miraShip":3,"raidShip":24} } }, "units": [ - ["p1",1,"op","chess_char_3_12_a",1,null,4457.94,1,29,6,56116,1735,7454,222,9], - ["p1",2,"op","chess_char_3_12_b",1,"none",5607.76,1,31,6,52402,1466,5490,156,7], - ["p1",3,"op","chess_char_3_18_a",1,null,1481,1,10,0,5796,0,0,0,7], - ["p1",4,"op","chess_char_3_18_b",1,"none",1845,1,60,3,61231,4973,0,130,9], - ["p1",5,"op","chess_char_3_04_a",2,null,1864,1,9,5,30544,308,0,102,3], - ["p1",6,"op","chess_char_3_05_a",1,null,5876,1,11,0,20218,5530,0,84,0], - ["p1",7,"op","chess_char_3_04_b",2,"uniequip_004_swire2",2588.3,1,74,8,61422,352,301,62,4], - ["p1",8,"op","chess_char_3_05_b",1,"none",6786.23,1,34,3,38798,723,0,33,0], - ["p1",9,"op","chess_char_3_01_a",1,null,1471.8,1,1,1,3517,0,0,36,1], - ["p1",10,"op","chess_char_3_19_a",1,null,1439,1,4,3,34773,0,0,114,12], - ["p1",11,"op","chess_char_3_21_a",1,null,1364,1,7,11,62130,0,0,197,19], - ["p1",12,"op","chess_char_3_01_b",1,"none",1770.9,1,2,1,7067,101,0,36,2], - ["p1",13,"token","token_10028_vigil_wolf",null,null,880,1,5,0,3947,38,38,7,null] + ["p1",1,"op","chess_char_3_12_a",1,null,4411.26,1,29,7,54875,1553,6712,222,9], + ["p1",2,"op","chess_char_3_12_b",1,"none",5549.04,1,31,6,62074,1585,6003,156,8], + ["p1",3,"op","chess_char_3_18_a",1,null,1481,1,10,0,6559,0,0,0,7], + ["p1",4,"op","chess_char_3_18_b",1,"none",1845,1,59,5,64813,4695,0,133,9], + ["p1",5,"op","chess_char_3_04_a",2,null,1864,1,71,3,25310,47,0,73,3], + ["p1",6,"op","chess_char_3_05_a",1,null,5876,1,11,0,20410,5937,0,88,0], + ["p1",7,"op","chess_char_3_04_b",2,"uniequip_004_swire2",2588.3,1,72,4,35869,271,254,48,3], + ["p1",8,"op","chess_char_3_05_b",1,"none",6715.17,1,34,1,38309,723,0,31,0], + ["p1",9,"op","chess_char_3_01_a",1,null,1471.8,1,1,4,15614,0,0,73,2], + ["p1",10,"op","chess_char_3_19_a",1,null,1145.5,1,4,5,37409,294,0,120,4], + ["p1",11,"op","chess_char_3_21_a",1,null,0,0,7,7,50328,1364,0,158,15], + ["p1",12,"op","chess_char_3_01_b",1,"none",1770.9,1,2,3,18936,101,0,73,3], + ["p1",13,"token","token_10028_vigil_wolf",null,null,880,1,5,1,4170,25,25,7,null] ], "enemies": { "enemy_10030_vtwand": [1,0,0,0,0], @@ -2449,16 +2449,16 @@ "enemy_1169_duphlx": [1,1,0,13,4320], "enemy_1208_msfji_2": [1,1,0,0,30], "enemy_1302_ymtro_2": [1,1,0,0,32400], - "enemy_1381_winman": [21,21,0,1153,131544], - "enemy_1381_winman_2": [12,12,0,1153,101088], - "enemy_1387_winshd": [12,7,0,9602,113227], + "enemy_1381_winman": [21,20,0,1140,126962], + "enemy_1381_winman_2": [12,12,0,1018,101088], + "enemy_1387_winshd": [12,7,0,11118,114526], "enemy_1438_dspred": [1,1,0,1030,14256], "enemy_2034_sythef": [1,1,0,139,8640] }, - "hooks": [1,73,5100,1445,1445,1980,1980,2325,48,54,73,71,0,16134,93,54,53,0,1,50,8,0,0], - "events": {"atk":1445,"bounty":3,"deploy":20,"die":54,"dmg":1980,"fx":176,"heal":188,"layer":8,"skill":143,"spawn":66,"status":153}, - "fx": {"aoe":32,"blink":3,"bondMilestone":1,"buff":14,"coin":63,"displace":6,"dp":28,"garrison":8,"shield":1,"volley":19,"wolfShadow":1}, - "snaps": "6d9db527 8766db85 954b6eb0 2cef17b3 647c06e2 1d9e5e43 8f86fa75 7716b2ca d33a9b65 47ffc983 db69a403 7973fbaf 6ff6f5f8 32a51549 72571943 2948a3dd 3bbdee6f" + "hooks": [1,74,5100,1436,1436,1954,1954,2273,48,55,63,61,0,16495,108,53,53,0,1,51,7,0,0], + "events": {"atk":1436,"bounty":3,"deploy":21,"die":55,"dmg":1953,"fx":139,"heal":160,"layer":7,"skill":123,"spawn":66,"status":169}, + "fx": {"aoe":33,"blink":3,"bondMilestone":1,"buff":6,"camouflage":2,"coin":45,"displace":3,"dp":21,"garrison":7,"shield":1,"shieldBreak":1,"volley":15,"wolfShadow":1}, + "snaps": "ed245fce 888d207d b41cc6de c8d56304 e5bf2cb3 4b70797d 6b6623eb 79906eee 7075f2a2 d9322c8d 76f904a2 3888b480 2b28d14b 7800a6be dc52c6de baf97ee7 077b1592" }, "roster-040": { "about": "pass 2 band 4: chess_char_4_01_a chess_char_4_17_a chess_char_4_18_a chess_char_4_12_a chess_char_4_04_a chess_char_4_07_a chess_char_4_16_a chess_char_4_09_a chess_char_3_19_b chess_char_3_21_b chess_char_4_02_a chess_char_4_13_a token_10028_vigil_wolf", @@ -2472,34 +2472,34 @@ "time": 170, "ticks": 5100, "reason": "timeout", - "killed": 21, + "killed": 23, "total": 65, "unspawned": 0, "bossHpLeft": null, "rngDraws": 226, "errors": {"count":0,"kinds":[]}, - "players": {"p1":{"killed":21,"total":65,"perfect":false,"leaks":44,"leaksUncounted":0,"coins":2,"dmg":398416,"bossDmg":0,"heal":495,"deaths":25,"layerGains":{}}}, + "players": {"p1":{"killed":23,"total":65,"perfect":false,"leaks":42,"leaksUncounted":0,"coins":2,"dmg":398198,"bossDmg":0,"heal":339,"deaths":25,"layerGains":{}}}, "units": [ ["p1",1,"op","chess_char_4_01_a",1,null,0,0,4,0,3410,2638,0,29,1], ["p1",2,"op","chess_char_4_17_a",2,null,0,0,7,0,14528,2849,0,10,1], ["p1",3,"op","chess_char_4_18_a",2,null,0,0,9,0,12723,2867,0,11,1], - ["p1",4,"op","chess_char_4_12_a",1,null,0,0,87,1,22077,3849,341,27,1], - ["p1",5,"op","chess_char_4_04_a",2,null,0,0,89,2,14432,7040,0,14,0], + ["p1",4,"op","chess_char_4_12_a",1,null,0,0,87,1,22077,3847,339,27,1], + ["p1",5,"op","chess_char_4_04_a",2,null,1623.38,1,96,2,14512,7177,0,15,0], ["p1",6,"op","chess_char_4_07_a",2,null,0,0,77,0,9369,7998,0,23,1], - ["p1",7,"op","chess_char_4_16_a",1,null,0,0,93,2,53656,7476,0,11,0], + ["p1",7,"op","chess_char_4_16_a",1,null,0,0,94,2,56048,7476,0,11,0], ["p1",8,"op","chess_char_4_09_a",2,null,0,0,3,0,0,1336,0,0,0], - ["p1",9,"op","chess_char_3_19_b",1,"none",814.75,1,96,4,49952,2481,0,63,5], - ["p1",10,"op","chess_char_3_21_b",1,"uniequip_004_archet",0,0,95,7,145539,3180,0,79,9], + ["p1",9,"op","chess_char_3_19_b",1,"none",0,0,5,3,43991,1648,0,54,1], + ["p1",10,"op","chess_char_3_21_b",1,"uniequip_004_archet",0,0,95,10,148810,3180,0,81,9], ["p1",11,"op","chess_char_4_02_a",1,null,0,0,84,1,20900,2856,0,8,1], ["p1",12,"op","chess_char_4_13_a",2,null,0,0,79,4,51831,3174,0,54,1], - ["p1",13,"token","token_10028_vigil_wolf",null,null,796.75,1,97,0,0,2796,154,0,null], + ["p1",13,"token","token_10028_vigil_wolf",null,null,0,0,6,0,0,2567,0,0,null], ["-","~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] ], "enemies": { - "enemy_1005_yokai": [24,10,14,0,44196], - "enemy_1005_yokai_2": [27,7,16,9143,63631], - "enemy_1005_yokai_3": [6,1,5,18180,181372], + "enemy_1005_yokai": [24,10,14,0,44006], + "enemy_1005_yokai_2": [27,9,16,8465,76599], + "enemy_1005_yokai_3": [6,1,5,17931,168377], "enemy_10065_ftzlc": [1,1,0,461,16339], "enemy_10162_mnctpt": [1,0,1,8345,20600], "enemy_1119_vofsd": [1,0,1,91,45544], @@ -2509,10 +2509,10 @@ "enemy_1517_xi": [1,0,1,5597,2809], "enemy_9016_acstmr": [1,1,0,0,8] }, - "hooks": [1,96,5100,546,546,823,867,523,48,88,21,32,16,8529,316,21,65,40,1,58,0,1,0], - "events": {"atk":619,"bounty":1,"deploy":29,"die":48,"dmg":861,"fx":101,"heal":1,"leak":40,"skill":42,"spawn":80,"status":171}, - "fx": {"beam":4,"block":3,"buff":6,"burst":1,"coldWind":1,"displace":15,"dp":5,"iceSpike":1,"liberate":1,"overclock":1,"overload":1,"palsy":3,"revive":3,"rockfall":1,"sentry":6,"shadowWeave":11,"shield":7,"shieldBreak":6,"stone":1,"summon":1,"swordStorm":7,"telegraph":2,"volley":9,"wake":1,"wolfShadow":1,"wolfShadowLost":2,"zone":1}, - "snaps": "4fee72dc fe5fef04 4473cf24 60569344 9d5cd492 7b0ccfce 4992cdf1 7d565a68 68c3c4c3 eac73f75 2dbfbb4d 2b661a94 5be2328b e1cf1b56 d6bf37b7 081de95c 95c27c04" + "hooks": [1,95,5100,533,533,815,851,518,50,90,17,28,16,7820,316,21,65,40,1,60,0,1,0], + "events": {"atk":606,"bounty":1,"deploy":28,"die":50,"dmg":845,"fx":93,"leak":40,"skill":34,"spawn":80,"status":171}, + "fx": {"beam":5,"block":3,"buff":2,"burst":1,"coldWind":1,"displace":15,"dp":1,"iceSpike":1,"liberate":1,"overclock":1,"overload":1,"palsy":3,"revive":3,"rockfall":1,"sentry":6,"shadowWeave":11,"shield":7,"shieldBreak":6,"stone":1,"swordStorm":7,"telegraph":2,"volley":9,"wake":1,"wolfShadow":1,"wolfShadowLost":2,"zone":1}, + "snaps": "de3ca31c 182b136c 5c27b035 f8f15ac1 250e93d3 6fde9171 1273cfdd f1c0ebf4 8e50442c 8277b17d 3a6591ca 5a144122 2014c207 a4445fd0 3d27fbdc 8d62308c d9b05d02" }, "roster-041": { "about": "pass 2 band 5: chess_char_4_23_a chess_char_4_01_b chess_char_4_19_a chess_char_4_22_a chess_char_4_12_b chess_char_4_04_b chess_char_4_07_b chess_char_4_09_b chess_char_4_20_a chess_char_4_24_a chess_char_4_25_a chess_char_4_02_b",