diff --git a/config/formats.ts b/config/formats.ts index c8ba02592e..be4b4c75e5 100644 --- a/config/formats.ts +++ b/config/formats.ts @@ -4100,7 +4100,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ mod: 'gen4', team: 'random', bestOfDefault: true, - ruleset: ['Obtainable', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Standard'], }, { name: "[Gen 3] Random Battle", @@ -4130,7 +4130,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ team: 'randomCC', searchShow: false, challengeShow: false, - ruleset: ['Obtainable', 'HP Percentage Mod', 'Cancel Mod', 'Desync Clause Mod', 'Sleep Clause Mod', 'Freeze Clause Mod'], + ruleset: ['Obtainable', 'Switch Priority Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Sleep Clause Mod', 'Freeze Clause Mod'], }, { name: "[Gen 1] Hackmons Cup", @@ -4139,7 +4139,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ team: 'randomHC', searchShow: false, challengeShow: false, - ruleset: ['HP Percentage Mod', 'Cancel Mod', 'Desync Clause Mod', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Team Type Preview'], + ruleset: ['HP Percentage Mod', 'Switch Priority Clause Mod', 'Cancel Mod', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Team Type Preview'], banlist: ['Nonexistent'], onModifySpecies(species, target, source, effect) { if (!target) return; @@ -4260,7 +4260,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ mod: 'gen3', gameType: 'doubles', searchShow: false, - ruleset: ['Standard', '!Switch Priority Clause Mod'], + ruleset: ['Standard'], banlist: ['Uber', 'Quick Claw', 'Soul Dew', 'Explosion', 'Self-Destruct', 'Swagger'], unbanlist: ['Wobbuffet', 'Wynaut'], }, @@ -5165,7 +5165,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ name: "[Gen 3] Ubers", mod: 'gen3', searchShow: false, - ruleset: ['Standard', 'Deoxys Camouflage Clause Mod', 'One Baton Pass Clause'], + ruleset: ['Standard', 'One Baton Pass Clause'], banlist: ['Wobbuffet + Leftovers', 'Wynaut + Leftovers', 'Baton Pass'], }, { @@ -5255,7 +5255,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ mod: 'gen3rs', gameType: 'doubles', searchShow: false, - ruleset: ['Standard', '!Switch Priority Clause Mod'], + ruleset: ['Standard'], banlist: ['Uber', 'Quick Claw', 'Soul Dew', 'Swagger'], }, { @@ -5265,7 +5265,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ gameType: 'doubles', ruleset: [ 'Obtainable', 'Team Preview', 'Species Clause', 'Stadium Sleep Clause', 'Freeze Clause Mod', 'Max Team Size = 6', 'VGC Timer', - 'Nickname Clause', 'Beat Up Nicknames Mod', 'Endless Battle Clause', 'Cancel Mod', 'Picked Team Size = 4', 'Exact HP Mod', 'Item Clause = 1', 'Open Team Sheets', + 'Nickname Clause', 'Switch Priority Clause Mod', 'Beat Up Nicknames Mod', 'Endless Battle Clause', 'Cancel Mod', 'Picked Team Size = 4', 'Exact HP Mod', 'Item Clause = 1', 'Open Team Sheets', ], banlist: ['Restricted Legendary', 'Mythical', 'Soul Dew'], bestOfDefault: true, @@ -5286,7 +5286,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ gameType: 'singles', ruleset: [ 'Obtainable', 'Team Preview', 'Species Clause', 'Stadium Sleep Clause', 'Freeze Clause Mod', 'Max Team Size = 6', 'VGC Timer', - 'Nickname Clause', 'Beat Up Nicknames Mod', 'Endless Battle Clause', 'Cancel Mod', 'Picked Team Size = 3', 'Exact HP Mod', "Item Clause = 1", 'Open Team Sheets', + 'Nickname Clause', 'Switch Priority Clause Mod', 'Beat Up Nicknames Mod', 'Endless Battle Clause', 'Cancel Mod', 'Picked Team Size = 3', 'Exact HP Mod', "Item Clause = 1", 'Open Team Sheets', ], banlist: ['Soul Dew', 'Restricted Legendary', 'Mythical', 'Wobbuffet + Leftovers', 'Wynaut + Leftovers'], restricted: [], @@ -5372,8 +5372,8 @@ export const Formats: import('../sim/dex-formats').FormatList = [ ruleset: [ 'Picked Team Size = 3', 'Min Level = 50', 'Max Level = 55', 'Max Total Level = 155', 'Obtainable', 'Stadium Sleep Clause', 'Freeze Clause Mod', 'Species Clause', 'Item Clause = 1', - 'Endless Battle Clause', 'Cancel Mod', 'Event Moves Clause', 'Nickname Clause', 'Beat Up Nicknames Mod', - 'Team Preview', + 'Endless Battle Clause', 'Cancel Mod', 'Event Moves Clause', 'Nickname Clause', 'Switch Priority Clause Mod', + 'Beat Up Nicknames Mod', 'Team Preview', ], banlist: ['Uber'], }, @@ -5450,7 +5450,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ searchShow: false, ruleset: [ 'Picked Team Size = 3', 'Min Level = 50', 'Max Level = 55', 'Max Total Level = 155', - 'Obtainable', 'Team Preview', 'Stadium Sleep Clause', 'Species Clause', 'Nickname Clause', 'Cancel Mod', 'NC 1997 Move Legality', + 'Obtainable', 'Switch Priority Clause Mod', 'Team Preview', 'Stadium Sleep Clause', 'Species Clause', 'Nickname Clause', 'Cancel Mod', 'NC 1997 Move Legality', ], banlist: ['Uber'], }, @@ -5477,7 +5477,7 @@ export const Formats: import('../sim/dex-formats').FormatList = [ desc: `Only Pokémon sets that can be rented through the American Stadium Poké Cup are legal.`, mod: 'gen1stadium', searchShow: false, - ruleset: ['Stadium Sleep Clause', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'Team Preview', 'Stadium Poke Cup Rentals'], + ruleset: ['Stadium Sleep Clause', 'Freeze Clause Mod', 'Species Clause', 'Nickname Clause', 'Team Preview', 'Switch Priority Clause Mod', 'Stadium Poke Cup Rentals'], banlist: ['Uber'], }, { @@ -5493,6 +5493,6 @@ export const Formats: import('../sim/dex-formats').FormatList = [ searchShow: false, debug: true, battle: { trunc: Math.trunc }, - ruleset: ['HP Percentage Mod', 'Cancel Mod', 'Desync Clause Mod', 'Max Team Size = 24', 'Max Move Count = 24', 'Max Level = 9999', 'Default Level = 100'], + ruleset: ['HP Percentage Mod', 'Cancel Mod', 'Max Team Size = 24', 'Max Move Count = 24', 'Max Level = 9999', 'Default Level = 100'], }, ]; diff --git a/data/mods/gen1/rulesets.ts b/data/mods/gen1/rulesets.ts index d6bfeaa805..ea6cc7c698 100644 --- a/data/mods/gen1/rulesets.ts +++ b/data/mods/gen1/rulesets.ts @@ -2,7 +2,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable standardag: { inherit: true, ruleset: [ - 'Obtainable', 'Desync Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Endless Battle Clause', + 'Obtainable', 'Switch Priority Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Endless Battle Clause', ], }, standard: { diff --git a/data/mods/gen1stadium/rulesets.ts b/data/mods/gen1stadium/rulesets.ts index 6d81137ec5..135b6dd9f0 100644 --- a/data/mods/gen1stadium/rulesets.ts +++ b/data/mods/gen1stadium/rulesets.ts @@ -2,7 +2,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable standardag: { inherit: true, ruleset: [ - 'Obtainable', 'Exact HP Mod', 'Cancel Mod', + 'Obtainable', 'Switch Priority Clause Mod', 'Exact HP Mod', 'Cancel Mod', ], }, standard: { diff --git a/data/mods/gen2stadium2/rulesets.ts b/data/mods/gen2stadium2/rulesets.ts index 7da1a4ed93..09e76cd416 100644 --- a/data/mods/gen2stadium2/rulesets.ts +++ b/data/mods/gen2stadium2/rulesets.ts @@ -2,7 +2,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable standardag: { inherit: true, ruleset: [ - 'Obtainable', 'Team Preview', 'Exact HP Mod', 'Cancel Mod', 'Beat Up Nicknames Mod', + 'Obtainable', 'Team Preview', 'Exact HP Mod', 'Cancel Mod', 'Switch Priority Clause Mod', 'Beat Up Nicknames Mod', ], }, standard: { diff --git a/data/mods/gen3/rulesets.ts b/data/mods/gen3/rulesets.ts index 637f7d2197..5249c30c5c 100644 --- a/data/mods/gen3/rulesets.ts +++ b/data/mods/gen3/rulesets.ts @@ -5,7 +5,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable desc: "The standard ruleset for all official Smogon singles tiers (Ubers, OU, etc.)", ruleset: [ 'Standard AG', - 'Sleep Clause Mod', 'Switch Priority Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', + 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', ], }, standarddraft: { @@ -13,7 +13,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable name: 'Standard Draft', desc: "The custom Draft League ruleset", ruleset: [ - 'Obtainable', 'Nickname Clause', 'Beat Up Nicknames Mod', '+Unreleased', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', + 'Obtainable', 'Nickname Clause', 'Switch Priority Clause Mod', 'Beat Up Nicknames Mod', '+Unreleased', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'One Boost Passer Clause', 'Freeze Clause Mod', 'Accuracy Moves Clause', 'Baton Pass Trap Clause', ], banlist: [ diff --git a/data/mods/gen3frlg/rulesets.ts b/data/mods/gen3frlg/rulesets.ts index 0dec9020f9..786d156bad 100644 --- a/data/mods/gen3frlg/rulesets.ts +++ b/data/mods/gen3frlg/rulesets.ts @@ -5,7 +5,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable desc: "The standard ruleset for all official Smogon singles tiers (Ubers, OU, etc.)", ruleset: [ 'Standard AG', - 'Sleep Clause Mod', 'Switch Priority Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', + 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Evasion Items Clause', 'Evasion Moves Clause', ], }, standarddraft: { diff --git a/data/mods/gen4/rulesets.ts b/data/mods/gen4/rulesets.ts index 71359c6c5a..d622596e3f 100644 --- a/data/mods/gen4/rulesets.ts +++ b/data/mods/gen4/rulesets.ts @@ -2,7 +2,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable standardag: { inherit: true, ruleset: [ - 'Obtainable', 'HP Percentage Mod', 'Cancel Mod', 'Beat Up Nicknames Mod', 'Endless Battle Clause', + 'Obtainable', 'HP Percentage Mod', 'Cancel Mod', 'Switch Priority Clause Mod', 'Beat Up Nicknames Mod', 'Endless Battle Clause', ], }, standard: { @@ -14,7 +14,7 @@ export const Rulesets: import('../../../sim/dex-formats').ModdedFormatDataTable }, flatrules: { inherit: true, - ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Item Clause = 1', 'Adjust Level Down = 50', 'Picked Team Size = Auto', 'Cancel Mod'], + ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Switch Priority Clause Mod', 'Item Clause = 1', 'Adjust Level Down = 50', 'Picked Team Size = Auto', 'Cancel Mod'], }, teampreview: { inherit: true, diff --git a/data/rulesets.ts b/data/rulesets.ts index 7fe0954628..27b0d154af 100644 --- a/data/rulesets.ts +++ b/data/rulesets.ts @@ -159,7 +159,7 @@ export const Rulesets: import('../sim/dex-formats').FormatDataTable = { name: 'Standard Draft', desc: "The custom Draft League ruleset", ruleset: [ - 'Obtainable', 'Nickname Clause', 'Beat Up Nicknames Mod', '+Unreleased', '+CAP', 'Sketch Post-Gen 7 Moves', 'Team Preview', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', + 'Obtainable', 'Nickname Clause', '+Unreleased', '+CAP', 'Sketch Post-Gen 7 Moves', 'Team Preview', 'Sleep Clause Mod', 'OHKO Clause', 'Evasion Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', ], // timer: {starting: 60 * 60, grace: 0, addPerTurn: 10, maxPerTurn: 100, timeoutAutoChoose: true}, }, @@ -1424,30 +1424,12 @@ export const Rulesets: import('../sim/dex-formats').FormatDataTable = { switchpriorityclausemod: { effectType: 'Rule', name: 'Switch Priority Clause Mod', - desc: "Makes a faster Pokémon switch first when double-switching, unlike in Emerald link battles, where player 1's Pokémon would switch first", + desc: "Makes a faster Pokémon switch first when double-switching, unlike in link battles, where player 1's Pokémon would switch first", + // Implemented in battle-queue.ts onBegin() { this.add('rule', 'Switch Priority Clause Mod: Faster Pokémon switch first'); }, }, - desyncclausemod: { - effectType: 'Rule', - name: 'Desync Clause Mod', - desc: 'If a desync would happen, the move fails instead. This rule currently covers Bide, Counter, and Psywave.', - onBegin() { - this.add('rule', 'Desync Clause Mod: Desyncs changed to move failure.'); - }, - // Hardcoded in gen1/moves.ts - // Can't be disabled (no precedent for how else to handle desyncs) - }, - deoxyscamouflageclausemod: { - effectType: 'Rule', - name: 'Deoxys Camouflage Clause Mod', - desc: "Reveals the Deoxys forme when it is sent in battle.", - // Hardcoded into effect, cannot be disabled. - onBegin() { - this.add('rule', 'Deoxys Camouflage Clause Mod: Reveals the Deoxys forme when it is sent in battle.'); - }, - }, freezeclausemod: { effectType: 'Rule', name: 'Freeze Clause Mod', diff --git a/sim/battle-queue.ts b/sim/battle-queue.ts index 59e5f80650..921070c9fc 100644 --- a/sim/battle-queue.ts +++ b/sim/battle-queue.ts @@ -202,6 +202,14 @@ export class BattleQueue { } } } + if (this.battle.turn > 0 && !this.battle.ruleTable.has('switchpriorityclausemod') && ( + (this.battle.gen <= 4 && action.choice === 'instaswitch') || + (this.battle.gen <= 3 && action.choice === 'switch') + )) { + // Port switch priority goes: p1a, p2a, p1b, p2b + // Not supported: in Gen 1, each trainer sees his own Pokemon switch first + action.order += (action as SwitchAction).pokemon.getFieldPositionValue() / (this.battle.activePerHalf * 2); + } if (!midTurn) { if (action.choice === 'move') { if (!action.maxMove && !action.zmove && action.move.beforeTurnCallback) { diff --git a/sim/battle.ts b/sim/battle.ts index 7a4d67aa65..9a20bfbdf5 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -1938,6 +1938,22 @@ export class Battle { this.add('rated', typeof this.rated === 'string' ? this.rated : ''); } + if (this.gen === 1 && this.dex.currentMod !== 'gen1stadium') { + // If a desync would happen, the move fails instead. This rule currently covers Bide, Counter, and Psywave. + this.add('rule', 'Desync Clause Mod: Desyncs changed to move failure.'); + } + if (this.gen === 3) { + // Reveals the Deoxys forme when it is sent in battle. + const deoxys = ['Deoxys', 'Deoxys-Attack', 'Deoxys-Defense', 'Deoxys-Speed']; + for (const forme of deoxys) { + const species = this.dex.species.get(forme); + if (!this.ruleTable.isBannedSpecies(species)) { + this.add('rule', `Deoxys Camouflage Clause${this.dex.currentMod === 'gen3colosseum' ? '' : ' Mod'}: Reveals the Deoxys forme when it is sent in battle.`); + break; + } + } + } + format.onBegin?.call(this); for (const rule of this.ruleTable.keys()) { if ('+*-!'.includes(rule.charAt(0))) continue; diff --git a/test/common.js b/test/common.js index 5cc908c283..d75bb4de75 100644 --- a/test/common.js +++ b/test/common.js @@ -56,6 +56,7 @@ class TestTools { options.preview ? '^Team Preview' : '^!Team Preview', options.sleepClause && 'Sleep Clause Mod', !options.cancel && '!Cancel Mod', + !options.portPriority && '^Switch Priority Clause Mod', options.endlessBattleClause ? '^Endless Battle Clause' : '^!Endless Battle Clause', options.inverseMod && 'Inverse Mod', options.overflowStatMod && 'Overflow Stat Mod', diff --git a/test/sim/misc/turn-order.js b/test/sim/misc/turn-order.js index 1c9a20a67a..18eddd59c8 100644 --- a/test/sim/misc/turn-order.js +++ b/test/sim/misc/turn-order.js @@ -185,6 +185,48 @@ describe('Switching out', () => { battle.makeChoices('switch 2', 'switch 2'); assert.equal(battle.p2.pokemon[0].boosts.atk, 0); }); + + describe(`Switch Priority Clause Mod [Gen 3]`, () => { + it('should follow speed priority if Switch Priority Clause Mod is included', () => { + battle = common.gen(3).createBattle({ gameType: 'doubles' }, [[ + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 0 } }, + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 4 } }, + { species: 'Pelipper', ability: 'drizzle', moves: ['sleeptalk'] }, + { species: 'Gyarados', ability: 'intimidate', moves: ['sleeptalk'] }, + ], [ + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 8 } }, + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 12 } }, + { species: 'Torkoal', ability: 'drought', moves: ['sleeptalk'] }, + { species: 'Salamence', ability: 'intimidate', moves: ['sleeptalk'] }, + ]]); + battle.makeChoices('switch 3, switch 4', 'switch 3, switch 4'); + assert.equal(battle.field.weather, 'raindance'); + assert.equal(battle.p1.active[0].boosts.atk, 0); + assert.equal(battle.p1.active[1].boosts.atk, 0); + assert.equal(battle.p2.active[0].boosts.atk, -1); + assert.equal(battle.p2.active[1].boosts.atk, -1); + }); + + it('should follow port priority if Switch Priority Clause Mod is excluded', () => { + battle = common.gen(3).createBattle({ gameType: 'doubles', portPriority: true }, [[ + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 0 } }, + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 4 } }, + { species: 'Pelipper', ability: 'drizzle', moves: ['sleeptalk'] }, + { species: 'Gyarados', ability: 'intimidate', moves: ['sleeptalk'] }, + ], [ + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 8 } }, + { species: 'Wynaut', moves: ['sleeptalk'], evs: { spe: 12 } }, + { species: 'Torkoal', ability: 'drought', moves: ['sleeptalk'] }, + { species: 'Salamence', ability: 'intimidate', moves: ['sleeptalk'] }, + ]]); + battle.makeChoices('switch 3, switch 4', 'switch 3, switch 4'); + assert.equal(battle.field.weather, 'sunnyday'); + assert.equal(battle.p1.active[0].boosts.atk, -1); + assert.equal(battle.p1.active[1].boosts.atk, -1); + assert.equal(battle.p2.active[0].boosts.atk, -1); + assert.equal(battle.p2.active[1].boosts.atk, 0); + }); + }); }); describe('Switching in', () => {