This commit is contained in:
André Bastos Dias 2026-06-02 14:06:41 +01:00 committed by GitHub
commit 1acaec17ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 91 additions and 42 deletions

View File

@ -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'],
},
];

View File

@ -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: {

View File

@ -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: {

View File

@ -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: {

View File

@ -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: [

View File

@ -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: {

View File

@ -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,

View File

@ -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',

View File

@ -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) {

View File

@ -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;

View File

@ -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',

View File

@ -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', () => {