From 4eef7d2878ba292d4962b8f8ee84f51bf484a7fb Mon Sep 17 00:00:00 2001 From: MacChaeger Date: Wed, 29 Jan 2025 13:29:06 -0600 Subject: [PATCH 1/9] Teambuilder: Customize Metronome Battle's popular items --- build-tools/build-indexes | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/build-tools/build-indexes b/build-tools/build-indexes index aa13c390fd..562f2d6411 100755 --- a/build-tools/build-indexes +++ b/build-tools/build-indexes @@ -677,21 +677,29 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); switch (id) { case 'leftovers': case 'lifeorb': - case 'choiceband': case 'choicescarf': - case 'choicespecs': - case 'eviolite': case 'assaultvest': case 'focussash': case 'powerherb': case 'rockyhelmet': - case 'heavydutyboots': case 'expertbelt': case 'salacberry': + if (!isMetBattle) greatItems.push(id); + else goodItems.push(id); + break; + case 'choiceband': + case 'choicespecs': + case 'eviolite': greatItems.push(id); break; + case 'mirrorherb': + case 'weaknesspolicy': + if (isMetBattle) greatItems.push(id); + else goodItems.push(id); + break; case 'mentalherb': - if (genNum > 4) greatItems.push(id); + if (isMetBattle) goodItems.push(id); + else if (genNum > 4) greatItems.push(id); else poorItems.push(id); break; case 'lumberry': From 6fdb02f64518ed2b6198d38279d6b7ec7a09da8c Mon Sep 17 00:00:00 2001 From: MacChaeger Date: Sat, 1 Feb 2025 19:55:39 -0600 Subject: [PATCH 2/9] Teambuilder: Update popular items for gen 9 & add doubles support --- build-tools/build-indexes | 46 ++++++++++++++---- .../src/battle-dex-data.ts | 2 + .../src/battle-dex-search.ts | 48 ++++++++++++------- play.pokemonshowdown.com/src/battle-dex.ts | 12 +++++ .../src/battle-tooltips.ts | 9 +--- 5 files changed, 83 insertions(+), 34 deletions(-) diff --git a/build-tools/build-indexes b/build-tools/build-indexes index 562f2d6411..365a3a746e 100755 --- a/build-tools/build-indexes +++ b/build-tools/build-indexes @@ -555,6 +555,7 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); } else if (isDoubles) { BattleTeambuilderTable[gen + 'doubles'] = {}; BattleTeambuilderTable[gen + 'doubles'].tiers = tiers; + BattleTeambuilderTable[gen + 'doubles'].items = items; BattleTeambuilderTable[gen + 'doubles'].overrideTier = overrideTier; BattleTeambuilderTable[gen + 'doubles'].formatSlices = formatSlices; } else if (isGen9BH) { @@ -675,6 +676,13 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); if (banlist.isBanned('item:' + item.id)) continue; } switch (id) { + // mainstays + case 'choiceband': + case 'choicespecs': + case 'eviolite': + greatItems.push(id); + break; + // great everywhere but metronome case 'leftovers': case 'lifeorb': case 'choicescarf': @@ -682,21 +690,38 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); case 'focussash': case 'powerherb': case 'rockyhelmet': + if (!isMetBattle) greatItems.push(id); + else goodItems.push(id); + break; + // just singles + case 'airballoon': + case 'loadeddice': + case 'heavydutyboots': case 'expertbelt': case 'salacberry': - if (!isMetBattle) greatItems.push(id); + if (isDoubles || isMetBattle) goodItems.push(id); + else greatItems.push(id); + break; + // just doubles + case 'safetygoggles': + case 'ejectbutton': + case 'ejectpack': + if (isDoubles) greatItems.push(id); else goodItems.push(id); break; - case 'choiceband': - case 'choicespecs': - case 'eviolite': - greatItems.push(id); + // doubles + metronome + case 'covertcloak': + case 'clearamulet': + case 'weaknesspolicy': + if (isDoubles || isMetBattle) greatItems.push(id); + else goodItems.push(id); break; + // metronome only case 'mirrorherb': - case 'weaknesspolicy': if (isMetBattle) greatItems.push(id); else goodItems.push(id); break; + // generation specific case 'mentalherb': if (isMetBattle) goodItems.push(id); else if (genNum > 4) greatItems.push(id); @@ -707,8 +732,8 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); else greatItems.push(id); break; case 'sitrusberry': - if (genNum > 6) goodItems.push(id); - else if (genNum > 3 && genNum < 7) greatItems.push(id); + if (genNum > 3 && (genNum < 7 || isDoubles)) greatItems.push(id); + else if (genNum > 6) goodItems.push(id); else poorItems.push(id); break; case 'aguavberry': @@ -716,7 +741,8 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); case 'iapapaberry': case 'magoberry': case 'wikiberry': - if (genNum >= 7) greatItems.push(id); + if (genNum === 7) greatItems.push(id); + else if (genNum >= 8) goodItems.push(id); else poorItems.push(id); break; case 'berryjuice': @@ -742,8 +768,8 @@ process.stdout.write("Building `data/teambuilder-tables.js`... "); case 'blueorb': case 'redorb': case 'souldew': + // falls through // Other - // fallsthrough case 'stick': case 'thickclub': case 'lightball': diff --git a/play.pokemonshowdown.com/src/battle-dex-data.ts b/play.pokemonshowdown.com/src/battle-dex-data.ts index 4d31317de7..3269486a11 100644 --- a/play.pokemonshowdown.com/src/battle-dex-data.ts +++ b/play.pokemonshowdown.com/src/battle-dex-data.ts @@ -1492,6 +1492,7 @@ class Species implements Effect { readonly evoMove: string; readonly evoItem: string; readonly evoCondition: string; + readonly nfe: boolean; readonly requiredItems: ReadonlyArray; readonly tier: string; readonly isTotem: boolean; @@ -1546,6 +1547,7 @@ class Species implements Effect { this.evoMove = data.evoMove || ''; this.evoItem = data.evoItem || ''; this.evoCondition = data.evoCondition || ''; + this.nfe = data.nfe || false; this.requiredItems = data.requiredItems || (data.requiredItem ? [data.requiredItem] : []); this.tier = data.tier || ''; diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index ab5f21c32c..1df75ca739 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -703,6 +703,9 @@ abstract class BattleTypedSearch { let results: SearchRow[]; let illegalResults: SearchRow[] | null; + if (this.defaultFilter) { + results = this.defaultFilter(this.baseResults); + } if (filters) { results = []; illegalResults = []; @@ -886,6 +889,7 @@ abstract class BattleTypedSearch { abstract getDefaultResults(): SearchRow[]; abstract getBaseResults(): SearchRow[]; abstract filter(input: SearchRow, filters: string[][]): boolean; + defaultFilter?(input: SearchRow[]): SearchRow[]; abstract sort(input: SearchRow[], sortCol: string, reverseSort?: boolean): SearchRow[]; } @@ -1275,6 +1279,8 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { table = table['gen5bw1']; } else if (this.formatType === 'natdex') { table = table['gen' + this.dex.gen + 'natdex']; + } else if (this.formatType?.endsWith('doubles')) { // no natdex/bdsp doubles support + table = table['gen' + this.dex.gen + 'doubles']; } else if (this.formatType === 'metronome') { table = table['gen' + this.dex.gen + 'metronome']; } else if (this.dex.gen < 9) { @@ -1296,32 +1302,42 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { const speciesName = this.dex.species.get(this.species).name; const results = this.getDefaultResults(); const speciesSpecific: SearchRow[] = []; + const abilitySpecific: SearchRow[] = []; + const abilityItem = { + protosynthesis: 'boosterenergy', + quarkdrive: 'boosterenegy', + // poisonheal: 'toxicorb', + // toxicboost: 'toxicorb', + // flareboost: 'flameorb', + }[toID(this.set?.ability) as string] for (const row of results) { if (row[0] !== 'item') continue; - if (this.dex.items.get(row[1]).itemUser?.includes(speciesName)) { - speciesSpecific.push(row); - } + const item = this.dex.items.get(row[1]); + if (item.itemUser?.includes(speciesName)) speciesSpecific.push(row); + if (abilityItem === item.id) abilitySpecific.push(row); } if (speciesSpecific.length) { - return [ + results.unshift( ['header', "Specific to " + speciesName], ...speciesSpecific, - ...results, - ]; + ); + } + if (abilitySpecific.length) { + results.unshift( + ['header', "Specific to " + this.set!.ability], + ...abilitySpecific, + ); } return results; } - filter(row: SearchRow, filters: string[][]) { - if (!filters) return true; - if (row[0] !== 'ability') return true; - const ability = this.dex.abilities.get(row[1]); - for (const [filterType, value] of filters) { - switch (filterType) { - case 'pokemon': - if (!Dex.hasAbility(this.dex.species.get(value), ability.name)) return false; - break; - } + defaultFilter(results: SearchRow[]) { + if (this.species && !this.dex.species.get(this.species).nfe) { + results.splice(results.findIndex(row => row[1] === 'eviolite'), 1); + return results; } + return results; + } + filter(row: SearchRow, filters: string[][]) { return true; } sort(results: SearchRow[], sortCol: string | null, reverseSort?: boolean): SearchRow[] { diff --git a/play.pokemonshowdown.com/src/battle-dex.ts b/play.pokemonshowdown.com/src/battle-dex.ts index 1ddb5a25e5..1096ed6bb5 100644 --- a/play.pokemonshowdown.com/src/battle-dex.ts +++ b/play.pokemonshowdown.com/src/battle-dex.ts @@ -396,6 +396,12 @@ const Dex = new class implements ModdedDex { if (!data.tier && data.baseSpecies && toID(data.baseSpecies) !== id) { data.tier = this.species.get(data.baseSpecies).tier; } + data.nfe = data.id === 'dipplin' || !!(data as Species).evos?.some(evo => { + const evoSpecies = this.species.get(evo); + return !evoSpecies.isNonstandard || evoSpecies.isNonstandard === data.isNonstandard || + // Pokemon with Hisui evolutions + evoSpecies.isNonstandard === "Unobtainable"; + }); species = new Species(id, name, data); window.BattlePokedex[id] = species; } @@ -989,6 +995,12 @@ class ModdedDex { data.tier = this.species.get(data.baseSpecies).tier; } if (data.gen > this.gen) data.tier = 'Illegal'; + data.nfe = data.id === 'dipplin' || !!data.evos?.some(evo => { + const evoSpecies = this.species.get(evo); + return !evoSpecies.isNonstandard || evoSpecies.isNonstandard === data.isNonstandard || + // Pokemon with Hisui evolutions + evoSpecies.isNonstandard === "Unobtainable"; + }); const species = new Species(id, name, data); this.cache.Species[id] = species; diff --git a/play.pokemonshowdown.com/src/battle-tooltips.ts b/play.pokemonshowdown.com/src/battle-tooltips.ts index 814a500751..9d37003471 100644 --- a/play.pokemonshowdown.com/src/battle-tooltips.ts +++ b/play.pokemonshowdown.com/src/battle-tooltips.ts @@ -1176,14 +1176,7 @@ class BattleTooltips { speedModifiers.push(1.5); } } - const isNFE = this.battle.dex.species.get(serverPokemon.speciesForme).evos?.some(evo => { - const evoSpecies = this.battle.dex.species.get(evo); - return !evoSpecies.isNonstandard || - evoSpecies.isNonstandard === this.battle.dex.species.get(serverPokemon.speciesForme)?.isNonstandard || - // Pokemon with Hisui evolutions - evoSpecies.isNonstandard === "Unobtainable"; - }); - if (item === 'eviolite' && (isNFE || this.battle.dex.species.get(serverPokemon.speciesForme).id === 'dipplin')) { + if (item === 'eviolite' && this.battle.dex.species.get(serverPokemon.speciesForme).nfe) { stats.def = Math.floor(stats.def * 1.5); stats.spd = Math.floor(stats.spd * 1.5); } From b1d9bfff2ca3c2f1c2e43dbaf4f9c13b74bf0c87 Mon Sep 17 00:00:00 2001 From: MacChaeger Date: Sat, 1 Feb 2025 20:09:24 -0600 Subject: [PATCH 3/9] Fixes --- play.pokemonshowdown.com/src/battle-dex-search.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index 1df75ca739..213551b6bf 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -703,9 +703,6 @@ abstract class BattleTypedSearch { let results: SearchRow[]; let illegalResults: SearchRow[] | null; - if (this.defaultFilter) { - results = this.defaultFilter(this.baseResults); - } if (filters) { results = []; illegalResults = []; @@ -730,6 +727,9 @@ abstract class BattleTypedSearch { results = [...this.baseResults]; illegalResults = null; } + if (this.defaultFilter) { + results = this.defaultFilter(results); + } if (sortCol) { results = results.filter(([rowType]) => rowType === this.searchType); @@ -1309,7 +1309,7 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { // poisonheal: 'toxicorb', // toxicboost: 'toxicorb', // flareboost: 'flameorb', - }[toID(this.set?.ability) as string] + }[toID(this.set?.ability) as string]; for (const row of results) { if (row[0] !== 'item') continue; const item = this.dex.items.get(row[1]); @@ -1319,13 +1319,13 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { if (speciesSpecific.length) { results.unshift( ['header', "Specific to " + speciesName], - ...speciesSpecific, + ...speciesSpecific ); } if (abilitySpecific.length) { results.unshift( ['header', "Specific to " + this.set!.ability], - ...abilitySpecific, + ...abilitySpecific ); } return results; From 67cd856febee749ea593f6e767e8e2651ded6f75 Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:27:41 -0700 Subject: [PATCH 4/9] Update play.pokemonshowdown.com/src/battle-dex-search.ts --- play.pokemonshowdown.com/src/battle-dex-search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index 58fc3324fe..b41f64d1a7 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -1334,7 +1334,7 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { } return results; } - defaultFilter(results: SearchRow[]) { + override defaultFilter(results: SearchRow[]) { if (this.species && !this.dex.species.get(this.species).nfe) { results.splice(results.findIndex(row => row[1] === 'eviolite'), 1); return results; From 93d55e406ffdbeaad936c5e9bd0c2d53410a67a0 Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:34:13 -0700 Subject: [PATCH 5/9] Apply suggestions from code review --- play.pokemonshowdown.com/src/battle-dex-search.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index b41f64d1a7..4f7df37502 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -1282,9 +1282,9 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { } else if (this.formatType === 'bw1') { table = table['gen5bw1']; } else if (this.formatType === 'natdex') { - table = table['gen' + this.dex.gen + 'natdex']; + table = table[`gen${this.dex.gen}natdex`]; } else if (this.formatType?.endsWith('doubles')) { // no natdex/bdsp doubles support - table = table['gen' + this.dex.gen + 'doubles']; + table = table[`gen${this.dex.gen}doubles`]; } else if (this.formatType === 'metronome') { table = table[`gen${this.dex.gen}metronome`]; } else if (this.dex.gen < 9) { @@ -1328,7 +1328,7 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { } if (abilitySpecific.length) { results.unshift( - ['header', "Specific to " + this.set!.ability], + ['header', `Specific to ${this.set!.ability}`], ...abilitySpecific ); } From 78136273820fb3d34c80c99979772d3eb006b7df Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:35:45 -0700 Subject: [PATCH 6/9] Update play.pokemonshowdown.com/src/battle-dex-search.ts --- play.pokemonshowdown.com/src/battle-dex-search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index 4f7df37502..80c079dcfe 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -1328,7 +1328,7 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { } if (abilitySpecific.length) { results.unshift( - ['header', `Specific to ${this.set!.ability}`], + ['header', `Specific to ${this.set!.ability as string}`], ...abilitySpecific ); } From 22c632d81a1779ba30a21f4700084a4f1fc16b21 Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:36:17 -0700 Subject: [PATCH 7/9] Apply suggestions from code review --- play.pokemonshowdown.com/src/battle-dex-search.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index 80c079dcfe..fdc7b50aef 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -891,7 +891,7 @@ abstract class BattleTypedSearch { abstract getDefaultResults(): SearchRow[]; abstract getBaseResults(): SearchRow[]; abstract filter(input: SearchRow, filters: string[][]): boolean; - defaultFilter?(input: SearchRow[]): SearchRow[]; + abstract defaultFilter?(input: SearchRow[]): SearchRow[]; abstract sort(input: SearchRow[], sortCol: string, reverseSort?: boolean): SearchRow[]; } @@ -1334,7 +1334,7 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { } return results; } - override defaultFilter(results: SearchRow[]) { + defaultFilter(results: SearchRow[]) { if (this.species && !this.dex.species.get(this.species).nfe) { results.splice(results.findIndex(row => row[1] === 'eviolite'), 1); return results; From eb5d149071f0367e7598dfac2068dfe944b2898e Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:38:19 -0700 Subject: [PATCH 8/9] Apply suggestions from code review --- play.pokemonshowdown.com/src/battle-dex-search.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index fdc7b50aef..80c079dcfe 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -891,7 +891,7 @@ abstract class BattleTypedSearch { abstract getDefaultResults(): SearchRow[]; abstract getBaseResults(): SearchRow[]; abstract filter(input: SearchRow, filters: string[][]): boolean; - abstract defaultFilter?(input: SearchRow[]): SearchRow[]; + defaultFilter?(input: SearchRow[]): SearchRow[]; abstract sort(input: SearchRow[], sortCol: string, reverseSort?: boolean): SearchRow[]; } @@ -1334,7 +1334,7 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { } return results; } - defaultFilter(results: SearchRow[]) { + override defaultFilter(results: SearchRow[]) { if (this.species && !this.dex.species.get(this.species).nfe) { results.splice(results.findIndex(row => row[1] === 'eviolite'), 1); return results; From e3c1fe880428c0f1f52391ab4badb9bb6e4d7cc1 Mon Sep 17 00:00:00 2001 From: Kris Johnson <11083252+KrisXV@users.noreply.github.com> Date: Wed, 26 Feb 2025 13:39:43 -0700 Subject: [PATCH 9/9] Apply suggestions from code review --- play.pokemonshowdown.com/src/battle-dex-search.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/play.pokemonshowdown.com/src/battle-dex-search.ts b/play.pokemonshowdown.com/src/battle-dex-search.ts index 80c079dcfe..8eabbb5f5a 100644 --- a/play.pokemonshowdown.com/src/battle-dex-search.ts +++ b/play.pokemonshowdown.com/src/battle-dex-search.ts @@ -1328,7 +1328,7 @@ class BattleItemSearch extends BattleTypedSearch<'item'> { } if (abilitySpecific.length) { results.unshift( - ['header', `Specific to ${this.set!.ability as string}`], + ['header', `Specific to ${this.set!.ability!}`], ...abilitySpecific ); }