From 4428a1444c3d39e915b7c7a19c5c76565da5aba3 Mon Sep 17 00:00:00 2001 From: Zachary Perlmutter Date: Mon, 19 Jan 2026 00:27:52 -0800 Subject: [PATCH] Fix teambuilder support for OMs (#2598) * battle-dex-search.ts: Fix natdex OMs pulling from SV OMs * Fix Teambuilder Support For OMs * National Dex OMs merging the rulesets for their SV counterparts * Bans via required abilities and items never being checked * Bans via required abilities not being implemented properly * mega rayquaza clause being wastefully checked over and over again * Tables in natdex now omit the 'natdex' part of the format to be consistent with battle-dex-search.ts * Synced meta tables in build-indexes and battle-dex-search.ts * Apply suggestions from code review --------- Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com> --- build-tools/build-indexes | 51 ++++++++++--------- .../src/battle-dex-search.ts | 21 ++++---- 2 files changed, 37 insertions(+), 35 deletions(-) diff --git a/build-tools/build-indexes b/build-tools/build-indexes index 032af7dee..62aea4e48 100755 --- a/build-tools/build-indexes +++ b/build-tools/build-indexes @@ -433,36 +433,41 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); if (genNum >= 6) { for (const meta of [ '1v1', '2v2doubles', 'lcuu', 'freeforall', 'ubersuu', 'almostanyability', 'balancedhackmons', 'godlygift', 'mixandmega', 'sharedpower', 'stabmons', - '12switch', '350cup', 'alphabetcup', 'badnboosted', 'battlefields', 'biomechmons', 'camomons', 'categoryswap', - 'convergence', 'crossevolution', 'ferventimpersonation', 'foresighters', 'formemons', 'fortemons', 'franticfusions', + '12switch', '350cup', 'alphabetcup', 'badnboosted', 'battlefields', 'biomechmons', 'camomons', 'categoryswap', 'categoryswap', + 'convergence', 'crossevolution', 'categoryswap', 'ferventimpersonation', 'foresighters', 'formemons', 'fortemons', 'franticfusions', 'fullpotential', 'inheritance', 'inverse', 'natureswap', 'partnersincrime', 'passiveaggressive', 'pokebilities', 'pokemoves', 'relayrace', 'revelationmons', 'sharingiscaring', 'teradonation', 'teraoverride', 'thecardgame', - 'thelosersgame', 'trademarked', 'triples', 'typesplit', 'voltturnmayhem', 'nationaldexubersuu', 'nationaldex1v1', - 'nationaldexaaa', 'nationaldexbh', 'nationaldexgodlygift', 'nationaldexstabmons', 'tiershift', + 'thelosersgame', 'trademarked', 'triples', 'typesplit', 'voltturnmayhem', + 'aaa', 'bh', // natdex abbreviations + 'tiershift', ]) { - const format = Dex.formats.get(gen + meta); - if (format.exists && Dex.formats.getRuleTable(format).isBannedSpecies(species)) { - if (!metagameBans[meta]) metagameBans[meta] = {}; - if (Dex.formats.getRuleTable(format).has('megarayquazaclause')) { - metagameBans[meta]['megarayquazaclause'] = 1; - } - if (species.requiredItems && species.requiredItems.length) { - for (const itemName of species.requiredItems) { + const format = Dex.formats.get(`${gen}${isNatDex ? 'nationaldex' : ''}${meta}`); + if (!format.exists) continue; + const ruleTable = Dex.formats.getRuleTable(format); + let banned = ruleTable.isBannedSpecies(species); + if (!banned) { + const requiredItems = species.requiredItems; + if (requiredItems && requiredItems.length) { + for (const itemName of requiredItems) { const item = Dex.items.get(itemName); - if (item.itemUser && item.itemUser.includes(species.name) && - Dex.formats.getRuleTable(format).isBanned('item:' + item.id)) { - metagameBans[meta][species.id] = 1; - } - if (item.megaStone && Object.values(item.megaStone).includes(species.name) && - Dex.formats.getRuleTable(format).isBanned('item:' + item.id)) { - metagameBans[meta][species.id] = 1; + if (((item.itemUser && item.itemUser.includes(species.name)) || + (item.megaStone && Object.values(item.megaStone).includes(species.name)) + ) && ruleTable.isBanned('item:' + item.id)) { + banned = true; + break; } } } - if (species.requiredAbility) { - const ability = Dex.items.get(species.requiredAbility); - if (Dex.formats.getRuleTable(format).isBanned('ability:' + ability.id)) { - metagameBans[meta][species.id] = 1; + } + if (!banned && species.requiredAbility) { + const ability = Dex.abilities.get(species.requiredAbility); + banned = ruleTable.isBanned('ability:' + ability.id); + } + if (banned) { + if (!metagameBans[meta]) { + metagameBans[meta] = {}; + if (ruleTable.has('megarayquazaclause')) { + metagameBans[meta]['megarayquazaclause'] = 1; } } metagameBans[meta][species.id] = 1; diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index dd4e5984d..875a13a46 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -1155,22 +1155,19 @@ class BattlePokemonSearch extends BattleTypedSearch<'pokemon'> { ]; } const customBanlists = [ - '1v1', '2v2doubles', 'lcuu', 'freeforall', 'ubersuu', 'almostanyability', 'balancedhackmons', 'godlygift', 'mixandmega', - 'sharedpower', 'stabmons', '12switch', '350cup', 'alphabetcup', 'badnboosted', 'battlefields', 'biomechmons', 'camomons', - 'categoryswap', 'convergence', 'crossevolution', 'fervetimpersonation', 'foresighters', 'formemons', 'fortemons', - 'franticfusions', 'fullpotential', 'inheritance', 'inverse', 'natureswap', 'partnersincrime', 'passiveaggressive', - 'pokebilities', 'pokemoves', 'relayrace', 'revelationmons', 'sharingiscaring', 'teradonation', 'teraoverride', 'thecardgame', - 'thelosersgame', 'trademarked', 'triples', 'typesplit', 'voltturnmayhem', 'nationaldexubersuu', 'nationaldex1v1', - 'nationaldexaaa', 'nationaldexbh', 'nationaldexgodlygift', 'nationaldexstabmons', 'tiershift', + '1v1', '2v2doubles', 'lcuu', 'freeforall', 'ubersuu', 'almostanyability', 'balancedhackmons', 'godlygift', 'mixandmega', 'sharedpower', 'stabmons', + '12switch', '350cup', 'alphabetcup', 'badnboosted', 'battlefields', 'biomechmons', 'camomons', 'categoryswap', 'categoryswap', + 'convergence', 'crossevolution', 'categoryswap', 'ferventimpersonation', 'foresighters', 'formemons', 'fortemons', 'franticfusions', + 'fullpotential', 'inheritance', 'inverse', 'natureswap', 'partnersincrime', 'passiveaggressive', 'pokebilities', + 'pokemoves', 'relayrace', 'revelationmons', 'sharingiscaring', 'teradonation', 'teraoverride', 'thecardgame', + 'thelosersgame', 'trademarked', 'triples', 'typesplit', 'voltturnmayhem', + 'aaa', 'bh', // natdex abbreviations + 'tiershift', ]; if (dex.gen >= 6) { - if ( - (customBanlists.includes(format) && table.metagameBans?.[format]) || - (this.formatType === 'natdex' && customBanlists.includes('nationaldex' + format) && - table.metagameBans?.['nationaldex' + format])) { + if (customBanlists.includes(format) && table.metagameBans?.[format]) { tierSet = tierSet.filter(([type, id]) => { if (id in table.metagameBans[format]) return false; - if (this.formatType === 'natdex' && id in table.metagameBans['nationaldex' + format]) return false; if (!this.formatType && dex.gen === 9 && 'miraidon' in table.metagameBans[format] && 'calyrexshadow' in table.metagameBans[format] &&