diff --git a/config/formats.js b/config/formats.js index 038d7f4423..aac3b562ea 100644 --- a/config/formats.js +++ b/config/formats.js @@ -21,7 +21,7 @@ let Formats = [ mod: 'gen7', team: 'random', - ruleset: ['PotD', 'Pokemon', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['PotD', 'Obtainable', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7] Unrated Random Battle", @@ -30,7 +30,7 @@ let Formats = [ team: 'random', challengeShow: false, rated: false, - ruleset: ['PotD', 'Pokemon', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['PotD', 'Obtainable', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7] OU", @@ -41,7 +41,7 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['Pokemon', 'Standard', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Team Preview'], banlist: ['Uber', 'Arena Trap', 'Power Construct', 'Shadow Tag', 'Baton Pass'], }, { @@ -64,7 +64,7 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['Pokemon', 'Standard', 'Team Preview', 'Mega Rayquaza Clause'], + ruleset: ['Obtainable', 'Standard', 'Team Preview', 'Mega Rayquaza Clause'], banlist: ['Baton Pass'], }, { @@ -127,7 +127,7 @@ let Formats = [ mod: 'gen7', maxLevel: 5, - ruleset: ['Pokemon', 'Standard', 'Swagger Clause', 'Team Preview', 'Little Cup'], + ruleset: ['Obtainable', 'Standard', 'Swagger Clause', 'Team Preview', 'Little Cup'], banlist: [ 'Aipom', 'Cutiefly', 'Drifloon', 'Gligar', 'Gothita', 'Meditite', 'Misdreavus', 'Murkrow', 'Porygon', 'Scyther', 'Sneasel', 'Swirlix', 'Tangela', 'Trapinch', 'Vulpix-Base', 'Wingull', 'Yanma', @@ -164,7 +164,7 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['Pokemon', 'Standard', 'Swagger Clause', 'Same Type Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Swagger Clause', 'Same Type Clause', 'Team Preview'], banlist: [ 'Aegislash', 'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Dialga', 'Genesect', 'Gengar-Mega', 'Giratina', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega', 'Kartana', 'Kyogre', 'Kyurem-White', 'Lucario-Mega', 'Lugia', 'Lunala', 'Magearna', @@ -182,8 +182,7 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['Pokemon', 'Endless Battle Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Illegal', 'Unreleased'], + ruleset: ['Obtainable', 'Endless Battle Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7] 1v1", @@ -200,9 +199,9 @@ let Formats = [ battle: 1, }, allowMultisearch: true, - ruleset: ['Pokemon', 'Species Clause', 'Nickname Clause', 'Moody Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Accuracy Moves Clause', 'Swagger Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], + ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Moody Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Accuracy Moves Clause', 'Swagger Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], banlist: [ - 'Illegal', 'Unreleased', 'Arceus', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Deoxys-Defense', 'Dialga', 'Giratina', + 'Arceus', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Deoxys-Defense', 'Dialga', 'Giratina', 'Groudon', 'Ho-Oh', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-Black', 'Kyurem-White', 'Lugia', 'Lunala', 'Marshadow', 'Mewtwo', 'Mimikyu', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky', 'Snorlax', 'Solgaleo', 'Tapu Koko', 'Xerneas', 'Yveltal', 'Zekrom', 'Focus Sash', 'Perish Song', 'Detect + Fightinium Z', @@ -255,7 +254,7 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['[Gen 7] OU', 'Allow CAP'], + ruleset: ['[Gen 7] OU', '+CAP'], banlist: [ 'Aurumoth + Quiver Dance', 'Crucibelle + Head Smash', 'Crucibelle + Low Kick', 'Tomohawk + Earth Power', 'Tomohawk + Reflect', @@ -268,7 +267,7 @@ let Formats = [ mod: 'gen7', searchShow: false, maxLevel: 5, - ruleset: ['[Gen 7] LC', 'Allow CAP'], + ruleset: ['[Gen 7] LC', '+CAP'], }, { name: "[Gen 7] Battle Spot Singles", @@ -285,7 +284,7 @@ let Formats = [ validate: [3, 6], battle: 3, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], requirePentagon: true, }, { @@ -298,7 +297,7 @@ let Formats = [ validate: [3, 6], battle: 3, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], banlist: ['Sonic Boom', 'Dragon Rage', 'Type: Null', 'Poipole'], onValidateSet(set) { let allowedNonLittleCupMons = [ @@ -331,8 +330,7 @@ let Formats = [ validate: [3, 6], battle: 3, }, - ruleset: ['Pokemon', 'Nickname Clause', 'Team Preview', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal'], + ruleset: ['Obtainable', 'Nickname Clause', 'Team Preview', 'Cancel Mod'], }, { name: "[Gen 7] Custom Game", @@ -364,7 +362,7 @@ let Formats = [ mod: 'gen7', gameType: 'doubles', team: 'random', - ruleset: ['PotD', 'Pokemon', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['PotD', 'Obtainable', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7] Doubles OU", @@ -376,7 +374,7 @@ let Formats = [ mod: 'gen7', gameType: 'doubles', - ruleset: ['Pokemon', 'Standard Doubles', 'Swagger Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard Doubles', 'Swagger Clause', 'Team Preview'], banlist: ['DUber', 'Power Construct', 'Eevium Z', 'Dark Void', 'Gravity ++ Grass Whistle', 'Gravity ++ Hypnosis', 'Gravity ++ Lovely Kiss', 'Gravity ++ Sing', 'Gravity ++ Sleep Powder'], }, { @@ -385,7 +383,7 @@ let Formats = [ mod: 'gen7', gameType: 'doubles', - ruleset: ['Pokemon', 'Standard Doubles', 'Team Preview'], + ruleset: ['Obtainable', 'Standard Doubles', 'Team Preview'], banlist: ['Dark Void'], }, { @@ -408,7 +406,7 @@ let Formats = [ validate: [4, 6], battle: 4, }, - ruleset: ['Pokemon', 'Minimal GBU', 'VGC Timer'], + ruleset: ['Obtainable', 'Minimal GBU', 'VGC Timer'], banlist: ['Unown', 'Dragon Ascent', 'Custap Berry', 'Enigma Berry', 'Jaboca Berry', 'Micle Berry', 'Rowap Berry'], requirePlus: true, onValidateTeam(team) { @@ -438,7 +436,7 @@ let Formats = [ validate: [4, 6], battle: 4, }, - ruleset: ['Pokemon', 'Minimal GBU', 'VGC Timer'], + ruleset: ['Obtainable', 'Minimal GBU', 'VGC Timer'], banlist: ['Unown', 'Dragon Ascent'], requirePlus: true, onValidateTeam(team) { @@ -471,7 +469,7 @@ let Formats = [ validate: [4, 6], battle: 4, }, - ruleset: ['Pokemon', 'Minimal GBU', 'VGC Timer'], + ruleset: ['Obtainable', 'Minimal GBU', 'VGC Timer'], banlist: ['Unown'], requirePlus: true, onValidateTeam(team) { @@ -500,7 +498,7 @@ let Formats = [ battle: 4, }, timer: {starting: 5 * 60, addPerTurn: 0, maxPerTurn: 55, maxFirstTurn: 90, grace: 90, timeoutAutoChoose: true, dcTimerBank: false}, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], banlist: ['Unown', 'Custap Berry', 'Enigma Berry', 'Jaboca Berry', 'Micle Berry', 'Rowap Berry'], requirePlus: true, }, @@ -521,9 +519,9 @@ let Formats = [ battle: 4, }, timer: {starting: 15 * 60, addPerTurn: 0, maxPerTurn: 55, maxFirstTurn: 90, grace: 90, timeoutAutoChoose: true, dcTimerBank: false}, - ruleset: ['Pokemon', 'Species Clause', 'Nickname Clause', 'Item Clause', 'Team Preview', 'Cancel Mod', 'Alola Pokedex'], + ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Item Clause', 'Team Preview', 'Cancel Mod', 'Alola Pokedex'], banlist: [ - 'Illegal', 'Unreleased', 'Solgaleo', 'Lunala', 'Necrozma', 'Magearna', 'Marshadow', 'Zygarde', 'Mega', + 'Solgaleo', 'Lunala', 'Necrozma', 'Magearna', 'Marshadow', 'Zygarde', 'Mega', 'Custap Berry', 'Enigma Berry', 'Jaboca Berry', 'Micle Berry', 'Rowap Berry', ], requirePlus: true, @@ -543,7 +541,7 @@ let Formats = [ validate: [4, 6], battle: 4, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], requirePentagon: true, }, { @@ -560,7 +558,7 @@ let Formats = [ validate: [2, 4], battle: 2, }, - ruleset: ['Pokemon', 'Standard Doubles', 'Accuracy Moves Clause', 'Swagger Clause', 'Z-Move Clause', 'Sleep Clause Mod', 'Team Preview'], + ruleset: ['Obtainable', 'Standard Doubles', 'Accuracy Moves Clause', 'Swagger Clause', 'Z-Move Clause', 'Sleep Clause Mod', 'Team Preview'], banlist: [ 'Arceus', 'Dialga', 'Giratina', 'Groudon', 'Ho-Oh', 'Jirachi', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-White', 'Lugia', 'Lunala', 'Magearna', 'Marshadow', 'Mewtwo', 'Necrozma-Dawn-Wings', 'Necrozma-Dusk-Mane', 'Palkia', @@ -646,13 +644,11 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['[Gen 7] OU'], + ruleset: ['[Gen 7] OU', '!Obtainable Formes', '!Obtainable Abilities', '!Obtainable Moves'], banlist: [ 'Blacephalon', 'Chansey', 'Cresselia', 'Hoopa-Unbound', 'Kartana', 'Kyurem-Black', 'Regigigas', 'Shedinja', 'Slaking', 'Gyaradosite', 'Huge Power', 'Imposter', 'Innards Out', 'Pure Power', 'Speed Boost', 'Water Bubble', 'Assist', 'Chatter', 'Shell Smash', ], - noChangeForme: true, - noChangeAbility: true, // @ts-ignore getEvoFamily(species) { let template = Dex.getTemplate(species); @@ -682,29 +678,14 @@ let Formats = [ this.format.abilityMap = abilityMap; } - // @ts-ignore - this.format.noChangeForme = false; /** @type {string[]} */ let problems = []; - let pkmnRule = Dex.getFormat('pokemon'); - if (pkmnRule.exists && pkmnRule.onChangeSet && pkmnRule.onChangeSet.call(Dex, set, this.format)) { - problems = pkmnRule.onChangeSet.call(Dex, set, this.format) || []; - } - // @ts-ignore - this.format.noChangeForme = true; - - if (problems.length) return problems; let template = Dex.getTemplate(set.species); - if (!template.exists) return [`The Pokemon "${set.species}" does not exist.`]; - if (template.isUnreleased) return [`${template.species} is unreleased.`]; let megaTemplate = Dex.getTemplate(Dex.getItem(set.item).megaStone); if (template.tier === 'Uber' || megaTemplate.tier === 'Uber' || this.format.banlist.includes(template.species)) return [`${megaTemplate.tier === 'Uber' ? megaTemplate.species : template.species} is banned.`]; - let name = set.name; - let ability = Dex.getAbility(set.ability); - if (!ability.exists || ability.isNonstandard || ability.isUnreleased) return [`${name} needs to have a valid ability.`]; // @ts-ignore let pokemonWithAbility = this.format.abilityMap[ability.id]; if (!pokemonWithAbility) return [`"${set.ability}" is not available on a legal Pok\u00e9mon.`]; @@ -824,7 +805,7 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['Pokemon', 'Ability Clause', 'OHKO Clause', 'Evasion Moves Clause', 'CFZ Clause', 'Sleep Clause Mod', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], + ruleset: ['-Nonexistent', 'Ability Clause', 'OHKO Clause', 'Evasion Moves Clause', 'CFZ Clause', 'Sleep Clause Mod', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], banlist: ['Groudon-Primal', 'Rayquaza-Mega', 'Arena Trap', 'Contrary', 'Huge Power', 'Illusion', 'Innards Out', 'Magnet Pull', 'Moody', 'Parental Bond', 'Protean', 'Psychic Surge', 'Pure Power', 'Shadow Tag', 'Stakeout', 'Water Bubble', 'Wonder Guard', 'Gengarite', 'Chatter', 'Comatose + Sleep Talk'], }, { @@ -836,7 +817,7 @@ let Formats = [ ], mod: 'mixandmega', - ruleset: ['Pokemon', 'Standard', 'Mega Rayquaza Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Mega Rayquaza Clause', 'Team Preview'], banlist: ['Shadow Tag', 'Gengarite', 'Baton Pass', 'Electrify'], restrictedStones: ['Beedrillite', 'Blazikenite', 'Kangaskhanite', 'Mawilite', 'Medichamite', 'Pidgeotite', 'Ultranecrozium Z'], cannotMega: [ @@ -898,7 +879,7 @@ let Formats = [ ], mod: 'gen7', - ruleset: ['[Gen 7] OU', 'Ability Clause', 'Ignore Illegal Abilities'], + ruleset: ['[Gen 7] OU', 'Ability Clause', '!Obtainable Abilities'], banlist: ['Archeops', 'Dragonite', 'Hoopa-Unbound', 'Kartana', 'Keldeo', 'Kyurem-Black', 'Regigigas', 'Shedinja', 'Slaking', 'Terrakion', 'Victini', 'Weavile'], unbanlist: ['Aegislash', 'Genesect', 'Landorus', 'Metagross-Mega', 'Naganadel'], restrictedAbilities: [ @@ -1079,7 +1060,7 @@ let Formats = [ mod: 'gennext', searchShow: false, challengeShow: false, - ruleset: ['Pokemon', 'Standard NEXT', 'Team Preview'], + ruleset: ['Obtainable', 'Standard NEXT', 'Team Preview'], banlist: ['Uber'], }, @@ -1095,7 +1076,7 @@ let Formats = [ mod: 'letsgo', team: 'random', - ruleset: ['Pokemon', 'Allow AVs', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'Allow AVs', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7 Let's Go] OU", @@ -1105,8 +1086,8 @@ let Formats = [ mod: 'letsgo', forcedLevel: 50, - ruleset: ['Pokemon', 'Species Clause', 'Nickname Clause', 'Evasion Moves Clause', 'OHKO Clause', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], - banlist: ['Illegal', 'Unreleased', 'Uber'], + ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Evasion Moves Clause', 'OHKO Clause', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], + banlist: ['Uber'], }, { name: "[Gen 7 Let's Go] Singles No Restrictions", @@ -1116,8 +1097,7 @@ let Formats = [ mod: 'letsgo', searchShow: false, - ruleset: ['Pokemon', 'Allow AVs', 'Endless Battle Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Illegal', 'Unreleased'], + ruleset: ['Obtainable', 'Allow AVs', 'Endless Battle Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7 Let's Go] Custom Game", @@ -1140,8 +1120,8 @@ let Formats = [ mod: 'letsgo', gameType: 'doubles', forcedLevel: 50, - ruleset: ['Pokemon', 'Species Clause', 'Nickname Clause', 'Evasion Moves Clause', 'OHKO Clause', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], - banlist: ['Illegal', 'Unreleased', 'Mewtwo'], + ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Evasion Moves Clause', 'OHKO Clause', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], + banlist: ['Mewtwo'], }, { name: "[Gen 7 Let's Go] Doubles No Restrictions", @@ -1152,8 +1132,7 @@ let Formats = [ mod: 'letsgo', gameType: 'doubles', searchShow: false, - ruleset: ['Pokemon', 'Allow AVs', 'Endless Battle Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Illegal', 'Unreleased'], + ruleset: ['Obtainable', 'Allow AVs', 'Endless Battle Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod'], }, // Randomized Metas @@ -1169,7 +1148,7 @@ let Formats = [ mod: 'gen7', team: 'randomFactory', - ruleset: ['Pokemon', 'Sleep Clause Mod', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Mega Rayquaza Clause'], + ruleset: ['Obtainable', 'Sleep Clause Mod', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Mega Rayquaza Clause'], }, { name: "[Gen 7] BSS Factory", @@ -1184,14 +1163,14 @@ let Formats = [ validate: [3, 6], battle: 3, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], }, { name: "[Gen 7] Monotype Random Battle", mod: 'gen7', team: 'random', - ruleset: ['Pokemon', 'Same Type Clause', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'Same Type Clause', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7] Super Staff Bros Brawl", @@ -1235,7 +1214,7 @@ let Formats = [ teamLength: { battle: 1, }, - ruleset: ['Pokemon', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], + ruleset: ['Obtainable', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], }, { name: "[Gen 7] Challenge Cup 2v2", @@ -1247,7 +1226,7 @@ let Formats = [ battle: 2, }, searchShow: false, - ruleset: ['Pokemon', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], + ruleset: ['Obtainable', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], }, { name: "[Gen 7] Hackmons Cup", @@ -1255,7 +1234,7 @@ let Formats = [ mod: 'gen7', team: 'randomHC', - ruleset: ['Pokemon', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 7] Doubles Hackmons Cup", @@ -1264,14 +1243,14 @@ let Formats = [ gameType: 'doubles', team: 'randomHC', searchShow: false, - ruleset: ['Pokemon', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 6] Random Battle", mod: 'gen6', team: 'random', - ruleset: ['Pokemon', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 6] Battle Factory", @@ -1280,42 +1259,42 @@ let Formats = [ mod: 'gen6', team: 'randomFactory', searchShow: false, - ruleset: ['Pokemon', 'Sleep Clause Mod', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Mega Rayquaza Clause'], + ruleset: ['Obtainable', 'Sleep Clause Mod', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod', 'Mega Rayquaza Clause'], }, { name: "[Gen 5] Random Battle", mod: 'gen5', team: 'random', - ruleset: ['Pokemon', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 4] Random Battle", mod: 'gen4', team: 'random', - ruleset: ['Pokemon', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'Sleep Clause Mod', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 3] Random Battle", mod: 'gen3', team: 'random', - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], }, { name: "[Gen 2] Random Battle", mod: 'gen2', team: 'random', - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], }, { name: "[Gen 1] Random Battle", mod: 'gen1', team: 'random', - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], }, { name: "[Gen 1] Challenge Cup", @@ -1324,7 +1303,7 @@ let Formats = [ team: 'randomCC', searchShow: false, challengeShow: false, - ruleset: ['Pokemon', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'HP Percentage Mod', 'Cancel Mod'], }, // RoA Spotlight @@ -1343,7 +1322,7 @@ let Formats = [ mod: 'gen5', // searchShow: false, - ruleset: ['Pokemon', 'Team Preview', 'Standard Ubers'], + ruleset: ['Obtainable', 'Team Preview', 'Standard Ubers'], }, { name: "[Gen 6] Monotype", @@ -1354,7 +1333,7 @@ let Formats = [ mod: 'gen6', // searchShow: false, - ruleset: ['Pokemon', 'Standard', 'Swagger Clause', 'Same Type Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Swagger Clause', 'Same Type Clause', 'Team Preview'], banlist: [ 'Aegislash', 'Altaria-Mega', 'Arceus', 'Blaziken', 'Charizard-Mega-X', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Dialga', 'Genesect', 'Gengar-Mega', 'Giratina', 'Greninja', 'Groudon', 'Ho-Oh', 'Hoopa-Unbound', 'Kangaskhan-Mega', 'Kyogre', @@ -1373,7 +1352,7 @@ let Formats = [ mod: 'gen4', // searchShow: false, maxLevel: 5, - ruleset: ['Pokemon', 'Standard', 'Little Cup'], + ruleset: ['Obtainable', 'Standard', 'Little Cup'], banlist: [ 'LC Uber', 'Misdreavus', 'Murkrow', 'Scyther', 'Sneasel', 'Tangela', 'Yanma', 'Berry Juice', 'Deep Sea Tooth', 'Dragon Rage', 'Hypnosis', 'Sonic Boom', @@ -1396,7 +1375,7 @@ let Formats = [ ], mod: 'gen6', - ruleset: ['Pokemon', 'Standard', 'Team Preview', 'Swagger Clause'], + ruleset: ['Obtainable', 'Standard', 'Team Preview', 'Swagger Clause'], banlist: ['Uber', 'Arena Trap', 'Shadow Tag', 'Soul Dew', 'Baton Pass'], }, { @@ -1407,7 +1386,7 @@ let Formats = [ ], mod: 'gen5', - ruleset: ['Pokemon', 'Standard', 'Evasion Abilities Clause', 'Baton Pass Clause', 'Swagger Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Evasion Abilities Clause', 'Baton Pass Clause', 'Swagger Clause', 'Team Preview'], banlist: ['Uber', 'Arena Trap', 'Drizzle ++ Swift Swim', 'Drought ++ Chlorophyll', 'Sand Rush', 'Shadow Tag', 'Soul Dew'], }, { @@ -1419,7 +1398,7 @@ let Formats = [ ], mod: 'gen4', - ruleset: ['Pokemon', 'Standard', 'Baton Pass Clause'], + ruleset: ['Obtainable', 'Standard', 'Baton Pass Clause'], banlist: ['Uber', 'Sand Veil', 'Soul Dew'], }, { @@ -1430,7 +1409,7 @@ let Formats = [ ], mod: 'gen3', - ruleset: ['Pokemon', 'Standard', '3 Baton Pass Clause'], + ruleset: ['Obtainable', 'Standard', '3 Baton Pass Clause'], banlist: ['Uber', 'Smeargle + Baton Pass'], }, { @@ -1441,7 +1420,7 @@ let Formats = [ ], mod: 'gen2', - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], banlist: ['Uber'], }, { @@ -1452,7 +1431,7 @@ let Formats = [ ], mod: 'gen1', - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], banlist: ['Uber'], }, @@ -1472,7 +1451,7 @@ let Formats = [ mod: 'gen6', searchShow: false, - ruleset: ['Pokemon', 'Standard', 'Swagger Clause', 'Team Preview', 'Mega Rayquaza Clause'], + ruleset: ['Obtainable', 'Standard', 'Swagger Clause', 'Team Preview', 'Mega Rayquaza Clause'], }, { name: "[Gen 6] UU", @@ -1532,7 +1511,7 @@ let Formats = [ mod: 'gen6', searchShow: false, maxLevel: 5, - ruleset: ['Pokemon', 'Standard', 'Team Preview', 'Little Cup'], + ruleset: ['Obtainable', 'Standard', 'Team Preview', 'Little Cup'], banlist: ['LC Uber', 'Gligar', 'Misdreavus', 'Scyther', 'Sneasel', 'Tangela', 'Baton Pass', 'Dragon Rage', 'Sonic Boom', 'Swagger'], }, { @@ -1544,8 +1523,7 @@ let Formats = [ mod: 'gen6', searchShow: false, - ruleset: ['Pokemon', 'Endless Battle Clause', 'Team Preview', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Illegal', 'Unreleased'], + ruleset: ['Obtainable', 'Team Preview', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 6] 1v1", @@ -1560,9 +1538,9 @@ let Formats = [ validate: [1, 3], battle: 1, }, - ruleset: ['Pokemon', 'Nickname Clause', 'Moody Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Accuracy Moves Clause', 'Swagger Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], + ruleset: ['Obtainable', 'Nickname Clause', 'Moody Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Accuracy Moves Clause', 'Swagger Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod', 'Team Preview'], banlist: [ - 'Illegal', 'Unreleased', 'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Deoxys-Defense', + 'Arceus', 'Blaziken', 'Darkrai', 'Deoxys-Base', 'Deoxys-Attack', 'Deoxys-Defense', 'Dialga', 'Giratina', 'Groudon', 'Ho-Oh', 'Kangaskhan-Mega', 'Kyogre', 'Kyurem-White', 'Lugia', 'Mewtwo', 'Palkia', 'Rayquaza', 'Reshiram', 'Salamence-Mega', 'Shaymin-Sky', 'Xerneas', 'Yveltal', 'Zekrom', 'Focus Sash', 'Soul Dew', 'Perish Song', @@ -1578,7 +1556,7 @@ let Formats = [ mod: 'gen6', searchShow: false, - ruleset: ['[Gen 6] OU', 'Allow CAP'], + ruleset: ['[Gen 6] OU', '+CAP'], }, { name: "[Gen 6] Battle Spot Singles", @@ -1594,7 +1572,7 @@ let Formats = [ validate: [3, 6], battle: 3, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], requirePentagon: true, }, { @@ -1626,7 +1604,7 @@ let Formats = [ mod: 'gen6', gameType: 'doubles', searchShow: false, - ruleset: ['Pokemon', 'Standard Doubles', 'Swagger Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard Doubles', 'Swagger Clause', 'Team Preview'], banlist: ['DUber', 'Soul Dew', 'Dark Void', 'Gravity ++ Grass Whistle', 'Gravity ++ Hypnosis', 'Gravity ++ Lovely Kiss', 'Gravity ++ Sing', 'Gravity ++ Sleep Powder'], }, { @@ -1644,9 +1622,9 @@ let Formats = [ validate: [4, 6], battle: 4, }, - ruleset: ['Pokemon', 'Species Clause', 'Nickname Clause', 'Item Clause', 'Team Preview', 'Cancel Mod'], + ruleset: ['Obtainable', 'Species Clause', 'Nickname Clause', 'Item Clause', 'Team Preview', 'Cancel Mod'], banlist: [ - 'Illegal', 'Unreleased', 'Mew', 'Celebi', 'Jirachi', 'Deoxys', 'Deoxys-Attack', 'Deoxys-Defense', 'Deoxys-Speed', 'Phione', 'Manaphy', 'Darkrai', + 'Mew', 'Celebi', 'Jirachi', 'Deoxys', 'Deoxys-Attack', 'Deoxys-Defense', 'Deoxys-Speed', 'Phione', 'Manaphy', 'Darkrai', 'Shaymin', 'Shaymin-Sky', 'Arceus', 'Victini', 'Keldeo', 'Meloetta', 'Genesect', 'Diancie', 'Hoopa', 'Hoopa-Unbound', 'Volcanion', 'Soul Dew', ], requirePentagon: true, @@ -1675,7 +1653,7 @@ let Formats = [ validate: [4, 6], battle: 4, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], requirePentagon: true, }, { @@ -1705,7 +1683,7 @@ let Formats = [ teamLength: { validate: [6, 6], }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], requirePentagon: true, }, { @@ -1738,7 +1716,7 @@ let Formats = [ mod: 'gen5', searchShow: false, - ruleset: ['Pokemon', 'Standard', 'Evasion Abilities Clause', 'Baton Pass Clause', 'Swagger Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Evasion Abilities Clause', 'Baton Pass Clause', 'Swagger Clause', 'Team Preview'], banlist: ['Uber', 'OU', 'UUBL', 'Arena Trap', 'Drought', 'Sand Stream', 'Snow Warning'], }, { @@ -1775,7 +1753,7 @@ let Formats = [ mod: 'gen5', searchShow: false, maxLevel: 5, - ruleset: ['Pokemon', 'Standard', 'Team Preview', 'Little Cup'], + ruleset: ['Obtainable', 'Standard', 'Team Preview', 'Little Cup'], banlist: ['Berry Juice', 'Soul Dew', 'Dragon Rage', 'Sonic Boom', 'LC Uber', 'Sand Rush', 'Gligar', 'Murkrow', 'Scyther', 'Sneasel', 'Tangela'], }, { @@ -1802,7 +1780,7 @@ let Formats = [ validate: [1, 3], battle: 1, }, - ruleset: ['Pokemon', 'Standard', 'Baton Pass Clause', 'Swagger Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Baton Pass Clause', 'Swagger Clause', 'Team Preview'], banlist: ['Uber', 'Whimsicott', 'Focus Sash', 'Soul Dew', 'Perish Song'], unbanlist: ['Genesect', 'Landorus', 'Manaphy', 'Thundurus', 'Tornadus-Therian'], }, @@ -1816,7 +1794,7 @@ let Formats = [ validate: [3, 6], battle: 3, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], banlist: ['Dark Void', 'Sky Drop'], }, { @@ -1849,7 +1827,7 @@ let Formats = [ mod: 'gen5', gameType: 'doubles', searchShow: false, - ruleset: ['Pokemon', 'Standard', 'Evasion Abilities Clause', 'Swagger Clause', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Evasion Abilities Clause', 'Swagger Clause', 'Team Preview'], banlist: ['DUber', 'Soul Dew', 'Dark Void', 'Sky Drop'], }, { @@ -1863,7 +1841,7 @@ let Formats = [ validate: [4, 6], battle: 4, }, - ruleset: ['Pokemon', 'Standard GBU'], + ruleset: ['Obtainable', 'Standard GBU'], banlist: ['Dark Void', 'Sky Drop'], }, { @@ -1896,7 +1874,7 @@ let Formats = [ mod: 'gen4', searchShow: false, - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], banlist: ['Arceus'], }, { @@ -1929,8 +1907,7 @@ let Formats = [ mod: 'gen4', searchShow: false, - ruleset: ['Pokemon', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Illegal', 'Unreleased'], + ruleset: ['Obtainable', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 4] Custom Game", @@ -1993,7 +1970,7 @@ let Formats = [ mod: 'gen3', searchShow: false, - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], banlist: ['Wobbuffet + Leftovers'], }, { @@ -2005,7 +1982,7 @@ let Formats = [ mod: 'gen3', searchShow: false, - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], banlist: ['Uber', 'OU', 'UUBL', 'Smeargle + Ingrain'], }, { @@ -2037,7 +2014,7 @@ let Formats = [ gameType: 'doubles', searchShow: false, debug: true, - ruleset: ['Pokemon', 'HP Percentage Mod', 'Cancel Mod'], + ruleset: ['Obtainable', 'HP Percentage Mod', 'Cancel Mod'], }, { name: "[Gen 2] Ubers", @@ -2048,7 +2025,7 @@ let Formats = [ mod: 'gen2', searchShow: false, - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], }, { name: "[Gen 2] UU", @@ -2088,7 +2065,7 @@ let Formats = [ mod: 'gen1', searchShow: false, - ruleset: ['Pokemon', 'Standard'], + ruleset: ['Obtainable', 'Standard'], }, { name: "[Gen 1] UU", @@ -2111,8 +2088,8 @@ let Formats = [ mod: 'gen1', searchShow: false, - ruleset: ['Pokemon', 'Allow Tradeback', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Uber', 'Unreleased', 'Illegal', + ruleset: ['Obtainable', 'Allow Tradeback', 'Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod'], + banlist: ['Uber', 'Nidoking + Fury Attack + Thrash', 'Exeggutor + Poison Powder + Stomp', 'Exeggutor + Sleep Powder + Stomp', 'Exeggutor + Stun Spore + Stomp', 'Jolteon + Focus Energy + Thunder Shock', 'Flareon + Focus Energy + Ember', ], @@ -2122,7 +2099,7 @@ let Formats = [ mod: 'stadium', searchShow: false, - ruleset: ['Pokemon', 'Standard', 'Team Preview'], + ruleset: ['Obtainable', 'Standard', 'Team Preview'], banlist: ['Uber', 'Nidoking + Fury Attack + Thrash', 'Exeggutor + Poison Powder + Stomp', 'Exeggutor + Sleep Powder + Stomp', 'Exeggutor + Stun Spore + Stomp', 'Jolteon + Focus Energy + Thunder Shock', 'Flareon + Focus Energy + Ember', diff --git a/data/formats-data.js b/data/formats-data.js index 306ec7b36f..13fc639fc2 100644 --- a/data/formats-data.js +++ b/data/formats-data.js @@ -3471,12 +3471,6 @@ let BattleFormatsData = { randomDoubleBattleMoves: ["swordsdance", "willowisp", "xscissor", "shadowsneak", "shadowclaw", "protect"], eventPokemon: [ {"generation": 3, "level": 50, "moves": ["spite", "confuseray", "shadowball", "grudge"], "pokeball": "pokeball"}, - {"generation": 3, "level": 20, "shiny": 1, "moves": ["doubleteam", "furycutter", "screech"]}, - {"generation": 3, "level": 25, "shiny": 1, "moves": ["swordsdance"]}, - {"generation": 3, "level": 31, "shiny": 1, "moves": ["slash"]}, - {"generation": 3, "level": 38, "shiny": 1, "moves": ["agility"]}, - {"generation": 3, "level": 45, "shiny": 1, "moves": ["batonpass"]}, - {"generation": 4, "level": 52, "shiny": 1, "moves": ["xscissor"]}, ], tier: "(PU)", doublesTier: "(DUU)", @@ -7806,18 +7800,12 @@ let BattleFormatsData = { necrozmaduskmane: { randomBattleMoves: ["swordsdance", "sunsteelstrike", "photongeyser", "earthquake", "knockoff", "autotomize"], randomDoubleBattleMoves: ["swordsdance", "sunsteelstrike", "photongeyser", "earthquake", "knockoff", "rockslide"], - eventPokemon: [ - {"generation": 7, "level": 65, "moves": ["sunsteelstrike"]}, - ], eventOnly: true, tier: "Uber", doublesTier: "DUber", }, necrozmadawnwings: { randomBattleMoves: ["calmmind", "moongeistbeam", "photongeyser", "heatwave", "powergem", "trickroom"], - eventPokemon: [ - {"generation": 7, "level": 65, "moves": ["moongeistbeam"]}, - ], eventOnly: true, tier: "Uber", doublesTier: "DUber", diff --git a/data/learnsets.js b/data/learnsets.js index abdf8405c5..0bbf4e914c 100644 --- a/data/learnsets.js +++ b/data/learnsets.js @@ -11476,6 +11476,7 @@ let BattleLearnsets = { laserfocus: ["7T"], lowkick: ["7T", "6T", "5T", "4T"], lowsweep: ["7M", "6M", "5M"], + machpunch: ["3C"], meditate: ["7L5", "7L1", "7V", "7V", "6L5", "5L5", "4L5", "3L6"], megakick: ["7L53", "7L1", "7V", "7V", "6L1", "5L53", "4L49", "3T", "3L46", "3S0"], megapunch: ["7V", "3T"], @@ -11557,6 +11558,7 @@ let BattleLearnsets = { headbutt: ["7V", "4T"], helpinghand: ["7T", "6T", "5T", "4T", "3S0"], hiddenpower: ["7M", "7V", "6M", "5M", "4M", "3M"], + highjumpkick: ["3C"], icepunch: ["7T", "7L36", "7V", "7V", "6T", "6L36", "5T", "5L36", "4T", "4L31", "3T", "3L26"], laserfocus: ["7T"], lowkick: ["7T", "6T", "5T", "4T"], @@ -11638,6 +11640,7 @@ let BattleLearnsets = { headbutt: ["7V", "4T"], helpinghand: ["7T", "6T", "5T", "5S0", "4T"], hiddenpower: ["7M", "7V", "6M", "5M", "4M", "3M"], + highjumpkick: ["3C"], laserfocus: ["7T"], lowkick: ["7T", "6T", "5T", "4T"], lowsweep: ["7M", "6M", "5M"], @@ -18804,6 +18807,7 @@ let BattleLearnsets = { metronome: ["7L5", "7L1", "7V", "6L1", "5L1", "4L1", "3T", "3L1"], mimic: ["3T"], mudslap: ["7V", "4T", "3T"], + nastyplot: ["5C", "4C"], naturalgift: ["4M"], ominouswind: ["4T"], protect: ["7M", "7V", "6M", "5M", "4M", "3M"], @@ -27318,23 +27322,23 @@ let BattleLearnsets = { shedinja: {learnset: { absorb: ["7L5", "7L1"], aerialace: ["7M", "6M", "5M", "4M", "3M"], - agility: ["3S4"], + agility: ["4R", "3R"], allyswitch: ["7T"], - batonpass: ["3S5"], + batonpass: ["4R", "3R"], bugbite: ["7T", "6T", "5T", "4T"], confide: ["7M", "6M"], confuseray: ["7L29", "6L29", "5L31", "4L31", "3L31", "3S0"], cut: ["6M", "5M", "4M", "3M"], dig: ["6M", "5M", "4M", "3M"], doubleedge: ["3T"], - doubleteam: ["7M", "6M", "5M", "4M", "3M", "3S1"], + doubleteam: ["7M", "6M", "5M", "4M", "3M"], dreameater: ["7M", "6M", "5M", "4M", "3T"], endure: ["4M", "3T"], facade: ["7M", "6M", "5M", "4M", "3M"], falseswipe: ["7M", "6M", "5M", "4M"], flash: ["6M", "5M", "4M", "3M"], frustration: ["7M", "6M", "5M", "4M", "3M"], - furycutter: ["4T", "3T", "3S1"], + furycutter: ["4T", "3T"], furyswipes: ["7L13", "6L13", "5L14", "4L14", "3L14"], gigadrain: ["7T", "6T", "5T", "4M", "3M"], gigaimpact: ["7M", "6M", "5M", "4M"], @@ -27358,12 +27362,12 @@ let BattleLearnsets = { sandattack: ["7L9", "7L1", "6L9", "5L9", "4L9", "3L9"], sandstorm: ["7M", "6M", "5M", "4M", "3M"], scratch: ["7L1", "6L1", "5L1", "4L1", "3L1"], - screech: ["3S1"], + screech: ["4R", "3R"], secretpower: ["6M", "4M", "3M"], shadowball: ["7M", "7L33", "6M", "6L33", "5M", "5L59", "4M", "4L59", "3M", "3L38", "3S0"], shadowclaw: ["7M", "6M", "5M", "4M"], shadowsneak: ["7L21", "6L21", "5L38", "4L38"], - slash: ["3S3"], + slash: ["4R", "3R"], sleeptalk: ["7M", "6M", "5T", "4M", "3T"], snore: ["7T", "6T", "5T", "4T", "3T"], solarbeam: ["7M", "6M", "5M", "4M", "3M"], @@ -27374,13 +27378,13 @@ let BattleLearnsets = { suckerpunch: ["4T"], sunnyday: ["7M", "6M", "5M", "4M", "3M"], swagger: ["7M", "6M", "5M", "4M", "3T"], - swordsdance: ["3S2"], + swordsdance: ["4R", "3R"], telekinesis: ["7T", "5M"], thief: ["7M", "6M", "5M", "4M", "3M"], toxic: ["7M", "6M", "5M", "4M", "3M"], trick: ["7T", "6T", "5T", "4T"], willowisp: ["7M", "6M", "5M", "4M"], - xscissor: ["7M", "6M", "5M", "4M", "4S6"], + xscissor: ["7M", "6M", "5M", "4M"], }}, whismur: {learnset: { astonish: ["7L8", "6L8", "5L11", "4L11", "3L11"], @@ -39483,19 +39487,19 @@ let BattleLearnsets = { willowisp: ["7M", "6M", "5M", "4M"], }}, rotomheat: {learnset: { - overheat: ["7L1", "6L1", "5T", "4T"], + overheat: ["7R", "6R", "5R", "4R"], }}, rotomwash: {learnset: { - hydropump: ["7L1", "6L1", "5T", "4T"], + hydropump: ["7R", "6R", "5R", "4R"], }}, rotomfrost: {learnset: { - blizzard: ["7L1", "6L1", "5T", "4T"], + blizzard: ["7R", "6R", "5R", "4R"], }}, rotomfan: {learnset: { - airslash: ["7L1", "6L1", "5T", "4T"], + airslash: ["7R", "6R", "5R", "4R"], }}, rotommow: {learnset: { - leafstorm: ["7L1", "6L1", "5T", "4T"], + leafstorm: ["7R", "6R", "5R", "4R"], }}, uxie: {learnset: { acrobatics: ["7M", "6M", "5M"], @@ -60779,160 +60783,10 @@ let BattleLearnsets = { xscissor: ["7M"], }}, necrozmaduskmane: {learnset: { - aerialace: ["7M"], - allyswitch: ["7T"], - autotomize: ["7L47"], - brickbreak: ["7M"], - brutalswing: ["7M"], - bulldoze: ["7M"], - calmmind: ["7M"], - chargebeam: ["7M", "7L1"], - confide: ["7M"], - confusion: ["7L1"], - darkpulse: ["7M"], - doubleteam: ["7M"], - dragonpulse: ["7T"], - earthpower: ["7T"], - earthquake: ["7M"], - embargo: ["7M"], - facade: ["7M"], - flashcannon: ["7M"], - fling: ["7M"], - frustration: ["7M"], - gigaimpact: ["7M"], - gravity: ["7T", "7L31"], - gyroball: ["7M"], - heatwave: ["7T"], - hiddenpower: ["7M"], - hyperbeam: ["7M"], - hypervoice: ["7T"], - irondefense: ["7T", "7L59"], - ironhead: ["7T"], - knockoff: ["7T"], - lightscreen: ["7M"], - magnetrise: ["7T"], - metalclaw: ["7L1"], - mirrorshot: ["7L1"], - moonlight: ["7L1"], - morningsun: ["7L1"], - nightslash: ["7L23"], - outrage: ["7T"], - photongeyser: ["7L50"], - powergem: ["7L43"], - prismaticlaser: ["7L73"], - protect: ["7M"], - psychic: ["7M"], - psychocut: ["7L37"], - psyshock: ["7M"], - recycle: ["7T"], - reflect: ["7M"], - rest: ["7M"], - return: ["7M"], - rockblast: ["7L19"], - rockpolish: ["7M"], - rockslide: ["7M"], - rocktomb: ["7M"], - round: ["7M"], - shadowclaw: ["7M"], - shockwave: ["7T"], - signalbeam: ["7T"], - slash: ["7L7"], - sleeptalk: ["7M"], - smartstrike: ["7M"], - snore: ["7T"], - solarbeam: ["7M"], - stealthrock: ["7T", "7L53"], - stoneedge: ["7M"], - storedpower: ["7L13"], - substitute: ["7M"], - sunsteelstrike: ["7S0"], - swagger: ["7M"], - swordsdance: ["7M"], - telekinesis: ["7T"], - thief: ["7M"], - thunderwave: ["7M"], - toxic: ["7M"], - trickroom: ["7M"], - wringout: ["7L67"], - xscissor: ["7M"], + sunsteelstrike: ["7R"], }}, necrozmadawnwings: {learnset: { - aerialace: ["7M"], - allyswitch: ["7T"], - autotomize: ["7L47"], - brickbreak: ["7M"], - brutalswing: ["7M"], - bulldoze: ["7M"], - calmmind: ["7M"], - chargebeam: ["7M", "7L1"], - confide: ["7M"], - confusion: ["7L1"], - darkpulse: ["7M"], - doubleteam: ["7M"], - dragonpulse: ["7T"], - earthpower: ["7T"], - earthquake: ["7M"], - embargo: ["7M"], - facade: ["7M"], - flashcannon: ["7M"], - fling: ["7M"], - frustration: ["7M"], - gigaimpact: ["7M"], - gravity: ["7T", "7L31"], - gyroball: ["7M"], - heatwave: ["7T"], - hiddenpower: ["7M"], - hyperbeam: ["7M"], - hypervoice: ["7T"], - irondefense: ["7T", "7L59"], - ironhead: ["7T"], - knockoff: ["7T"], - lightscreen: ["7M"], - magnetrise: ["7T"], - metalclaw: ["7L1"], - mirrorshot: ["7L1"], - moongeistbeam: ["7S0"], - moonlight: ["7L1"], - morningsun: ["7L1"], - nightslash: ["7L23"], - outrage: ["7T"], - photongeyser: ["7L50"], - powergem: ["7L43"], - prismaticlaser: ["7L73"], - protect: ["7M"], - psychic: ["7M"], - psychocut: ["7L37"], - psyshock: ["7M"], - recycle: ["7T"], - reflect: ["7M"], - rest: ["7M"], - return: ["7M"], - rockblast: ["7L19"], - rockpolish: ["7M"], - rockslide: ["7M"], - rocktomb: ["7M"], - round: ["7M"], - shadowclaw: ["7M"], - shockwave: ["7T"], - signalbeam: ["7T"], - slash: ["7L7"], - sleeptalk: ["7M"], - smartstrike: ["7M"], - snore: ["7T"], - solarbeam: ["7M"], - stealthrock: ["7T", "7L53"], - stoneedge: ["7M"], - storedpower: ["7L13"], - substitute: ["7M"], - swagger: ["7M"], - swordsdance: ["7M"], - telekinesis: ["7T"], - thief: ["7M"], - thunderwave: ["7M"], - toxic: ["7M"], - trickroom: ["7M"], - wringout: ["7L67"], - xscissor: ["7M"], + moongeistbeam: ["7R"], }}, magearna: {learnset: { afteryou: ["7T"], diff --git a/data/mods/gen1/rulesets.js b/data/mods/gen1/rulesets.js index 2b197e6e67..edd519b95b 100644 --- a/data/mods/gen1/rulesets.js +++ b/data/mods/gen1/rulesets.js @@ -2,58 +2,15 @@ /**@type {{[k: string]: ModdedFormatsData}} */ let BattleFormats = { - pokemon: { - effectType: 'ValidatorRule', - name: 'Pokemon', - onValidateSet(set, format) { - let template = this.getTemplate(set.species); - let problems = []; - if (set.species === set.name) delete set.name; - - if (template.gen > this.gen) { - problems.push(set.species + ' does not exist in gen ' + this.gen + '.'); - } else if (template.isNonstandard) { - problems.push(set.species + ' is not a real Pokemon.'); - } - if (set.moves) { - for (const setMoveid of set.moves) { - let move = this.getMove(setMoveid); - if (move.gen > this.gen) { - problems.push(move.name + ' does not exist in gen ' + this.gen + '.'); - } else if (move.isNonstandard) { - problems.push(move.name + ' is not a real move.'); - } - } - } - if (set.moves && set.moves.length > 4) { - problems.push((set.name || set.species) + ' has more than four moves.'); - } - - if (set.evs) set.evs['spd'] = set.evs['spa']; - if (set.ivs) set.ivs['spd'] = set.ivs['spa']; - - // Let's manually delete items. - set.item = ''; - - // Automatically set ability to None - set.ability = 'None'; - - // They also get a useless nature, since that didn't exist - set.nature = 'Serious'; - - // No shinies - set.shiny = false; - - return problems; - }, - }, - standard: { - effectType: 'ValidatorRule', - name: 'Standard', - ruleset: ['Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal', 'Dig', 'Fly', + validatemoves: { + inherit: true, + banlist: [ + // https://www.smogon.com/forums/threads/implementing-all-old-gens-in-ps-testers-required.3483261/post-5420130 + // confirmed by Marty 'Kakuna + Poison Sting + Harden', 'Kakuna + String Shot + Harden', 'Beedrill + Poison Sting + Harden', 'Beedrill + String Shot + Harden', + + // https://www.smogon.com/forums/threads/rby-and-gsc-illegal-movesets.78638/ 'Nidoking + Fury Attack + Thrash', 'Exeggutor + Poison Powder + Stomp', 'Exeggutor + Sleep Powder + Stomp', 'Exeggutor + Stun Spore + Stomp', 'Eevee + Tackle + Growl', @@ -61,22 +18,12 @@ let BattleFormats = { 'Jolteon + Tackle + Growl', 'Jolteon + Focus Energy + Thunder Shock', 'Flareon + Tackle + Growl', 'Flareon + Focus Energy + Ember', ], - onValidateSet(set) { - // limit one of each move in Standard - let moves = []; - if (set.moves) { - /**@type {{[k: string]: true}} */ - let hasMove = {}; - for (const setMoveid of set.moves) { - let move = this.getMove(setMoveid); - let moveid = move.id; - if (hasMove[moveid]) continue; - hasMove[moveid] = true; - moves.push(setMoveid); - } - } - set.moves = moves; - }, + }, + standard: { + effectType: 'ValidatorRule', + name: 'Standard', + ruleset: ['Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod'], + banlist: ['Dig', 'Fly'], }, }; diff --git a/data/mods/gen2/rulesets.js b/data/mods/gen2/rulesets.js index 07582acc3d..79d3c40092 100644 --- a/data/mods/gen2/rulesets.js +++ b/data/mods/gen2/rulesets.js @@ -2,67 +2,9 @@ /**@type {{[k: string]: ModdedFormatsData}} */ let BattleFormats = { - pokemon: { - effectType: 'ValidatorRule', - name: 'Pokemon', - onValidateSet(set, format) { - let template = this.getTemplate(set.species); - let problems = []; - if (set.species === set.name) delete set.name; - - if (template.gen > this.gen) { - problems.push(set.species + ' does not exist in gen ' + this.gen + '.'); - } else if (template.isNonstandard) { - problems.push(set.species + ' is not a real Pokemon.'); - } - let hasSD = false; - if (set.item) { - let item = this.getItem(set.item); - if (item.gen > this.gen) { - problems.push(item.name + ' does not exist in gen ' + this.gen + '.'); - } else if (item.isNonstandard) { - problems.push(item.name + ' is not a real item.'); - } - } - if (set.moves) { - for (const setMoveid of set.moves) { - let move = this.getMove(setMoveid); - if (move.gen > this.gen) { - problems.push(move.name + ' does not exist in gen ' + this.gen + '.'); - } else if (move.isNonstandard) { - problems.push(move.name + ' is not a real move.'); - } - if (move.id === 'swordsdance') hasSD = true; - } - } - if (set.moves && set.moves.length > 4) { - problems.push((set.name || set.species) + ' has more than four moves.'); - } - - // Automatically set ability to None - set.ability = 'None'; - - if (set.ivs && toID(set.item) === 'thickclub' && set.species === 'Marowak' && hasSD && (!set.level || set.level === 100)) { - if (!set.evs) set.evs = {hp: 252, atk: 252, def: 252, spa: 252, spd: 252, spe: 252}; - if (set.evs.atk === undefined) set.evs.atk = 252; - if (set.ivs.atk === undefined) set.ivs.atk = 30; - set.ivs.atk = Math.floor(set.ivs.atk / 2) * 2; - while (set.evs.atk > 0 && 2 * 80 + set.ivs.atk + Math.floor(set.evs.atk / 4) + 5 > 255) { - set.evs.atk -= 4; - } - } - - // They all also get a useless nature, since that didn't exist - set.nature = 'Serious'; - - return problems; - }, - }, - standard: { - effectType: 'ValidatorRule', - name: 'Standard', - ruleset: ['Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal', + validatemoves: { + inherit: true, + banlist: [ 'Hypnosis + Mean Look', 'Hypnosis + Spider Web', 'Lovely Kiss + Mean Look', @@ -74,22 +16,11 @@ let BattleFormats = { 'Spore + Mean Look', 'Spore + Spider Web', ], - onValidateSet(set) { - // limit one of each move in Standard - let moves = []; - if (set.moves) { - /**@type {{[k: string]: true}} */ - let hasMove = {}; - for (const setMoveid of set.moves) { - let move = this.getMove(setMoveid); - let moveid = move.id; - if (hasMove[moveid]) continue; - hasMove[moveid] = true; - moves.push(setMoveid); - } - } - set.moves = moves; - }, + }, + standard: { + effectType: 'ValidatorRule', + name: 'Standard', + ruleset: ['Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'HP Percentage Mod', 'Cancel Mod'], }, }; diff --git a/data/mods/gen3/rulesets.js b/data/mods/gen3/rulesets.js index d6434e013c..19fa519079 100644 --- a/data/mods/gen3/rulesets.js +++ b/data/mods/gen3/rulesets.js @@ -7,7 +7,6 @@ let BattleFormats = { name: 'Standard', desc: "The standard ruleset for all offical Smogon singles tiers (Ubers, OU, etc.)", ruleset: ['Sleep Clause Mod', 'Switch Priority Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal'], }, }; diff --git a/data/mods/gen4/rulesets.js b/data/mods/gen4/rulesets.js index 8b2ee5d7c4..6facb00d96 100644 --- a/data/mods/gen4/rulesets.js +++ b/data/mods/gen4/rulesets.js @@ -2,10 +2,9 @@ /**@type {{[k: string]: ModdedFormatsData}} */ let BattleFormats = { - pokemon: { + validatestats: { inherit: true, - onValidateSet(set, format) { - if (!format || !this.getRuleTable(format).has('-illegal')) return; + onValidateSet(set) { let template = this.getTemplate(set.species); let item = this.getItem(set.item); if (item && item.id === 'griseousorb' && template.num !== 487) { diff --git a/data/mods/gen5/rulesets.js b/data/mods/gen5/rulesets.js index 2e0aa1127c..bdd71190a3 100644 --- a/data/mods/gen5/rulesets.js +++ b/data/mods/gen5/rulesets.js @@ -2,7 +2,7 @@ /**@type {{[k: string]: ModdedFormatsData}} */ let BattleFormats = { - pokemon: { + validatemoves: { inherit: true, banlist: [ 'Chansey + Charm + Seismic Toss', diff --git a/data/mods/letsgo/rulesets.js b/data/mods/letsgo/rulesets.js index 2d9fa8c2f3..d5fc157425 100644 --- a/data/mods/letsgo/rulesets.js +++ b/data/mods/letsgo/rulesets.js @@ -2,177 +2,11 @@ /**@type {{[k: string]: ModdedFormatsData}} */ let BattleFormats = { - pokemon: { - effectType: 'ValidatorRule', - name: 'Pokemon', - onValidateTeam(team, format) { - let problems = []; - if (team.length > 6) problems.push('Your team has more than six Pok\u00E9mon.'); - // Unlike Pokemon like Kyurem-B and Kyurem-W, the two Starter Pokemon cannot be hacked onto other games. - let hasStarter = 0; - for (const set of team) { - if (set.species === 'Pikachu-Starter' || set.species === 'Eevee-Starter') { - hasStarter++; - if (hasStarter > 1) { - problems.push(`You can only have one of Pikachu-Starter or Eevee-Starter on a team.`); - break; - } - } - } - return problems; - }, - onChangeSet(set, format) { - let template = this.getTemplate(set.species); - let baseTemplate = this.getTemplate(template.baseSpecies); - let problems = []; - let allowAVs = !!(format && this.getRuleTable(format).has('allowavs')); - let allowCAP = !!(format && this.getRuleTable(format).has('allowcap')); - - if (set.species === set.name) delete set.name; - const validNum = (baseTemplate.num <= 151 && baseTemplate.num >= 1) || [808, 809].includes(baseTemplate.num); - if (!validNum) { - problems.push( - `Only Pok\u00E9mon whose base formes are from Gen 1, Meltan, and Melmetal can be used.`, - `(${set.species} is from Gen ${baseTemplate.gen === 1 ? 7 : baseTemplate.gen}.)` - ); - } - if (template.forme && (!['Alola', 'Mega', 'Mega-X', 'Mega-Y', 'Starter'].includes(template.forme) || template.species === 'Pikachu-Alola')) { - problems.push(`${set.species}'s forme ${template.forme} is not available in Let's Go.`); - } - if (set.moves) { - for (const moveid of set.moves) { - let move = this.getMove(moveid); - if (move.gen > this.gen) { - problems.push(move.name + ' does not exist in gen ' + this.gen + '.'); - } else if (!allowCAP && move.isNonstandard) { - problems.push(move.name + ' does not exist.'); - } - } - } - if (set.moves && set.moves.length > 4) { - problems.push((set.name || set.species) + ' has more than four moves.'); - } - if (set.level && set.level > 100) { - problems.push((set.name || set.species) + ' is higher than level 100.'); - } - - if (!allowCAP || !template.tier.startsWith('CAP')) { - if (template.isNonstandard && template.num > -5000) { - problems.push(set.species + ' does not exist.'); - } - } - - if (!allowAVs && set.evs) { - const statNames = {hp: 'HP', atk: 'Attack', def: 'Defense', spa: 'Special Attack', spd: 'Special Defense', spe: 'Speed'}; - for (let k in set.evs) { - // @ts-ignore - if (set.evs[k]) { - // @ts-ignore - problems.push(`${set.name || set.species} has ${set.evs[k]} AVs/EVs in ${statNames[k]}, but AVs and EVs are not allowed in this format.`); - break; - } - // @ts-ignore - set.evs[k] = 0; - } - } - - set.ability = 'No Ability'; - // Temporary hack to allow mega evolution - if (set.item) { - let item = this.getItem(set.item); - if (item.megaEvolves !== template.baseSpecies) { - problems.push(`Items aren't allowed in Let's Go.`); - } - } - - if (!set.happiness || set.happiness !== 70) { - set.happiness = 70; - } - - // ----------- legality line ------------------------------------------ - if (!this.getRuleTable(format).has('-illegal')) return problems; - // everything after this line only happens if we're doing legality enforcement - - // Pokestar studios - if (template.num <= -5000 && template.isNonstandard) { - problems.push(`${set.species} cannot be obtained by legal means.`); - } - - // Legendary Pokemon must have at least 3 perfect IVs in gen 6 - if (set.ivs && this.gen >= 6 && (baseTemplate.gen >= 6 || format.requirePentagon) && (template.eggGroups[0] === 'Undiscovered' || template.species === 'Manaphy') && !template.prevo && !template.nfe && - // exceptions - template.species !== 'Unown' && template.baseSpecies !== 'Pikachu' && (template.baseSpecies !== 'Diancie' || !set.shiny)) { - let perfectIVs = 0; - for (let i in set.ivs) { - // @ts-ignore - if (set.ivs[i] >= 31) perfectIVs++; - } - let reason = (format.requirePentagon ? " and this format requires gen " + this.gen + " Pokémon" : " in gen 6"); - if (perfectIVs < 3) problems.push((set.name || set.species) + " must have at least three perfect IVs because it's a legendary" + reason + "."); - } - - // limit one of each move - let moves = []; - if (set.moves) { - /**@type {{[k: string]: true}} */ - let hasMove = {}; - for (const moveId of set.moves) { - let move = this.getMove(moveId); - let moveid = move.id; - if (hasMove[moveid]) continue; - hasMove[moveid] = true; - moves.push(moveId); - } - } - set.moves = moves; - - let battleForme = template.battleOnly && template.species; - if (battleForme) { - if (template.isMega) set.species = template.baseSpecies; - if (template.requiredMove && !set.moves.includes(toID(template.requiredMove))) { - problems.push(`${template.species} transforms in-battle with ${template.requiredMove}.`); // Meloetta-Pirouette, Rayquaza-Mega - } - } else { - if (template.requiredMove && !set.moves.includes(toID(template.requiredMove))) { - problems.push(`${(set.name || set.species)} needs to have the move ${template.requiredMove}.`); // Keldeo-Resolute - } - } - - return problems; - }, - }, allowavs: { effectType: 'ValidatorRule', name: 'Allow AVs', desc: "Tells formats with the 'letsgo' mod to take Awakening Values into consideration when calculating stats", - onChangeSet(set, format) { - /**@type {string[]} */ - let problems = ([]); - let avs = /** @type {StatsTable} */(this.getAwakeningValues(set)); - if (set.evs) { - for (let k in set.evs) { - // @ts-ignore - avs[k] = set.evs[k]; - // @ts-ignore - if (typeof avs[k] !== 'number' || avs[k] < 0) { - // @ts-ignore - avs[k] = 0; - } - } - } - - // Pokemon cannot have more than 200 Awakening Values in a stat. It is impossible to hack more than 200 AVs onto a stat, so legality doesn't matter. - for (let av in avs) { - let statNames = {hp: 'HP', atk: 'Attack', def: 'Defense', spa: 'Special Attack', spd: 'Special Defense', spe: 'Speed'}; - // @ts-ignore - if (avs[av] > 200) { - // @ts-ignore - problems.push(`${set.name || set.species} has more than 200 Awakening Values in its ${statNames[av]}.`); - } - } - return problems; - }, - // Partially implemented in the modified pokemon rule above + // implemented in TeamValidator#validateStats }, }; diff --git a/data/mods/stadium/rulesets.js b/data/mods/stadium/rulesets.js index cc21291a77..4deeaab14d 100644 --- a/data/mods/stadium/rulesets.js +++ b/data/mods/stadium/rulesets.js @@ -6,23 +6,6 @@ let BattleFormats = { effectType: 'ValidatorRule', name: 'Standard', ruleset: ['Sleep Clause Mod', 'Freeze Clause Mod', 'Species Clause', 'OHKO Clause', 'Evasion Moves Clause', 'Exact HP Mod', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal'], - onValidateSet(set) { - // limit one of each move in Standard - let moves = []; - if (set.moves) { - /**@type {{[k: string]: true}} */ - let hasMove = {}; - for (const setMoveid of set.moves) { - let move = this.getMove(setMoveid); - let moveid = move.id; - if (hasMove[moveid]) continue; - hasMove[moveid] = true; - moves.push(setMoveid); - } - } - set.moves = moves; - }, }, }; diff --git a/data/rulesets.js b/data/rulesets.js index e15355ac3b..7f56e66ea8 100644 --- a/data/rulesets.js +++ b/data/rulesets.js @@ -14,28 +14,26 @@ let BattleFormats = { name: 'Standard', desc: "The standard ruleset for all offical Smogon singles tiers (Ubers, OU, etc.)", ruleset: ['Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal'], }, standardnext: { effectType: 'ValidatorRule', name: 'Standard NEXT', desc: "The standard ruleset for the NEXT mod", - ruleset: ['Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Illegal', 'Soul Dew'], + ruleset: ['+Unreleased', 'Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'OHKO Clause', 'HP Percentage Mod', 'Cancel Mod'], + banlist: ['Soul Dew'], }, standardubers: { effectType: 'ValidatorRule', name: 'Standard Ubers', desc: "The standard ruleset for [Gen 5] Ubers", ruleset: ['Sleep Clause Mod', 'Species Clause', 'Nickname Clause', 'Moody Clause', 'OHKO Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal'], }, standardgbu: { effectType: 'ValidatorRule', name: 'Standard GBU', desc: "The standard ruleset for all official in-game Pokémon tournaments and Battle Spot", ruleset: ['Species Clause', 'Nickname Clause', 'Item Clause', 'Team Preview', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal', 'Battle Bond', + banlist: ['Battle Bond', 'Mewtwo', 'Mew', 'Lugia', 'Ho-Oh', 'Celebi', 'Kyogre', 'Groudon', 'Rayquaza', 'Jirachi', 'Deoxys', @@ -55,7 +53,7 @@ let BattleFormats = { name: 'Minimal GBU', desc: "The standard ruleset for official tournaments, but without Restricted Legendary bans", ruleset: ['Species Clause', 'Nickname Clause', 'Item Clause', 'Team Preview', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal', 'Battle Bond', + banlist: ['Battle Bond', 'Mew', 'Celebi', 'Jirachi', 'Deoxys', @@ -75,137 +73,70 @@ let BattleFormats = { name: 'Standard Doubles', desc: "The standard ruleset for all official Smogon doubles tiers", ruleset: ['Species Clause', 'Nickname Clause', 'OHKO Clause', 'Moody Clause', 'Evasion Abilities Clause', 'Evasion Moves Clause', 'Endless Battle Clause', 'HP Percentage Mod', 'Cancel Mod'], - banlist: ['Unreleased', 'Illegal'], }, - pokemon: { + validate: { effectType: 'ValidatorRule', - name: 'Pokemon', - desc: "Applies the basic limitations of pokemon games: level 100, 6 pokemon, 4 moves, no CAP, no future-gen pokemon/moves/etc - but does not include illegal move/ability validation", - onValidateTeam(team, format) { - let problems = []; - if (team.length > 6) problems.push('Your team has more than six Pok\u00E9mon.'); - // ----------- legality line ------------------------------------------ - if (!format || !this.getRuleTable(format).has('-illegal')) return problems; - // everything after this line only happens if we're doing legality enforcement - let kyurems = 0; - let ndm = 0; - let ndw = 0; + name: 'Obtainable', + desc: "Makes sure the team is possible to obtain in-game.", + ruleset: ['Obtainable Moves', 'Obtainable Abilities', 'Obtainable Formes', 'Obtainable Misc'], + banlist: ['Unreleased', 'Nonexistent'], + }, + validatemoves: { + effectType: 'ValidatorRule', + name: 'Obtainable Moves', + desc: "Makes sure moves are learnable by the species.", + banlist: [ + 'Chansey + Charm + Seismic Toss', 'Chansey + Charm + Psywave', + 'Blissey + Charm + Seismic Toss', 'Blissey + Charm + Psywave', + 'Shiftry + Leaf Blade + Sucker Punch', + ], + // Mostly hardcoded in team-validator.ts + }, + validateabilities: { + effectType: 'ValidatorRule', + name: 'Obtainable Abilities', + desc: "Makes sure abilities match the species.", + // Hardcoded in team-validator.ts + }, + validateformes: { + effectType: 'ValidatorRule', + name: 'Obtainable Formes', + desc: "Makes sure in-battle formes only appear in-battle.", + // Mostly hardcoded in team-validator.ts + onValidateTeam(team) { + let kyuremCount = 0; + let necrozmaDMCount = 0; + let necrozmaDWCount = 0; for (const set of team) { if (set.species === 'Kyurem-White' || set.species === 'Kyurem-Black') { - if (kyurems > 0) { - problems.push('You cannot have more than one Kyurem-Black/Kyurem-White.'); - break; + if (kyuremCount > 0) { + return ['You cannot have more than one Kyurem-Black/Kyurem-White.']; } - kyurems++; + kyuremCount++; } if (set.species === 'Necrozma-Dusk-Mane') { - if (ndm > 0) { - problems.push('You cannot have more than one Necrozma-Dusk-Mane.'); - break; + if (necrozmaDMCount > 0) { + return ['You cannot have more than one Necrozma-Dusk-Mane.']; } - ndm++; + necrozmaDMCount++; } if (set.species === 'Necrozma-Dawn-Wings') { - if (ndw > 0) { - problems.push('You cannot have more than one Necrozma-Dawn-Wings.'); - break; + if (necrozmaDWCount > 0) { + return ['You cannot have more than one Necrozma-Dawn-Wings.']; } - ndw++; + necrozmaDWCount++; } } - return problems; + return []; }, - onChangeSet(set, format) { - let item = this.getItem(set.item); + }, + validatemisc: { + effectType: 'ValidatorRule', + name: 'Obtainable Misc', + desc: "Validate all obtainability things that aren't moves/abilities (Hidden Power type, gender, stats, etc).", + // Mostly hardcoded in team-validator.ts + onChangeSet(set) { let template = this.getTemplate(set.species); - let problems = []; - let totalEV = 0; - let allowCAP = !!(format && this.getRuleTable(format).has('allowcap')); - - if (set.species === set.name) delete set.name; - if (template.gen > this.gen) { - problems.push(set.species + ' does not exist in gen ' + this.gen + '.'); - } - if (template.gen && template.gen !== this.gen && template.tier === 'Illegal') { - problems.push(set.species + ' does not exist outside of gen ' + template.gen + '.'); - } - /**@type {Ability} */ - // @ts-ignore - let ability = {}; - if (set.ability) { - ability = this.getAbility(set.ability); - if (ability.gen > this.gen) { - problems.push(ability.name + ' does not exist in gen ' + this.gen + '.'); - } - } - if (set.moves) { - for (const moveid of set.moves) { - let move = this.getMove(moveid); - if (move.gen > this.gen) { - problems.push(move.name + ' does not exist in gen ' + this.gen + '.'); - } else if (!allowCAP && move.isNonstandard) { - problems.push(move.name + ' does not exist.'); - } - } - } - if (item.gen > this.gen) { - problems.push(item.name + ' does not exist in gen ' + this.gen + '.'); - } - if (set.moves && set.moves.length > 4) { - problems.push((set.name || set.species) + ' has more than four moves.'); - } - if (set.level && set.level > 100) { - problems.push((set.name || set.species) + ' is higher than level 100.'); - } - - if (!allowCAP || !template.tier.startsWith('CAP')) { - if (template.isNonstandard && template.num > -5000) { - problems.push(set.species + ' does not exist.'); - } - } - - if (!allowCAP && ability.isNonstandard) { - problems.push(ability.name + ' does not exist.'); - } - - if (item.isNonstandard) { - if (item.isNonstandard === 'Past' || item.isNonstandard === 'Future') { - problems.push(item.name + ' does not exist in this generation.'); - } else if (!allowCAP) { - problems.push(item.name + ' does not exist.'); - } - } - - if (set.evs) { - for (let k in set.evs) { - // @ts-ignore - if (typeof set.evs[k] !== 'number' || set.evs[k] < 0) { - // @ts-ignore - set.evs[k] = 0; - } - // @ts-ignore - totalEV += set.evs[k]; - } - } - - // In gen 6, it is impossible to battle other players with pokemon that break the EV limit - if (totalEV > 510 && this.gen === 6) { - problems.push((set.name || set.species) + " has more than 510 total EVs."); - } - - // ----------- legality line ------------------------------------------ - if (!this.getRuleTable(format).has('-illegal')) return problems; - // everything after this line only happens if we're doing legality enforcement - - // Pokestar studios - if (template.num <= -5000 && template.isNonstandard) { - problems.push(`${set.species} cannot be obtained by legal means.`); - } - - // only in gen 1 and 2 it was legal to max out all EVs - if (this.gen >= 3 && totalEV > 510) { - problems.push((set.name || set.species) + " has more than 510 total EVs."); - } if (template.gender) { if (set.gender !== template.gender) { @@ -217,20 +148,6 @@ let BattleFormats = { } } - // Legendary Pokemon must have at least 3 perfect IVs in gen 6 - let baseTemplate = this.getTemplate(template.baseSpecies); - if (set.ivs && this.gen >= 6 && (baseTemplate.gen >= 6 || format.requirePentagon) && (template.eggGroups[0] === 'Undiscovered' || template.species === 'Manaphy') && !template.prevo && !template.nfe && - // exceptions - template.species !== 'Unown' && template.baseSpecies !== 'Pikachu' && (template.baseSpecies !== 'Diancie' || !set.shiny)) { - let perfectIVs = 0; - for (let i in set.ivs) { - // @ts-ignore - if (set.ivs[i] >= 31) perfectIVs++; - } - let reason = (format.requirePentagon ? " and this format requires gen " + this.gen + " Pokémon" : " in gen 6"); - if (perfectIVs < 3) problems.push((set.name || set.species) + " must have at least three perfect IVs because it's a legendary" + reason + "."); - } - // limit one of each move let moves = []; if (set.moves) { @@ -245,78 +162,7 @@ let BattleFormats = { } } set.moves = moves; - - let battleForme = template.battleOnly && template.species; - if (battleForme) { - if (template.requiredAbility && set.ability !== template.requiredAbility) { - problems.push("" + template.species + " transforms in-battle with " + template.requiredAbility + "."); // Darmanitan-Zen, Zygarde-Complete - } - if (template.requiredItems) { - if (template.species === 'Necrozma-Ultra') { - problems.push(`Necrozma-Ultra must start the battle as Necrozma-Dawn-Wings or Necrozma-Dusk-Mane holding Ultranecrozium Z.`); // Necrozma-Ultra transforms from one of two formes, and neither one is the base forme - } else if (!template.requiredItems.includes(item.name)) { - problems.push(`${template.species} transforms in-battle with ${Chat.plural(template.requiredItems.length, "either ") + template.requiredItems.join(" or ")}.`); // Mega or Primal - } - } - if (template.requiredMove && set.moves.indexOf(toID(template.requiredMove)) < 0) { - problems.push(`${template.species} transforms in-battle with ${template.requiredMove}.`); // Meloetta-Pirouette, Rayquaza-Mega - } - if (!format.noChangeForme) set.species = template.baseSpecies; // Fix battle-only forme - } else { - if (template.requiredAbility && set.ability !== template.requiredAbility) { - problems.push(`${(set.name || set.species)} needs the ability ${template.requiredAbility}.`); // No cases currently. - } - if (template.requiredItems && !template.requiredItems.includes(item.name)) { - problems.push(`${(set.name || set.species)} needs to hold ${Chat.plural(template.requiredItems.length, "either ") + template.requiredItems.join(" or ")}.`); // Memory/Drive/Griseous Orb/Plate/Z-Crystal - Forme mismatch - } - if (template.requiredMove && set.moves.indexOf(toID(template.requiredMove)) < 0) { - problems.push(`${(set.name || set.species)} needs to have the move ${template.requiredMove}.`); // Keldeo-Resolute - } - - // Mismatches between the set forme (if not base) and the item signature forme will have been rejected already. - // It only remains to assign the right forme to a set with the base species (Arceus/Genesect/Giratina/Silvally). - if (item.forcedForme && template.species === this.getTemplate(item.forcedForme).baseSpecies && !format.noChangeForme) { - set.species = item.forcedForme; - } - } - - if (template.species === 'Pikachu-Cosplay') { - /**@type {{[k: string]: string}} */ - let cosplay = {meteormash: 'Pikachu-Rock-Star', iciclecrash: 'Pikachu-Belle', drainingkiss: 'Pikachu-Pop-Star', electricterrain: 'Pikachu-PhD', flyingpress: 'Pikachu-Libre'}; - for (const moveid of set.moves) { - if (moveid in cosplay) { - set.species = cosplay[moveid]; - break; - } - } - } - - if (set.species !== template.species) { - // Autofixed forme. - template = this.getTemplate(set.species); - - if (!this.getRuleTable(format).has('ignoreillegalabilities') && !format.noChangeAbility) { - // Ensure that the ability is (still) legal. - let legalAbility = false; - for (let i in template.abilities) { - // @ts-ignore - if (template.abilities[i] !== set.ability) continue; - legalAbility = true; - break; - } - if (!legalAbility) { // Default to first ability. - set.ability = template.abilities['0']; - } - } - } - - return problems; }, - banlist: [ - 'Chansey + Charm + Seismic Toss', 'Chansey + Charm + Psywave', - 'Blissey + Charm + Seismic Toss', 'Blissey + Charm + Psywave', - 'Shiftry + Leaf Blade + Sucker Punch', - ], }, hoennpokedex: { effectType: 'ValidatorRule', @@ -852,7 +698,7 @@ let BattleFormats = { effectType: 'ValidatorRule', name: 'STABmons Move Legality', desc: "Allows Pokémon to use any move that they or a previous evolution/out-of-battle forme share a type with", - checkLearnset(move, template, lsetData, set) { + checkLearnset(move, template, setSources, set) { const restrictedMoves = this.format.restrictedMoves || []; if (!move.isZ && !restrictedMoves.includes(move.name)) { let dex = this.dex; @@ -871,16 +717,10 @@ let BattleFormats = { } if (types.includes(move.type)) return null; } - return this.checkLearnset(move, template, lsetData, set); + return this.checkLearnset(move, template, setSources, set); }, unbanlist: ['Shiftry + Leaf Blade + Sucker Punch'], }, - allowcap: { - effectType: 'ValidatorRule', - name: 'Allow CAP', - desc: "Allows the use of Pokémon, abilities, moves, and items made by the Create-A-Pokémon project", - // Implemented in the 'pokemon' ruleset - }, allowtradeback: { effectType: 'ValidatorRule', name: 'Allow Tradeback', diff --git a/server/chat-plugins/datasearch.js b/server/chat-plugins/datasearch.js index 07ff80a808..3286ff2ca3 100644 --- a/server/chat-plugins/datasearch.js +++ b/server/chat-plugins/datasearch.js @@ -594,7 +594,7 @@ function runDexsearch(target, cmd, canAll, message) { const accumulateKeyCount = (count, searchData) => count + (typeof searchData === 'object' ? Object.keys(searchData).length : 0); searches.sort((a, b) => Object.values(a).reduce(accumulateKeyCount, 0) - Object.values(b).reduce(accumulateKeyCount, 0)); - let lsetData = {}; + let pokemonSources = {}; for (const alts of searches) { if (alts.skip) continue; for (let mon in dex) { @@ -723,9 +723,10 @@ function runDexsearch(target, cmd, canAll, message) { } if (matched) continue; + const validator = TeamValidator.get(`gen${maxGen}ou`); for (let move in alts.moves) { - if (!lsetData[mon]) lsetData[mon] = {fastCheck: true, sources: [], sourcesBefore: maxGen}; - if (!TeamValidator.get(`gen${maxGen}ou`).checkLearnset(move, mon, lsetData[mon]) === alts.moves[move]) { + if (!pokemonSources[mon]) pokemonSources[mon] = validator.allSources(); + if (!validator.checkLearnset(move, mon, pokemonSources[mon], true) === alts.moves[move]) { matched = true; break; } @@ -1575,13 +1576,12 @@ function runLearn(target, cmd) { formatName = `Gen ${gen}`; if (format.requirePentagon) formatName += ' Pentagon'; } - let lsetData = {set: {}, sources: [], sourcesBefore: gen}; - const validator = TeamValidator.get(format); + let template = validator.dex.getTemplate(targets.shift()); - let move = {}; + let setSources = validator.allSources(template); + let set = {level: cmd === 'learn5' ? 5 : 100}; let all = (cmd === 'learnall'); - if (cmd === 'learn5') lsetData.set.level = 5; if (!template.exists || template.id === 'missingno') { return {error: `Pok\u00e9mon '${template.id}' not found.`}; @@ -1596,34 +1596,36 @@ function runLearn(target, cmd) { } let lsetProblem; + let moveNames = []; for (const arg of targets) { if (['ha', 'hidden', 'hiddenability'].includes(toID(arg))) { - lsetData.isHidden = true; + setSources.isHidden = true; continue; } - move = validator.dex.getMove(arg); + let move = validator.dex.getMove(arg); + moveNames.push(move.name); if (!move.exists || move.id === 'magikarpsrevenge') { return {error: `Move '${move.id}' not found.`}; } if (move.gen > gen) { return {error: `${move.name} didn't exist yet in generation ${gen}.`}; } - lsetProblem = validator.checkLearnset(move, template, lsetData); + lsetProblem = validator.checkLearnset(move, template, setSources, set); if (lsetProblem) { lsetProblem.moveName = move.name; break; } } - let problems = validator.reconcileLearnset(template, lsetData, lsetProblem); + let problems = validator.reconcileLearnset(template, setSources, lsetProblem); let buffer = `In ${formatName}, `; - buffer += `${template.name}` + (problems ? ` learn ` : ` learn `) + (targets.length > 1 ? `these moves` : move.name); + buffer += `${template.name}` + (problems ? ` learn ` : ` learn `) + Chat.toListString(moveNames); if (!problems) { let sourceNames = {E: "egg", S: "event", D: "dream world", V: "virtual console transfer from gen 1-2", X: "egg, traded back", Y: "event, traded back"}; - let sourcesBefore = lsetData.sourcesBefore; - if (lsetData.sources || sourcesBefore < gen) buffer += " only when obtained"; + let sourcesBefore = setSources.sourcesBefore; + if (setSources.sources || sourcesBefore < gen) buffer += " only when obtained"; buffer += " from:
"; } else if (targets.length > 1 || problems.length > 1) { @@ -1725,6 +1727,7 @@ if (!PM.isParentProcess) { } global.Dex = require('../../.sim-dist/dex').Dex; + global.Chat = require('../../.server-dist/chat').Chat; global.toID = Dex.getId; Dex.includeData(); global.TeamValidator = require('../../.sim-dist/team-validator').TeamValidator; diff --git a/server/chat.ts b/server/chat.ts index 94e9aeee1b..833a9b0d19 100644 --- a/server/chat.ts +++ b/server/chat.ts @@ -1615,12 +1615,23 @@ export const Chat = new class { } /** - * Takes an array and turns it into a sentence string by adding commas and the word 'and' at the end + * Takes an array and turns it into a sentence string by adding commas and the word "and" */ toListString(arr: string[]) { if (!arr.length) return ''; if (arr.length === 1) return arr[0]; - return `${arr.slice(0, -1).join(", ")} and ${arr.slice(-1)}`; + if (arr.length === 2) return `${arr[0]} and ${arr[1]}`; + return `${arr.slice(0, -1).join(", ")}, and ${arr.slice(-1)[0]}`; + } + + /** + * Takes an array and turns it into a sentence string by adding commas and the word "or" + */ + toOrList(arr: string[]) { + if (!arr.length) return ''; + if (arr.length === 1) return arr[0]; + if (arr.length === 2) return `${arr[0]} or ${arr[1]}`; + return `${arr.slice(0, -1).join(", ")}, or ${arr.slice(-1)[0]}`; } collapseLineBreaksHTML(htmlContent: string) { diff --git a/sim/battle.ts b/sim/battle.ts index abf61e4c04..9506508b07 100644 --- a/sim/battle.ts +++ b/sim/battle.ts @@ -1399,7 +1399,7 @@ export class Battle extends Dex.ModdedDex { continue; } const ruleTable = this.getRuleTable(this.getFormat()); - if (!ruleTable.has('-illegal') && !this.getFormat().team) { + if ((ruleTable.has('+hackmons') || !ruleTable.has('validateabilities')) && !this.getFormat().team) { // hackmons format continue; } else if (abilitySlot === 'H' && template.unreleasedHidden) { diff --git a/sim/dex-data.ts b/sim/dex-data.ts index 67c902f3a7..72fa4726cb 100644 --- a/sim/dex-data.ts +++ b/sim/dex-data.ts @@ -160,8 +160,10 @@ export type ComplexTeamBan = ComplexBan; * - '-[thing]' or '-[category]:[thing]' ban a thing * - '+[thing]' or '+[category]:[thing]' allow a thing (override a ban) * [category] is one of: item, move, ability, species, basespecies + * + * The value is the name of the parent rule (blank for the active format). */ -export class RuleTable extends Map { +export class RuleTable extends Map