From ae22234ed0274b5364683d86e1cc371e2f36bfb7 Mon Sep 17 00:00:00 2001 From: Guangcong Luo Date: Thu, 13 Mar 2025 15:34:47 -0700 Subject: [PATCH] Add Guaranteed Secondary Mod This is currently for tests, but does have the side effect of plausibly being fun as an actual mod to add to games. --- data/rulesets.ts | 13 +++++++++++++ test/common.js | 1 + test/sim/events.js | 2 +- test/sim/misc/statuses.js | 35 +++++++---------------------------- test/sim/moves/substitute.js | 2 +- 5 files changed, 23 insertions(+), 30 deletions(-) diff --git a/data/rulesets.ts b/data/rulesets.ts index 422fd4cb11..7b780d4297 100644 --- a/data/rulesets.ts +++ b/data/rulesets.ts @@ -2119,6 +2119,19 @@ export const Rulesets: import('../sim/dex-formats').FormatDataTable = { pokemon.trapped = true; }, }, + guaranteedsecondarymod: { + effectType: 'Rule', + name: 'Guaranteed Secondary Mod', + desc: 'All moves\' secondary effect chances are set to 100% (Tri Attack and Dire Claw set a random status; Poison Touch is not a real secondary and remains at 30%).', + onModifyMove(move) { + if (move.secondaries) { + this.debug('Freeze test: Guaranteeing secondary'); + for (const secondary of move.secondaries) { + secondary.chance = 100; + } + } + }, + }, chimera1v1rule: { effectType: 'Rule', name: 'Chimera 1v1 Rule', diff --git a/test/common.js b/test/common.js index c2e7505e24..eb7596e95e 100644 --- a/test/common.js +++ b/test/common.js @@ -59,6 +59,7 @@ class TestTools { options.endlessBattleClause ? '^Endless Battle Clause' : '^!Endless Battle Clause', options.inverseMod && 'Inverse Mod', options.overflowStatMod && 'Overflow Stat Mod', + options.customRules, ].filter(Boolean); const customRulesID = customRules.length ? `@@@${customRules.join(',')}` : ``; diff --git a/test/sim/events.js b/test/sim/events.js index 7450a1b462..cab0a5f1f7 100644 --- a/test/sim/events.js +++ b/test/sim/events.js @@ -5,7 +5,7 @@ const common = require('./../common'); let battle; -describe('Battle#on', () => { +describe('Battle#onEvent', () => { afterEach(() => { battle.destroy(); }); diff --git a/test/sim/misc/statuses.js b/test/sim/misc/statuses.js index d793890288..c630afb61d 100644 --- a/test/sim/misc/statuses.js +++ b/test/sim/misc/statuses.js @@ -182,37 +182,24 @@ describe('Freeze', () => { }); it('should cause an afflicted Shaymin-Sky to revert to its base forme', () => { - battle = common.createBattle([ + battle = common.createBattle({ + customRules: 'guaranteedsecondarymod', + }, [ [{ species: 'Chansey', ability: 'serenegrace', moves: ['icebeam'] }], [{ species: 'Shaymin-Sky', ability: 'sturdy', moves: ['sleeptalk'] }], ]); - // I didn't feel like manually testing seed after seed. Sue me. - battle.onEvent('ModifyMove', battle.format, function (move) { - if (move.secondaries) { - this.debug('Freeze test: Guaranteeing secondary'); - for (const secondary of move.secondaries) { - secondary.chance = 100; - } - } - }); battle.makeChoices('move icebeam', 'move sleeptalk'); assert.equal(battle.p2.active[0].status, 'frz'); assert.equal(battle.p2.active[0].species.name, 'Shaymin'); }); it('should not cause an afflicted Pokemon transformed into Shaymin-Sky to change to Shaymin', () => { - battle = common.createBattle([ + battle = common.createBattle({ + customRules: 'guaranteedsecondarymod', + }, [ [{ species: 'Ditto', ability: 'imposter', moves: ['transform'] }], [{ species: 'Shaymin-Sky', ability: 'sturdy', moves: ['icebeam', 'sleeptalk'] }], ]); - battle.onEvent('ModifyMove', battle.format, function (move) { - if (move.secondaries) { - this.debug('Freeze test: Guaranteeing secondary'); - for (const secondary of move.secondaries) { - secondary.chance = 100; - } - } - }); battle.makeChoices('move sleeptalk', 'move icebeam'); assert.equal(battle.p1.active[0].status, 'frz'); assert.equal(battle.p1.active[0].species.name, 'Shaymin-Sky'); @@ -220,21 +207,13 @@ describe('Freeze', () => { it('should not linger after fainting from switch-out', () => { battle = common.createBattle({ - formatid: 'gen4customgame@@@freezeclausemod', + formatid: 'gen4customgame@@@freezeclausemod,guaranteedsecondarymod', }, [[ { species: 'weavile', moves: ['icebeam', 'pursuit'] }, ], [ { species: 'gastly', moves: ['splash'] }, { species: 'seaking', moves: ['splash'] }, ]]); - battle.onEvent('ModifyMove', battle.format, function (move) { - if (move.secondaries) { - this.debug('Freeze test: Guaranteeing secondary'); - for (const secondary of move.secondaries) { - secondary.chance = 100; - } - } - }); battle.makeChoices('move icebeam', 'auto'); battle.makeChoices('move pursuit', 'switch seaking'); // battle.makeChoices('', 'switch seaking'); // in modern gens diff --git a/test/sim/moves/substitute.js b/test/sim/moves/substitute.js index 1d2cca185d..19153637be 100644 --- a/test/sim/moves/substitute.js +++ b/test/sim/moves/substitute.js @@ -78,7 +78,7 @@ describe('Substitute', () => { battle.makeChoices('move highjumpkick', 'move agility'); // Modding accuracy so High Jump Kick will miss and cause recoil - battle.onEvent('Accuracy', battle.format, true); + battle.onEvent('Accuracy', battle.format, false); battle.makeChoices('move highjumpkick', 'move agility'); // Only P1 has a substitute, so no one takes recoil damage.