Random Battles: Indigo Disk update (#9964)

* Random Battles: Indigo Disk update

* linting 1

* Update data/random-teams.ts

Co-authored-by: livid washed <115855253+livid-washed@users.noreply.github.com>

* dedge komala

* Update data/random-teams.ts

Co-authored-by: livid washed <115855253+livid-washed@users.noreply.github.com>

* Update data/random-teams.ts

Co-authored-by: livid washed <115855253+livid-washed@users.noreply.github.com>

* malignant chain makes toxic suck

* throat chop ursaring

* make skarm not weak armor

* prevent moody smeargle

* lint

* cm virizion destruction

* fix registeel

* flip turn enforcement

* doom desire nostab

* alphabet + flamigo

* fix psyfangs enforcement

* lint 3

* magearna changes + lint

* Fix build

---------

Co-authored-by: livid washed <115855253+livid-washed@users.noreply.github.com>
Co-authored-by: Kris Johnson <11083252+KrisXV@users.noreply.github.com>
This commit is contained in:
ACakeWearingAHat
2023-12-15 23:46:40 -06:00
committed by GitHub
parent 8f8b16306b
commit cd3eb2cfd6
3 changed files with 1545 additions and 188 deletions

View File

@@ -4248,7 +4248,7 @@ export const Abilities: {[abilityid: string]: AbilityData} = {
this.boost({def: 1});
},
name: "Stamina",
rating: 3.5,
rating: 4,
num: 192,
},
stancechange: {

File diff suppressed because it is too large Load Diff

View File

@@ -74,7 +74,7 @@ const MIXED_SETUP = [
];
// Some moves that only boost Speed:
const SPEED_SETUP = [
'agility', 'autotomize', 'rockpolish', 'trailblaze',
'agility', 'autotomize', 'flamecharge', 'rockpolish', 'trailblaze',
];
// Conglomerate for ease of access
const SETUP = [
@@ -88,9 +88,10 @@ const SPEED_CONTROL = [
// Moves that shouldn't be the only STAB moves:
const NO_STAB = [
'accelerock', 'aquajet', 'beakblast', 'bounce', 'breakingswipe', 'bulletpunch', 'chatter', 'chloroblast', 'clearsmog', 'covet',
'dragontail', 'electroweb', 'eruption', 'explosion', 'fakeout', 'feint', 'flamecharge', 'flipturn', 'grassyglide', 'iceshard', 'icywind',
'incinerate', 'machpunch', 'meteorbeam', 'mortalspin', 'nuzzle', 'pluck', 'pursuit', 'quickattack', 'rapidspin', 'reversal', 'selfdestruct',
'shadowsneak', 'skydrop', 'snarl', 'strugglebug', 'suckerpunch', 'uturn', 'watershuriken', 'vacuumwave', 'voltswitch', 'waterspout',
'dragontail', 'doomdesire', 'electroweb', 'eruption', 'explosion', 'fakeout', 'feint', 'flamecharge', 'flipturn', 'futuresight',
'grassyglide', 'iceshard', 'icywind', 'incinerate', 'machpunch', 'meteorbeam', 'mortalspin', 'nuzzle', 'pluck', 'pursuit', 'quickattack',
'rapidspin', 'reversal', 'selfdestruct', 'shadowsneak', 'skydrop', 'snarl', 'strugglebug', 'suckerpunch', 'uturn', 'watershuriken',
'vacuumwave', 'voltswitch', 'waterspout',
];
// Hazard-setting moves
const HAZARDS = [
@@ -111,6 +112,7 @@ const MOVE_PAIRS = [
['sleeptalk', 'rest'],
['protect', 'wish'],
['leechseed', 'protect'],
['leechseed', 'substitute'],
];
/** Pokemon who always want priority STAB, and are fine with it as its only STAB move of that type */
@@ -126,6 +128,10 @@ const DOUBLES_NO_LEAD_POKEMON = [
'Basculegion', 'Houndstone', 'Roaring Moon', 'Zacian', 'Zamazenta',
];
const DEFENSIVE_TERA_BLAST_USERS = [
'alcremie', 'bellossom', 'comfey', 'florges',
];
function sereneGraceBenefits(move: Move) {
return move.secondary?.chance && move.secondary.chance > 20 && move.secondary.chance < 100;
}
@@ -168,7 +174,10 @@ export class RandomTeams {
this.prng = prng && !Array.isArray(prng) ? prng : new PRNG(prng);
this.moveEnforcementCheckers = {
Bug: (movePool) => (movePool.includes('megahorn') || movePool.includes('xscissor')),
Bug: (movePool, moves, abilities, types, counter) => (
movePool.includes('megahorn') || movePool.includes('xscissor') ||
(!counter.get('Bug') && types.includes('Electric'))
),
Dark: (movePool, moves, abilities, types, counter) => !counter.get('Dark'),
Dragon: (movePool, moves, abilities, types, counter) => !counter.get('Dragon'),
Electric: (movePool, moves, abilities, types, counter) => !counter.get('Electric'),
@@ -192,13 +201,13 @@ export class RandomTeams {
},
Psychic: (movePool, moves, abilities, types, counter) => {
if (counter.get('Psychic')) return false;
if (movePool.includes('calmmind') || movePool.includes('psychicfangs')) return true;
return abilities.has('Psychic Surge') || ['Electric', 'Fighting', 'Fire', 'Poison'].some(m => types.includes(m));
if (movePool.includes('calmmind') || abilities.has('Strong Jaw')) return true;
return abilities.has('Psychic Surge') || ['Electric', 'Fighting', 'Fire', 'Grass', 'Poison'].some(m => types.includes(m));
},
Rock: (movePool, moves, abilities, types, counter, species) => !counter.get('Rock') && species.baseStats.atk >= 80,
Steel: (movePool, moves, abilities, types, counter, species, teamDetails, isLead, isDoubles) => (
!counter.get('Steel') &&
(isDoubles || species.baseStats.atk > 95 || movePool.includes('gigatonhammer') || movePool.includes('makeitrain'))
(isDoubles || species.baseStats.atk >= 90 || movePool.includes('gigatonhammer') || movePool.includes('makeitrain'))
),
Water: (movePool, moves, abilities, types, counter) => (!counter.get('Water') && !types.includes('Ground')),
};
@@ -493,7 +502,6 @@ export class RandomTeams {
[['muddywater', 'hydropump'], 'scald'],
['disable', 'encore'],
['freezedry', 'icebeam'],
['bodyslam', 'doubleedge'],
['energyball', 'leafstorm'],
['earthpower', 'sandsearstorm'],
['boomburst', 'hyperdrill'],
@@ -512,6 +520,7 @@ export class RandomTeams {
[SETUP, HAZARDS],
[SETUP, ['defog', 'nuzzle', 'toxic', 'waterspout', 'yawn', 'haze']],
[PHYSICAL_SETUP, PHYSICAL_SETUP],
['curse', 'irondefense'],
[SPECIAL_SETUP, 'thunderwave'],
['substitute', PIVOT_MOVES],
[SPEED_SETUP, ['aquajet', 'rest', 'trickroom']],
@@ -519,7 +528,7 @@ export class RandomTeams {
['dragondance', 'dracometeor'],
// These attacks are redundant with each other
['psychic', 'psyshock'],
[['psychic', 'psychicnoise'], ['psyshock', 'psychicnoise']],
['surf', 'hydropump'],
['liquidation', 'wavecrash'],
['aquajet', 'flipturn'],
@@ -527,7 +536,7 @@ export class RandomTeams {
['powerwhip', 'hornleech'],
[['airslash', 'bravebird', 'hurricane'], ['airslash', 'bravebird', 'hurricane']],
['knockoff', 'foulplay'],
['doubleedge', 'headbutt'],
['doubleedge', ['bodyslam', 'headbutt']],
['fireblast', ['fierydance', 'flamethrower']],
['lavaplume', 'magmastorm'],
['thunderpunch', 'wildcharge'],
@@ -535,7 +544,6 @@ export class RandomTeams {
['aurasphere', 'focusblast'],
['closecombat', 'drainpunch'],
['bugbite', 'pounce'],
['bittermalice', 'shadowball'],
[['dragonpulse', 'spacialrend'], 'dracometeor'],
// These status moves are redundant with each other
@@ -573,7 +581,6 @@ export class RandomTeams {
if (species.id === 'luvdisc') {
this.incompatibleMoves(moves, movePool, ['charm', 'flipturn', 'icebeam'], ['charm', 'flipturn']);
}
if (species.id === "dugtrio") this.incompatibleMoves(moves, movePool, statusMoves, 'memento');
if (species.id === "cyclizar") this.incompatibleMoves(moves, movePool, 'taunt', 'knockoff');
if (species.baseSpecies === 'Dudunsparce') this.incompatibleMoves(moves, movePool, 'earthpower', 'shadowball');
if (species.id === 'mesprit') this.incompatibleMoves(moves, movePool, 'healingwish', 'uturn');
@@ -749,6 +756,38 @@ export class RandomTeams {
}
}
// Enforce Knock Off on pure Normal- and Fighting-types in singles
if (!isDoubles && types.length === 1 && (types.includes('Normal') || types.includes('Fighting'))) {
if (movePool.includes('knockoff')) {
counter = this.addMove('knockoff', moves, types, abilities, teamDetails, species, isLead, isDoubles,
movePool, teraType, role);
}
}
// Enforce Flip Turn on pure Water-type Wallbreakers
if (types.length === 1 && types.includes('Water') && role === 'Wallbreaker') {
if (movePool.includes('flipturn')) {
counter = this.addMove('flipturn', moves, types, abilities, teamDetails, species, isLead, isDoubles,
movePool, teraType, role);
}
}
// Enforce Spore on Smeargle
if (species.id === 'smeargle') {
if (movePool.includes('spore')) {
counter = this.addMove('spore', moves, types, abilities, teamDetails, species, isLead, isDoubles,
movePool, teraType, role);
}
}
// Apparently, nothing else currently in Random Battles requires special code to enforce Night Shade/Stoss
if (species.id === 'deoxysdefense') {
if (movePool.includes('nightshade')) {
counter = this.addMove('nightshade', moves, types, abilities, teamDetails, species, isLead, isDoubles,
movePool, teraType, role);
}
}
// Enforce moves in doubles
if (isDoubles) {
const doublesEnforcedMoves = ['auroraveil', 'mortalspin', 'spore'];
@@ -1024,15 +1063,18 @@ export class RandomTeams {
case 'Intimidate':
if (abilities.has('Hustle')) return true;
if (abilities.has('Sheer Force') && !!counter.get('sheerforce')) return true;
if (species.id === 'hitmontop' && moves.has('tripleaxel')) return true;
return (abilities.has('Stakeout'));
case 'Iron Fist':
return !counter.ironFist;
return !counter.ironFist || moves.has('dynamicpunch');
case 'Justified':
return !counter.get('Physical');
case 'Libero': case 'Protean':
return role === 'Offensive Protect' || (species.id === 'meowscarada' && role === 'Fast Attacker');
case 'Lightning Rod':
return species.id === 'rhyperior';
case 'Mold Breaker':
return (abilities.has('Sharpness') || abilities.has('Unburden'));
return (abilities.has('Sharpness') || abilities.has('Unburden') || abilities.has('Sheer Force'));
case 'Moxie':
return (!counter.get('Physical') || moves.has('stealthrock'));
case 'Natural Cure':
@@ -1044,7 +1086,7 @@ export class RandomTeams {
case 'Overgrow':
return !counter.get('Grass');
case 'Prankster':
return !counter.get('Status');
return (!counter.get('Status') || (species.id === 'grafaiai' && role === 'Setup Sweeper'));
case 'Reckless':
return !counter.get('recoil');
case 'Regenerator':
@@ -1072,7 +1114,7 @@ export class RandomTeams {
case 'Sticky Hold':
return (species.id === 'muk');
case 'Sturdy':
return !!counter.get('recoil');
return (!!counter.get('recoil') && species.id !== 'skarmory');
case 'Swarm':
return (!counter.get('Bug') || !!counter.get('recovery'));
case 'Swift Swim':
@@ -1093,7 +1135,7 @@ export class RandomTeams {
if (abilities.has('Iron Fist') && counter.ironFist >= 2) return true;
return (this.dex.getEffectiveness('Electric', species) < -1);
case 'Water Absorb':
return (species.id === 'politoed' || species.id === 'quagsire' || moves.has('raindance'));
return (['lanturn', 'politoed', 'quagsire'].includes(species.id) || moves.has('raindance'));
case 'Weak Armor':
return (moves.has('shellsmash') && species.id !== 'magcargo');
}
@@ -1128,10 +1170,13 @@ export class RandomTeams {
if (abilities.has('Guts') && (moves.has('facade') || moves.has('sleeptalk') || species.id === 'gurdurr')) return 'Guts';
if (species.id === 'copperajah' && moves.has('heavyslam')) return 'Heavy Metal';
if (species.id === 'jumpluff') return 'Infiltrator';
if (species.id === 'reuniclus') return (role === 'AV Pivot') ? 'Regenerator' : 'Magic Guard';
if (species.id === 'smeargle') return 'Own Tempo';
if (species.id === 'cetitan' && (role === 'Wallbreaker' || isDoubles)) return 'Sheer Force';
if (species.id === 'ribombee') return 'Shield Dust';
if (species.id === 'dipplin') return 'Sticky Hold';
if (species.id === 'breloom') return 'Technician';
if (species.id === 'porygon2') return 'Trace';
if (species.id === 'shiftry' && moves.has('tailwind')) return 'Wind Rider';
// singles
@@ -1139,15 +1184,17 @@ export class RandomTeams {
if (species.id === 'hypno') return 'Insomnia';
if (species.id === 'staraptor') return 'Reckless';
if (species.id === 'arcaninehisui') return 'Rock Head';
if (species.id === 'vespiquen') return 'Pressure';
if (['raikou', 'suicune', 'vespiquen'].includes(species.id)) return 'Pressure';
if (species.id === 'enamorus' && moves.has('calmmind')) return 'Cute Charm';
if (species.id === 'klawf' && role === 'Setup Sweeper') return 'Anger Shell';
if (abilities.has('Cud Chew') && moves.has('substitute')) return 'Cud Chew';
if (abilities.has('Harvest') && (moves.has('protect') || moves.has('substitute'))) return 'Harvest';
if (abilities.has('Serene Grace') && moves.has('headbutt')) return 'Serene Grace';
if (abilities.has('Own Tempo') && moves.has('petaldance')) return 'Own Tempo';
if (species.id === 'zebstrika') return 'Sap Sipper';
if (abilities.has('Slush Rush') && moves.has('snowscape')) return 'Slush Rush';
if (abilities.has('Soundproof') && (moves.has('substitute') || moves.has('clangoroussoul'))) return 'Soundproof';
if (abilities.has('Soundproof') && (moves.has('substitute') || counter.get('setup'))) return 'Soundproof';
if (species.id === 'cinccino') return (role === 'Setup Sweeper') ? 'Technician' : 'Skill Link';
}
// doubles, multi, and ffa
@@ -1253,10 +1300,11 @@ export class RandomTeams {
) {
return 'Booster Energy';
}
if (species.id === 'pincurchin') return 'Shuca Berry';
if (species.id === 'lokix') {
return (role === 'Fast Attacker') ? 'Silver Powder' : 'Life Orb';
}
if (species.id === 'froslass') return 'Wide Lens';
if (species.id === 'necrozmaduskmane') return 'Weakness Policy';
}
if (species.requiredItems) {
// Z-Crystals aren't available in Gen 9, so require Plates
@@ -1268,6 +1316,7 @@ export class RandomTeams {
if (role === 'AV Pivot') return 'Assault Vest';
if (species.id === 'pikachu') return 'Light Ball';
if (species.id === 'regieleki') return 'Magnet';
if (species.id === 'smeargle') return 'Focus Sash';
if (moves.has('clangoroussoul') || (species.id === 'toxtricity' && moves.has('shiftgear'))) return 'Throat Spray';
if (species.baseSpecies === 'Magearna' && role === 'Tera Blast user') return 'Weakness Policy';
if (moves.has('lastrespects') || moves.has('dragonenergy')) return 'Choice Scarf';
@@ -1275,6 +1324,8 @@ export class RandomTeams {
ability === 'Imposter' ||
(species.id === 'magnezone' && moves.has('bodypress') && !isDoubles)
) return 'Choice Scarf';
if (species.id === 'rampardos' && role === 'Wallbreaker') return 'Choice Band';
if (species.id === 'reuniclus' && ability === 'Magic Guard') return 'Life Orb';
if (moves.has('bellydrum') && moves.has('substitute')) return 'Salac Berry';
if (
['Cheek Pouch', 'Cud Chew', 'Harvest'].some(m => ability === m) ||
@@ -1293,7 +1344,7 @@ export class RandomTeams {
}
}
if (species.id === 'scyther' && !isDoubles) return (isLead && !moves.has('uturn')) ? 'Eviolite' : 'Heavy-Duty Boots';
if (species.nfe || species.id === 'dipplin') return 'Eviolite';
if (species.nfe) return 'Eviolite';
if (ability === 'Poison Heal') return 'Toxic Orb';
if ((ability === 'Guts' || moves.has('facade')) && !moves.has('sleeptalk')) {
return (types.includes('Fire') || ability === 'Toxic Boost') ? 'Toxic Orb' : 'Flame Orb';
@@ -1302,11 +1353,13 @@ export class RandomTeams {
if (ability === 'Anger Shell') return this.sample(['Rindo Berry', 'Passho Berry', 'Scope Lens', 'Sitrus Berry']);
if (moves.has('courtchange')) return 'Heavy-Duty Boots';
if (moves.has('populationbomb')) return 'Wide Lens';
if (moves.has('scaleshot') && role !== 'Choice Item user') return 'Loaded Dice';
if (moves.has('stuffcheeks')) return this.randomChance(1, 2) ? 'Liechi Berry' : 'Salac Berry';
if (
(moves.has('scaleshot') && role !== 'Choice Item user') ||
(counter.get('setup') && (species.id === 'torterra' || species.id === 'cinccino'))
) return 'Loaded Dice';
if (ability === 'Unburden') return moves.has('closecombat') ? 'White Herb' : 'Sitrus Berry';
if (moves.has('shellsmash') && ability !== 'Weak Armor') return 'White Herb';
if (moves.has('acrobatics') && ability !== 'Protosynthesis') return ability === 'Grassy Surge' ? 'Grassy Seed' : '';
if (moves.has('acrobatics') && ability !== 'Protosynthesis') return '';
if (moves.has('auroraveil') || moves.has('lightscreen') && moves.has('reflect')) return 'Light Clay';
if (ability === 'Gluttony') return `${this.sample(['Aguav', 'Figy', 'Iapapa', 'Mago', 'Wiki'])} Berry`;
if (
@@ -1410,8 +1463,7 @@ export class RandomTeams {
): string {
if (types.includes('Normal') && moves.has('fakeout')) return 'Silk Scarf';
if (
species.id !== 'jirachi' && (counter.get('Physical') >= 4 ||
(counter.get('Physical') >= 3 && moves.has('memento'))) &&
species.id !== 'jirachi' && (counter.get('Physical') >= 4) &&
['fakeout', 'firstimpression', 'flamecharge', 'rapidspin', 'ruination', 'superfang'].every(m => !moves.has(m))
) {
const scarfReqs = (
@@ -1482,9 +1534,7 @@ export class RandomTeams {
if (role === 'Fast Support' || role === 'Fast Bulky Setup') {
return (counter.get('Physical') + counter.get('Special') >= 3 && !moves.has('nuzzle')) ? 'Life Orb' : 'Leftovers';
}
if (
role === 'Tera Blast user' && species.baseSpecies === 'Florges'
) return 'Leftovers';
if (role === 'Tera Blast user' && DEFENSIVE_TERA_BLAST_USERS.includes(species.id)) return 'Leftovers';
if (
['flamecharge', 'rapidspin', 'trailblaze'].every(m => !moves.has(m)) &&
['Fast Attacker', 'Setup Sweeper', 'Tera Blast user', 'Wallbreaker'].some(m => role === (m))
@@ -1639,7 +1689,7 @@ export class RandomTeams {
return {
name: species.baseSpecies,
species: forme,
gender: species.gender,
gender: species.baseSpecies === 'Greninja' ? 'M' : species.gender,
shiny: this.randomChance(1, 1024),
level,
moves: shuffledMoves,
@@ -1730,8 +1780,8 @@ export class RandomTeams {
// Limit to one of each species (Species Clause)
if (baseFormes[species.baseSpecies]) continue;
// Treat Ogerpon formes like the Tera Blast user role; reject if team has one already
if (species.baseSpecies === 'Ogerpon' && teamDetails.teraBlast) continue;
// Treat Ogerpon formes and Terapagos like the Tera Blast user role; reject if team has one already
if ((species.baseSpecies === 'Ogerpon' || species.baseSpecies === 'Terapagos') && teamDetails.teraBlast) continue;
// Illusion shouldn't be on the last slot
if (species.baseSpecies === 'Zoroark' && pokemon.length >= (this.maxTeamSize - 1)) continue;
@@ -1843,7 +1893,9 @@ export class RandomTeams {
if (set.moves.includes('auroraveil') || (set.moves.includes('reflect') && set.moves.includes('lightscreen'))) {
teamDetails.screens = 1;
}
if (set.role === 'Tera Blast user' || species.baseSpecies === "Ogerpon") teamDetails.teraBlast = 1;
if (set.role === 'Tera Blast user' || species.baseSpecies === "Ogerpon" || species.baseSpecies === "Terapagos") {
teamDetails.teraBlast = 1;
}
}
if (pokemon.length < this.maxTeamSize && pokemon.length < 12) { // large teams sometimes cannot be built
throw new Error(`Could not build a random team for ${this.format} (seed=${seed})`);