mirror of
https://github.com/smogon/pokemon-showdown.git
synced 2026-05-20 05:58:08 -05:00
New validator (#5840)
* Refactor validator This is a major refactor intended to make the default rules easier to understand, and also easier for OMs to bypass. Removed rules: - `Pokemon`: This is now `-Nonexistent`. Its previous name was intended to be interpreted as "simulate the Pokémon games exactly, and only allow what they allow". The new name should make it clearer that it mainly bans CAPs and other nonexistent Pokémon and functionality. - `-Illegal`: This is now `Obtainable` (see below). - `Allow CAP`: This is now `+CAP`. Instead of having a hardcoded rule, OMs can now be manually whitelist any pokemon/item/etc or group of them, overriding `-Nonexistent`. - `Ignore Illegal Abilities`: This is now `!Obtainable Abilities` (see below). `Obtainable` was previously `-Illegal`, and does the same thing: Makes sure you have a regular Pokémon game with only Pokémon that can be obtained without hacking. But instead of being a ban, it's now a rule that does nothing by itself, except contain more rules: - `Obtainable Moves` - `Obtainable Abilities` - `Obtainable Formes` - `Obtainable Misc` - `-Nonexistent` - `-Unreleased` This allows OMs to piecemeal repeal and unban any of these individual rules, instead of the previous approach of unbanning them all and manually reimplementing every single validation you wanted to keep. * Refactor PokemonSources into a class This mostly just makes a lot of the weirder checks in the validator substantially more readable. This also renames `lsetData` to `setSources`, which should also help readability. * Validate Bottle Cap HP types Fixes an issue reported here: https://github.com/Zarel/Pokemon-Showdown/issues/5742#issuecomment-533850288 * Fix several move validation issues Fixes #5742 We have a new MoveSource type: R for Restricted. R moves work like level-up/tutor/TM moves, except you're limited to one R move. - Shedinja move stolen from Ninjask in Gen 3-4 are now R moves instead of event moves. This allows them to coexist with Nincada egg moves. - Necrozma-DW/DM now inherit moves/events from Necrozma (like Rotom, but with event validation). This allows them to be shiny. - Pokemon can now get egg moves from their own evolutions. This fixes some Tyrogue, Charmander, and Treecko sets mentioned in #5742 - Some more C moves were added, fixing some Hitmontop and Chatot sets mentioned in #5742 * Improve ability/move compatibility validator
This commit is contained in:
parent
d70b8d426e
commit
71498d451d
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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"],
|
||||
|
|
|
|||
|
|
@ -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'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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'],
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
/**@type {{[k: string]: ModdedFormatsData}} */
|
||||
let BattleFormats = {
|
||||
pokemon: {
|
||||
validatemoves: {
|
||||
inherit: true,
|
||||
banlist: [
|
||||
'Chansey + Charm + Seismic Toss',
|
||||
|
|
|
|||
|
|
@ -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
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
|
|
|
|||
270
data/rulesets.js
270
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',
|
||||
|
|
|
|||
|
|
@ -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 ? ` <span class="message-learn-cannotlearn">can't</span> learn ` : ` <span class="message-learn-canlearn">can</span> learn `) + (targets.length > 1 ? `these moves` : move.name);
|
||||
buffer += `${template.name}` + (problems ? ` <span class="message-learn-cannotlearn">can't</span> learn ` : ` <span class="message-learn-canlearn">can</span> 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:<ul class=\"message-learn-list\">";
|
||||
if (lsetData.sources) {
|
||||
let sources = lsetData.sources.map(source => {
|
||||
if (setSources.sources) {
|
||||
let sources = setSources.sources.map(source => {
|
||||
if (source.slice(0, 3) === '1ET') {
|
||||
return '2X' + source.slice(3);
|
||||
}
|
||||
|
|
@ -1658,8 +1660,8 @@ function runLearn(target, cmd) {
|
|||
if (sourcesBefore) {
|
||||
buffer += `<li>${(sourcesBefore < gen ? "Gen " + sourcesBefore + " or earlier" : "anywhere") + " (all moves are level-up/tutor/TM/HM in Gen " + Math.min(gen, sourcesBefore) + (sourcesBefore < gen ? " to " + gen : "")})`;
|
||||
}
|
||||
if (lsetData.babyOnly && sourcesBefore) {
|
||||
buffer += `<li>must be obtained as ` + Dex.getTemplate(lsetData.babyOnly).species;
|
||||
if (setSources.babyOnly && sourcesBefore) {
|
||||
buffer += `<li>must be obtained as ` + Dex.getTemplate(setSources.babyOnly).species;
|
||||
}
|
||||
buffer += "</ul>";
|
||||
} 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;
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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<string, string> {
|
||||
complexBans: ComplexBan[];
|
||||
complexTeamBans: ComplexTeamBan[];
|
||||
// tslint:disable-next-line:ban-types
|
||||
|
|
@ -176,14 +178,23 @@ export class RuleTable extends Map {
|
|||
this.timer = null;
|
||||
}
|
||||
|
||||
check(thing: string, setHas: {[id: string]: true} | null = null): string {
|
||||
isBanned(thing: string) {
|
||||
if (this.has(`+${thing}`)) return false;
|
||||
return this.has(`-${thing}`);
|
||||
}
|
||||
|
||||
check(thing: string, setHas: {[id: string]: true} | null = null) {
|
||||
if (this.has(`+${thing}`)) return '';
|
||||
if (setHas) setHas[thing] = true;
|
||||
return this.getReason(`-${thing}`);
|
||||
}
|
||||
|
||||
getReason(key: string): string {
|
||||
getReason(key: string): string | null {
|
||||
const source = this.get(key);
|
||||
if (source === undefined) return '';
|
||||
if (source === undefined) return null;
|
||||
if (key === '-nonexistent' || key.startsWith('validate')) {
|
||||
return 'not obtainable';
|
||||
}
|
||||
return source ? `banned by ${source}` : `banned`;
|
||||
}
|
||||
|
||||
|
|
|
|||
21
sim/dex.ts
21
sim/dex.ts
|
|
@ -409,6 +409,13 @@ export class ModdedDex {
|
|||
template.doublesTier = 'Illegal';
|
||||
template.isNonstandard = 'Future';
|
||||
}
|
||||
if (this.currentMod === 'letsgo' && !template.isNonstandard) {
|
||||
const isLetsGo = (
|
||||
(template.num <= 151 || ['Meltan', 'Melmetal'].includes(template.name)) &&
|
||||
(!template.forme || ['Alola', 'Mega', 'Mega-X', 'Mega-Y'].includes(template.forme))
|
||||
);
|
||||
if (!isLetsGo) template.isNonstandard = 'Past';
|
||||
}
|
||||
} else {
|
||||
template = new Data.Template({
|
||||
id, name, exists: false, tier: 'Illegal', doublesTier: 'Illegal', isNonstandard: 'Custom',
|
||||
|
|
@ -608,6 +615,10 @@ export class ModdedDex {
|
|||
if (item.gen > this.gen) {
|
||||
(item as any).isNonstandard = 'Future';
|
||||
}
|
||||
// hack for allowing mega evolution in LGPE
|
||||
if (this.currentMod === 'letsgo' && !item.isNonstandard && !item.megaStone) {
|
||||
(item as any).isNonstandard = 'Past';
|
||||
}
|
||||
} else {
|
||||
item = new Data.Item({id, name, exists: false});
|
||||
}
|
||||
|
|
@ -634,6 +645,12 @@ export class ModdedDex {
|
|||
if (ability.gen > this.gen) {
|
||||
(ability as any).isNonstandard = 'Future';
|
||||
}
|
||||
if (this.currentMod === 'letsgo' && ability.id !== 'noability') {
|
||||
(ability as any).isNonstandard = 'Past';
|
||||
}
|
||||
if ((this.currentMod === 'letsgo' || this.gen <= 2) && ability.id === 'noability') {
|
||||
(ability as any).isNonstandard = null;
|
||||
}
|
||||
} else {
|
||||
ability = new Data.Ability({id, name, exists: false});
|
||||
}
|
||||
|
|
@ -888,7 +905,7 @@ export class ModdedDex {
|
|||
validateBanRule(rule: string) {
|
||||
let id = toID(rule);
|
||||
if (id === 'unreleased') return 'unreleased';
|
||||
if (id === 'illegal') return 'illegal';
|
||||
if (id === 'nonexistent') return 'nonexistent';
|
||||
const matches = [];
|
||||
let matchTypes = ['pokemon', 'move', 'ability', 'item', 'pokemontag'];
|
||||
for (const matchType of matchTypes) {
|
||||
|
|
@ -916,6 +933,8 @@ export class ModdedDex {
|
|||
'duber', 'dou', 'dbl', 'duu', 'dnu',
|
||||
// custom tags
|
||||
'mega',
|
||||
// illegal/nonstandard reasons
|
||||
'glitch', 'past', 'future', 'lgpe', 'pokestar', 'custom',
|
||||
];
|
||||
if (validTags.includes(ruleid)) matches.push('pokemontag:' + ruleid);
|
||||
continue;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ type Pokemon = import('./pokemon').Pokemon
|
|||
type PRNGSeed = import('./prng').PRNGSeed;
|
||||
type Side = import('./side').Side
|
||||
type TeamValidator = import('./team-validator').TeamValidator
|
||||
type PokemonSources = import('./team-validator').PokemonSources
|
||||
|
||||
type ID = '' | string & {__isID: true};
|
||||
interface AnyObject {[k: string]: any}
|
||||
|
|
@ -46,6 +47,7 @@ type PokemonSet = {
|
|||
* - L = start or level-up, 3rd char+ is the level
|
||||
* - M = TM/HM
|
||||
* - T = tutor
|
||||
* - R = restricted (special moves like Rotom moves)
|
||||
* - E = egg
|
||||
* - S = event, 3rd char+ is the index in .eventPokemon
|
||||
* - D = Dream World, only 5D is valid
|
||||
|
|
@ -60,48 +62,6 @@ type PokemonSet = {
|
|||
*/
|
||||
type MoveSource = string;
|
||||
|
||||
/**
|
||||
* Describes a possible way to get a pokemon. Is not exhaustive!
|
||||
* sourcesBefore covers all sources that do not have exclusive
|
||||
* moves (like catching wild pokemon).
|
||||
*
|
||||
* First character is a generation number, 1-7.
|
||||
* Second character is a source ID, one of:
|
||||
*
|
||||
* - E = egg, 3rd char+ is the father in gen 2-5, empty in gen 6-7
|
||||
* because egg moves aren't restricted to fathers anymore
|
||||
* - S = event, 3rd char+ is the index in .eventPokemon
|
||||
* - D = Dream World, only 5D is valid
|
||||
* - V = Virtual Console transfer, only 7V is valid
|
||||
*
|
||||
* Designed to match MoveSource where possible.
|
||||
*/
|
||||
type PokemonSource = string;
|
||||
|
||||
/**
|
||||
* Keeps track of how a pokemon with a given set might be obtained.
|
||||
*
|
||||
* `sources` is a list of possible PokemonSources, and a nonzero
|
||||
* sourcesBefore means the Pokemon is compatible with all possible
|
||||
* PokemonSources from that gen or earlier.
|
||||
*
|
||||
* `limitedEgg` tracks moves that can only be obtained from an egg with
|
||||
* another father in gen 2-5. If there are multiple such moves,
|
||||
* potential fathers need to be checked to see if they can actually
|
||||
* learn the move combination in question.
|
||||
*/
|
||||
type PokemonSources = {
|
||||
sources: PokemonSource[]
|
||||
sourcesBefore: number
|
||||
babyOnly?: string
|
||||
sketchMove?: string
|
||||
hm?: string
|
||||
restrictiveMoves?: string[]
|
||||
limitedEgg?: (string | 'self')[]
|
||||
isHidden?: boolean
|
||||
fastCheck?: true
|
||||
}
|
||||
|
||||
type EventInfo = {
|
||||
generation: number,
|
||||
level?: number,
|
||||
|
|
@ -1015,8 +975,6 @@ interface FormatsData extends EventMethods {
|
|||
maxForcedLevel?: number
|
||||
maxLevel?: number
|
||||
mod?: string
|
||||
noChangeAbility?: boolean
|
||||
noChangeForme?: boolean
|
||||
onBasePowerPriority?: number
|
||||
onModifyMovePriority?: number
|
||||
onSwitchInPriority?: number
|
||||
|
|
@ -1035,7 +993,7 @@ interface FormatsData extends EventMethods {
|
|||
timer?: Partial<GameTimerSettings>
|
||||
tournamentShow?: boolean
|
||||
unbanlist?: string[]
|
||||
checkLearnset?: (this: TeamValidator, move: Move, template: Template, lsetData: PokemonSources, set: PokemonSet) => {type: string, [any: string]: any} | null
|
||||
checkLearnset?: (this: TeamValidator, move: Move, template: Template, setSources: PokemonSources, set: PokemonSet) => {type: string, [any: string]: any} | null
|
||||
onAfterMega?: (this: Battle, pokemon: Pokemon) => void
|
||||
onBegin?: (this: Battle) => void
|
||||
onChangeSet?: (this: ModdedDex, set: PokemonSet, format: Format, setHas?: AnyObject, teamHas?: AnyObject) => string[] | void
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -80,8 +80,8 @@ class TestTools {
|
|||
if (!format.ruleset) format.ruleset = [];
|
||||
if (!format.banlist) format.banlist = [];
|
||||
|
||||
if (options.pokemon) format.ruleset.push('Pokemon');
|
||||
if (options.legality) format.banlist.push('Illegal', 'Unreleased');
|
||||
if (options.pokemon) format.ruleset.push('-Nonexistent');
|
||||
if (options.legality) format.ruleset.push('Obtainable');
|
||||
if (options.preview) format.ruleset.push('Team Preview');
|
||||
if (options.sleepClause) format.ruleset.push('Sleep Clause Mod');
|
||||
if (options.cancel) format.ruleset.push('Cancel Mod');
|
||||
|
|
|
|||
|
|
@ -107,6 +107,52 @@ describe('Team Validator', function () {
|
|||
assert(illegal);
|
||||
});
|
||||
|
||||
it('should handle weird things', function () {
|
||||
// Necrozma-DW should use Necrozma's events, plus Moongeist Beam
|
||||
let team = [
|
||||
{species: 'necrozmadawnwings', ability: 'prismarmor', shiny: true, moves: ['moongeistbeam', 'metalclaw'], evs: {hp: 1}},
|
||||
];
|
||||
let illegal = TeamValidator.get('gen7anythinggoes').validateTeam(team);
|
||||
assert.strictEqual(illegal, null);
|
||||
|
||||
// Shedinja should be able to take one level-up move from ninjask in gen 3-4
|
||||
|
||||
team = [
|
||||
{species: 'shedinja', ability: 'wonderguard', moves: ['silverwind', 'swordsdance'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen4ou').validateTeam(team);
|
||||
assert.strictEqual(illegal, null);
|
||||
|
||||
team = [
|
||||
{species: 'shedinja', ability: 'wonderguard', moves: ['silverwind', 'batonpass'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen3ou').validateTeam(team);
|
||||
assert.strictEqual(illegal, null);
|
||||
|
||||
team = [
|
||||
{species: 'shedinja', ability: 'wonderguard', moves: ['silverwind', 'swordsdance', 'batonpass'], evs: {hp: 1}},
|
||||
{species: 'charmander', ability: 'blaze', moves: ['flareblitz', 'dragondance'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen4ou').validateTeam(team);
|
||||
assert(illegal);
|
||||
|
||||
// Chansey can't have Chansey-only egg moves as well as Happiny-only level-up moves
|
||||
|
||||
team = [
|
||||
{species: 'chansey', ability: 'naturalcure', moves: ['charm', 'seismictoss'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen7ou').validateTeam(team);
|
||||
assert(illegal);
|
||||
|
||||
// male-only hidden abilities are incompatible with egg moves in Gen 5
|
||||
|
||||
team = [
|
||||
{species: 'combusken', ability: 'speedboost', moves: ['batonpass'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen5ou').validateTeam(team);
|
||||
assert(illegal);
|
||||
});
|
||||
|
||||
it('should reject illegal egg move combinations', function () {
|
||||
let team = [
|
||||
{species: 'azumarill', ability: 'hugepower', moves: ['bellydrum', 'aquajet'], evs: {hp: 1}},
|
||||
|
|
@ -150,6 +196,12 @@ describe('Team Validator', function () {
|
|||
illegal = TeamValidator.get('gen3ou').validateTeam(team);
|
||||
assert(illegal);
|
||||
|
||||
team = [
|
||||
{species: 'hitmontop', ability: 'intimidate', moves: ["highjumpkick", 'machpunch'], evs: {hp: 1}},
|
||||
];
|
||||
illegal = TeamValidator.get('gen3ou').validateTeam(team);
|
||||
assert.strictEqual(illegal, null);
|
||||
|
||||
team = [
|
||||
{species: 'snorlax', ability: 'immunity', moves: ['curse', 'pursuit'], evs: {hp: 1}},
|
||||
];
|
||||
|
|
@ -247,6 +299,16 @@ describe('Team Validator', function () {
|
|||
/*********************************************************
|
||||
* Custom rules
|
||||
*********************************************************/
|
||||
it('should support legality tags', function () {
|
||||
let team = [
|
||||
{species: 'kitsunoh', ability: 'frisk', moves: ['shadowstrike'], evs: {hp: 1}},
|
||||
];
|
||||
let illegal = TeamValidator.get('gen7anythinggoes').validateTeam(team);
|
||||
assert(illegal);
|
||||
illegal = TeamValidator.get('gen7anythinggoes@@@+cap').validateTeam(team);
|
||||
assert.strictEqual(illegal, null);
|
||||
});
|
||||
|
||||
it('should allow Pokemon to be banned', function () {
|
||||
let team = [
|
||||
{species: 'pikachu', ability: 'static', moves: ['agility', 'protect', 'thunder', 'thunderbolt'], evs: {hp: 1}},
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user