mirror of
https://github.com/smogon/pokemon-showdown-client.git
synced 2026-10-26 20:27:05 -05:00
Teambuilder: Update move usefulness
- Correctly detect Doubles formats - Add better notes about what is useful vs not - Leaf Blade: gen 3 -> all gens (pretty sure this was just a mistake) - Barrier: gen 1 -> useful in all gens (outclasses Iron Defense, outclassed by Acid Armor) - Thunder, Toxic: gen 2+ -> all gens - Quick Attack: gen 1 -> useful in all gens - Vacuum Wave: useful - Mirror Coat: match Counter - Decorate, Snarl: useful in Doubles - BP 60 moves: useful with Technician - Hidden Powers: fix bug (unless otherwise specified, reasoning is: we do not judge metagames) Many of these were suggested in the thread: https://www.smogon.com/forums/threads/move-category-suggestions.3671530/
This commit is contained in:
@@ -575,6 +575,7 @@ abstract class BattleTypedSearch<T extends SearchType> {
|
||||
protected formatType: 'doubles' | 'bdsp' | 'bdspdoubles' | 'rs' | 'bw1' | 'letsgo' | 'metronome' | 'natdex' | 'nfe' |
|
||||
'ssdlc1' | 'ssdlc1doubles' | 'predlc' | 'predlcdoubles' | 'predlcnatdex' | 'svdlc1' | 'svdlc1doubles' |
|
||||
'svdlc1natdex' | 'stadium' | 'lc' | null = null;
|
||||
isDoubles = false;
|
||||
|
||||
/**
|
||||
* Cached copy of what the results list would be with only base filters
|
||||
@@ -608,6 +609,7 @@ abstract class BattleTypedSearch<T extends SearchType> {
|
||||
if (format.startsWith('dlc1') && this.dex.gen === 8) {
|
||||
if (format.includes('doubles')) {
|
||||
this.formatType = 'ssdlc1doubles';
|
||||
this.isDoubles = true;
|
||||
} else {
|
||||
this.formatType = 'ssdlc1';
|
||||
}
|
||||
@@ -616,6 +618,7 @@ abstract class BattleTypedSearch<T extends SearchType> {
|
||||
if (format.startsWith('predlc')) {
|
||||
if (format.includes('doubles') && !format.includes('nationaldex')) {
|
||||
this.formatType = 'predlcdoubles';
|
||||
this.isDoubles = true;
|
||||
} else if (format.includes('nationaldex')) {
|
||||
this.formatType = 'predlcnatdex';
|
||||
} else {
|
||||
@@ -626,6 +629,7 @@ abstract class BattleTypedSearch<T extends SearchType> {
|
||||
if (format.startsWith('dlc1') && this.dex.gen === 9) {
|
||||
if (format.includes('doubles') && !format.includes('nationaldex')) {
|
||||
this.formatType = 'svdlc1doubles';
|
||||
this.isDoubles = true;
|
||||
} else if (format.includes('nationaldex')) {
|
||||
this.formatType = 'svdlc1natdex';
|
||||
} else {
|
||||
@@ -638,13 +642,26 @@ abstract class BattleTypedSearch<T extends SearchType> {
|
||||
format = format.slice(7) as ID;
|
||||
if (!format) format = 'ou' as ID;
|
||||
}
|
||||
if (format.startsWith('vgc')) this.formatType = 'doubles';
|
||||
if (format === 'vgc2020') this.formatType = 'ssdlc1doubles';
|
||||
if (format === 'vgc2023regulationd') this.formatType = 'predlcdoubles';
|
||||
if (format === 'vgc2023regulatione') this.formatType = 'svdlc1doubles';
|
||||
if (format.startsWith('vgc')) {
|
||||
this.formatType = 'doubles';
|
||||
this.isDoubles = true;
|
||||
}
|
||||
if (format === 'vgc2020') {
|
||||
this.formatType = 'ssdlc1doubles';
|
||||
this.isDoubles = true;
|
||||
}
|
||||
if (format === 'vgc2023regulationd') {
|
||||
this.formatType = 'predlcdoubles';
|
||||
this.isDoubles = true;
|
||||
}
|
||||
if (format === 'vgc2023regulatione') {
|
||||
this.formatType = 'svdlc1doubles';
|
||||
this.isDoubles = true;
|
||||
}
|
||||
if (format.includes('bdsp')) {
|
||||
if (format.includes('doubles')) {
|
||||
this.formatType = 'bdspdoubles';
|
||||
this.isDoubles = true;
|
||||
} else {
|
||||
this.formatType = 'bdsp';
|
||||
}
|
||||
@@ -670,8 +687,12 @@ abstract class BattleTypedSearch<T extends SearchType> {
|
||||
format.includes('natdex') ? format.slice(6) : format.slice(11)) as ID;
|
||||
this.formatType = 'natdex';
|
||||
if (!format) format = 'ou' as ID;
|
||||
this.isDoubles = format.includes('doubles');
|
||||
}
|
||||
if (format.includes('doubles') && this.dex.gen > 4 && !this.formatType) {
|
||||
this.formatType = 'doubles';
|
||||
this.isDoubles = true;
|
||||
}
|
||||
if (format.includes('doubles') && this.dex.gen > 4 && !this.formatType) this.formatType = 'doubles';
|
||||
if (this.formatType === 'letsgo') format = format.slice(6) as ID;
|
||||
if (format.includes('metronome')) {
|
||||
this.formatType = 'metronome';
|
||||
@@ -1415,6 +1436,12 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
return results;
|
||||
}
|
||||
private moveIsNotUseless(id: ID, species: Dex.Species, moves: string[], set: Dex.PokemonSet | null) {
|
||||
// IMPORTANT!
|
||||
// Please do not mark moves as useless if there is any doubt whatsoever.
|
||||
// I don't care if you think it's clutter or whatever. We are not in the
|
||||
// business of taking sides in arguments, or making judgments about
|
||||
// specific metagames. If it could potentially be useful in some metagame,
|
||||
// it is not useless.
|
||||
const dex = this.dex;
|
||||
|
||||
let abilityid: ID = set ? toID(set.ability) : '' as ID;
|
||||
@@ -1423,14 +1450,14 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
if (dex.gen === 1) {
|
||||
// Usually not useless for Gen 1
|
||||
if ([
|
||||
'acidarmor', 'amnesia', 'barrier', 'bind', 'blizzard', 'clamp', 'confuseray', 'counter', 'firespin', 'growth', 'headbutt', 'hyperbeam', 'mirrormove', 'pinmissile', 'razorleaf', 'sing', 'slash', 'sludge', 'twineedle', 'wrap',
|
||||
'acidarmor', 'amnesia', 'bind', 'blizzard', 'clamp', 'confuseray', 'counter', 'firespin', 'growth', 'headbutt', 'hyperbeam', 'mirrorcoat', 'mirrormove', 'pinmissile', 'razorleaf', 'sing', 'slash', 'sludge', 'twineedle', 'wrap',
|
||||
].includes(id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Usually useless for Gen 1
|
||||
if ([
|
||||
'disable', 'haze', 'leechseed', 'quickattack', 'roar', 'thunder', 'toxic', 'triattack', 'waterfall', 'whirlwind',
|
||||
'disable', 'haze', 'leechseed', 'roar', 'triattack', 'waterfall', 'whirlwind', 'bonemerang',
|
||||
].includes(id)) {
|
||||
return false;
|
||||
}
|
||||
@@ -1492,6 +1519,8 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
return species.baseSpecies === 'Morpeko';
|
||||
case 'axekick':
|
||||
return !moves.includes('highjumpkick');
|
||||
case 'barrier':
|
||||
return !moves.includes('acidarmor');
|
||||
case 'bellydrum':
|
||||
return moves.includes('aquajet') || moves.includes('jetpunch') || moves.includes('extremespeed') ||
|
||||
['iceface', 'unburden'].includes(abilityid);
|
||||
@@ -1499,7 +1528,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
return ['skilllink', 'technician'].includes(abilityid);
|
||||
case 'chillingwater':
|
||||
return !moves.includes('scald');
|
||||
case 'counter':
|
||||
case 'counter': case 'mirrorcoat':
|
||||
return species.baseStats.hp >= 65;
|
||||
case 'dazzlinggleam':
|
||||
return !moves.includes('alluringvoice') || this.formatType?.includes('doubles');
|
||||
@@ -1522,14 +1551,14 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
case 'hex':
|
||||
return !moves.includes('infernalparade');
|
||||
case 'hiddenpowerelectric':
|
||||
return (dex.gen < 4 && !moves.includes('thunderpunch')) && !moves.includes('thunderbolt');
|
||||
return !(dex.gen < 4 && moves.includes('thunderpunch')) && !moves.includes('thunderbolt');
|
||||
case 'hiddenpowerfighting':
|
||||
return (dex.gen < 4 && !moves.includes('brickbreak')) && !moves.includes('aurasphere') && !moves.includes('focusblast');
|
||||
return !(dex.gen < 4 && moves.includes('brickbreak')) && !moves.includes('aurasphere') && !moves.includes('focusblast');
|
||||
case 'hiddenpowerfire':
|
||||
return (dex.gen < 4 && !moves.includes('firepunch')) && !moves.includes('flamethrower') &&
|
||||
return !(dex.gen < 4 && moves.includes('firepunch')) && !moves.includes('flamethrower') &&
|
||||
!moves.includes('mysticalfire') && !moves.includes('burningjealousy');
|
||||
case 'hiddenpowergrass':
|
||||
return (dex.gen < 4 && !moves.includes('leafblade')) ||
|
||||
return !(dex.gen < 4 && moves.includes('leafblade')) ||
|
||||
(dex.gen > 3 && !moves.includes('energyball') && !moves.includes('grassknot') && !moves.includes('gigadrain'));
|
||||
case 'hiddenpowerice':
|
||||
return !moves.includes('icebeam') && (dex.gen < 4 && !moves.includes('icepunch')) ||
|
||||
@@ -1552,11 +1581,11 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
return dex.gen > 3;
|
||||
case 'icywind':
|
||||
// Keldeo needs Hidden Power for Electric/Ghost
|
||||
return species.baseSpecies === 'Keldeo' || this.formatType === 'doubles';
|
||||
return species.baseSpecies === 'Keldeo' || this.isDoubles;
|
||||
case 'infestation':
|
||||
return moves.includes('stickyweb');
|
||||
case 'irondefense':
|
||||
return !moves.includes('acidarmor');
|
||||
return !moves.includes('acidarmor') && !moves.includes('barrier');
|
||||
case 'irontail':
|
||||
return dex.gen > 5 && !moves.includes('ironhead') && !moves.includes('gunkshot') && !moves.includes('poisonjab');
|
||||
case 'jumpkick':
|
||||
@@ -1564,7 +1593,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
case 'lastresort':
|
||||
return set && set.moves.length < 3;
|
||||
case 'leafblade':
|
||||
return dex.gen < 4;
|
||||
return true;
|
||||
case 'leechlife':
|
||||
return dex.gen > 6;
|
||||
case 'magiccoat':
|
||||
@@ -1584,7 +1613,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
case 'petaldance':
|
||||
return abilityid === 'owntempo';
|
||||
case 'phantomforce':
|
||||
return (!moves.includes('poltergeist') && !moves.includes('shadowclaw')) || this.formatType === 'doubles';
|
||||
return (!moves.includes('poltergeist') && !moves.includes('shadowclaw')) || this.isDoubles;
|
||||
case 'poisonfang':
|
||||
return species.types.includes('Poison') && !moves.includes('gunkshot') && !moves.includes('poisonjab');
|
||||
case 'raindance':
|
||||
@@ -1614,7 +1643,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
case 'steelwing':
|
||||
return !moves.includes('ironhead');
|
||||
case 'stompingtantrum':
|
||||
return (!moves.includes('earthquake') && !moves.includes('drillrun')) || this.formatType === 'doubles';
|
||||
return (!moves.includes('earthquake') && !moves.includes('drillrun')) || this.isDoubles;
|
||||
case 'stunspore':
|
||||
return !moves.includes('thunderwave');
|
||||
case 'sunnyday':
|
||||
@@ -1625,7 +1654,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
return dex.gen > 7;
|
||||
case 'temperflare':
|
||||
return (!moves.includes('flareblitz') && !moves.includes('pyroball') && !moves.includes('sacredfire') &&
|
||||
!moves.includes('bitterblade') && !moves.includes('firepunch')) || this.formatType === 'doubles';
|
||||
!moves.includes('bitterblade') && !moves.includes('firepunch')) || this.isDoubles;
|
||||
case 'terrainpulse': case 'waterpulse':
|
||||
return ['megalauncher', 'technician'].includes(abilityid) && !moves.includes('originpulse');
|
||||
case 'thief':
|
||||
@@ -1642,7 +1671,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
return abilityid === 'noguard' || (dex.gen < 4 && !moves.includes('thunderwave'));
|
||||
}
|
||||
|
||||
if (this.formatType === 'doubles' && BattleMoveSearch.GOOD_DOUBLES_MOVES.includes(id)) {
|
||||
if (this.isDoubles && BattleMoveSearch.GOOD_DOUBLES_MOVES.includes(id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1655,7 +1684,7 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
return BattleMoveSearch.GOOD_STATUS_MOVES.includes(id);
|
||||
}
|
||||
if (move.basePower < 75) {
|
||||
return BattleMoveSearch.GOOD_WEAK_MOVES.includes(id);
|
||||
return BattleMoveSearch.GOOD_WEAK_MOVES.includes(id) || (abilityid === 'technician' && move.basePower === 60);
|
||||
}
|
||||
if (id === 'skydrop') return true;
|
||||
// strong moves
|
||||
@@ -1674,13 +1703,13 @@ class BattleMoveSearch extends BattleTypedSearch<'move'> {
|
||||
'acidarmor', 'agility', 'aromatherapy', 'auroraveil', 'autotomize', 'banefulbunker', 'batonpass', 'bellydrum', 'bulkup', 'burningbulwark', 'calmmind', 'chillyreception', 'clangoroussoul', 'coil', 'cottonguard', 'courtchange', 'curse', 'defog', 'destinybond', 'detect', 'disable', 'dragondance', 'encore', 'extremeevoboost', 'filletaway', 'geomancy', 'glare', 'haze', 'healbell', 'healingwish', 'healorder', 'heartswap', 'honeclaws', 'kingsshield', 'leechseed', 'lightscreen', 'lovelykiss', 'lunardance', 'magiccoat', 'maxguard', 'memento', 'milkdrink', 'moonlight', 'morningsun', 'nastyplot', 'naturesmadness', 'noretreat', 'obstruct', 'painsplit', 'partingshot', 'perishsong', 'protect', 'quiverdance', 'recover', 'reflect', 'reflecttype', 'rest', 'revivalblessing', 'roar', 'rockpolish', 'roost', 'shedtail', 'shellsmash', 'shiftgear', 'shoreup', 'silktrap', 'slackoff', 'sleeppowder', 'sleeptalk', 'softboiled', 'spikes', 'spikyshield', 'spore', 'stealthrock', 'stickyweb', 'strengthsap', 'substitute', 'switcheroo', 'swordsdance', 'synthesis', 'tailglow', 'tailwind', 'taunt', 'thunderwave', 'tidyup', 'toxic', 'transform', 'trick', 'victorydance', 'whirlwind', 'willowisp', 'wish', 'yawn',
|
||||
] as ID[] as readonly ID[];
|
||||
static readonly GOOD_WEAK_MOVES = [
|
||||
'accelerock', 'acrobatics', 'aquacutter', 'avalanche', 'barbbarrage', 'bonemerang', 'bouncybubble', 'bulletpunch', 'buzzybuzz', 'ceaselessedge', 'circlethrow', 'clearsmog', 'doubleironbash', 'dragondarts', 'dragontail', 'drainingkiss', 'endeavor', 'facade', 'firefang', 'flipturn', 'flowertrick', 'freezedry', 'frustration', 'geargrind', 'gigadrain', 'grassknot', 'gyroball', 'icefang', 'iceshard', 'iciclespear', 'infernalparade', 'knockoff', 'lastrespects', 'lowkick', 'machpunch', 'mortalspin', 'mysticalpower', 'naturesmadness', 'nightshade', 'nuzzle', 'pikapapow', 'populationbomb', 'psychocut', 'psyshieldbash', 'pursuit', 'quickattack', 'ragefist', 'rapidspin', 'return', 'rockblast', 'ruination', 'saltcure', 'scorchingsands', 'seismictoss', 'shadowclaw', 'shadowsneak', 'sizzlyslide', 'stoneaxe', 'storedpower', 'stormthrow', 'suckerpunch', 'superfang', 'surgingstrikes', 'tachyoncutter', 'tailslap', 'thunderclap', 'tripleaxel', 'tripledive', 'twinbeam', 'uturn', 'veeveevolley', 'voltswitch', 'watershuriken', 'weatherball',
|
||||
'accelerock', 'acrobatics', 'aquacutter', 'avalanche', 'barbbarrage', 'bonemerang', 'bouncybubble', 'bulletpunch', 'buzzybuzz', 'ceaselessedge', 'circlethrow', 'clearsmog', 'doubleironbash', 'dragondarts', 'dragontail', 'drainingkiss', 'endeavor', 'facade', 'firefang', 'flipturn', 'flowertrick', 'freezedry', 'frustration', 'geargrind', 'gigadrain', 'grassknot', 'gyroball', 'icefang', 'iceshard', 'iciclespear', 'infernalparade', 'knockoff', 'lastrespects', 'lowkick', 'machpunch', 'mortalspin', 'mysticalpower', 'naturesmadness', 'nightshade', 'nuzzle', 'pikapapow', 'populationbomb', 'psychocut', 'psyshieldbash', 'pursuit', 'quickattack', 'ragefist', 'rapidspin', 'return', 'rockblast', 'ruination', 'saltcure', 'scorchingsands', 'seismictoss', 'shadowclaw', 'shadowsneak', 'sizzlyslide', 'stoneaxe', 'storedpower', 'stormthrow', 'suckerpunch', 'superfang', 'surgingstrikes', 'tachyoncutter', 'tailslap', 'thunderclap', 'tripleaxel', 'tripledive', 'twinbeam', 'uturn', 'vacuumwave', 'veeveevolley', 'voltswitch', 'watershuriken', 'weatherball',
|
||||
] as ID[] as readonly ID[];
|
||||
static readonly BAD_STRONG_MOVES = [
|
||||
'belch', 'burnup', 'crushclaw', 'dragonrush', 'dreameater', 'eggbomb', 'firepledge', 'flyingpress', 'futuresight', 'grasspledge', 'hyperbeam', 'hyperfang', 'hyperspacehole', 'jawlock', 'landswrath', 'megakick', 'megapunch', 'mistyexplosion', 'muddywater', 'nightdaze', 'pollenpuff', 'rockclimb', 'selfdestruct', 'shelltrap', 'skyuppercut', 'slam', 'strength', 'submission', 'synchronoise', 'takedown', 'thrash', 'uproar', 'waterpledge',
|
||||
] as ID[] as readonly ID[];
|
||||
static readonly GOOD_DOUBLES_MOVES = [
|
||||
'allyswitch', 'bulldoze', 'coaching', 'electroweb', 'faketears', 'fling', 'followme', 'healpulse', 'helpinghand', 'junglehealing', 'lifedew', 'lunarblessing', 'muddywater', 'pollenpuff', 'psychup', 'ragepowder', 'safeguard', 'skillswap', 'snipeshot', 'wideguard',
|
||||
'allyswitch', 'bulldoze', 'coaching', 'electroweb', 'faketears', 'fling', 'followme', 'healpulse', 'helpinghand', 'junglehealing', 'lifedew', 'lunarblessing', 'muddywater', 'pollenpuff', 'psychup', 'ragepowder', 'safeguard', 'skillswap', 'snipeshot', 'wideguard', 'decorate', 'snarl',
|
||||
] as ID[] as readonly ID[];
|
||||
getBaseResults() {
|
||||
if (!this.species) return this.getDefaultResults();
|
||||
|
||||
Reference in New Issue
Block a user