Spaces:
Running
Running
import { RandomGen7Teams, ZeroAttackHPIVs } from '../gen7/teams'; | |
const POWERFUL_ABILITIES = [ | |
'Adaptability', 'Aftermath', 'Analytic', 'Arena Trap', 'Beast Boost', 'Berserk', 'Comatose', 'Competitive', | |
'Compound Eyes', 'Contrary', 'Cursed Body', 'Defiant', 'Desolate Land', 'Download', 'Drizzle', 'Drought', 'Dry Skin', | |
'Effect Spore', 'Filter', 'Flame Body', 'Flash Fire', 'Fluffy', 'Fur Coat', 'Gooey', 'Grassy Surge', 'Heatproof', | |
'Huge Power', 'Hustle', 'Illusion', 'Imposter', 'Innards Out', 'Intimidate', 'Iron Barbs', 'Levitate', 'Lightning Rod', | |
'Magic Bounce', 'Magic Guard', 'Marvel Scale', 'Mold Breaker', 'Moody', 'Motor Drive', 'Moxie', 'Multiscale', | |
'Natural Cure', 'Neuroforce', 'Parental Bond', 'Poison Point', 'Poison Touch', 'Prankster', 'Primordial Sea', 'Prism Armor', | |
'Protean', 'Pure Power', 'Regenerator', 'Rough Skin', 'Sand Stream', 'Sap Sipper', 'Serene Grace', | |
'Shadow Shield', 'Shadow Tag', 'Shed Skin', 'Sheer Force', 'Shield Dust', 'Simple', 'Snow Warning', 'Solid Rock', | |
'Soul-Heart', 'Speed Boost', 'Stakeout', 'Stamina', 'Static', 'Storm Drain', 'Sturdy', 'Tangling Hair', 'Technician', | |
'Teravolt', 'Thick Fat', 'Tinted Lens', 'Tough Claws', 'Trace', 'Triage', 'Turboblaze', 'Unaware', 'Volt Absorb', | |
'Water Absorb', 'Water Bubble', 'Wonder Guard', | |
]; | |
export class RandomGen7ApexTeams extends RandomGen7Teams { | |
randomSet( | |
species: string | Species, | |
teamDetails: RandomTeamsTypes.TeamDetails = {}, | |
isLead = false | |
): RandomTeamsTypes.RandomSet { | |
species = this.dex.species.get(species); | |
const forme = this.getForme(species); | |
const sets = this.randomSets[species.id]["sets"]; | |
const possibleSets = []; | |
// Check if the Pokemon has a Z-Move user set | |
let canZMove = false; | |
for (const set of sets) { | |
if (!teamDetails.zMove && set.role === 'Z-Move user') canZMove = true; | |
} | |
for (const set of sets) { | |
// Prevent multiple Z-Move users | |
if (teamDetails.zMove && set.role === 'Z-Move user') continue; | |
// Prevent Setup Sweeper and Bulky Setup if Z-Move user is available | |
if (canZMove && ['Setup Sweeper', 'Bulky Setup'].includes(set.role)) continue; | |
possibleSets.push(set); | |
} | |
const set = this.sampleIfArray(possibleSets); | |
const role = set.role; | |
const movePool: string[] = Array.from(set.movepool); | |
const preferredTypes = set.preferredTypes; | |
const preferredType = this.sampleIfArray(preferredTypes) || ''; | |
let ability = ''; | |
let item = undefined; | |
const evs = { hp: 85, atk: 85, def: 85, spa: 85, spd: 85, spe: 85 }; | |
const ivs = { hp: 31, atk: 31, def: 31, spa: 31, spd: 31, spe: 31 }; | |
const types = species.types; | |
const baseAbilities = set.abilities!; | |
// Use the mega's ability for moveset generation | |
const abilities = (species.battleOnly && !species.requiredAbility) ? Object.values(species.abilities) : baseAbilities; | |
// Get moves | |
const moves = this.randomMoveset(types, abilities, teamDetails, species, isLead, movePool, | |
preferredType, role); | |
const counter = this.newQueryMoves(moves, species, preferredType, abilities); | |
// Get ability | |
ability = this.getAbility(new Set(types), moves, baseAbilities, counter, movePool, teamDetails, species, | |
preferredType, role); | |
// Get items | |
item = this.getPriorityItem(ability, types, moves, counter, teamDetails, species, isLead, preferredType, role); | |
if (item === undefined) { | |
item = this.getItem(ability, types, moves, counter, teamDetails, species, isLead, preferredType, role); | |
} | |
// For Trick / Switcheroo | |
if (item === 'Leftovers' && types.includes('Poison')) { | |
item = 'Black Sludge'; | |
} | |
const level = this.getLevel(species); | |
// Minimize confusion damage, including if Foul Play is its only physical attack | |
if ( | |
(!counter.get('Physical') || (counter.get('Physical') <= 1 && (moves.has('foulplay') || moves.has('rapidspin')))) && | |
!moves.has('copycat') && !moves.has('transform') | |
) { | |
evs.atk = 0; | |
ivs.atk = 0; | |
} | |
// Override regular ability with a random "powerful" ability | |
ability = this.sample(POWERFUL_ABILITIES); | |
if (ability === 'Beast Boost' && !counter.get('Special')) { | |
evs.spa = 0; | |
ivs.spa = 0; | |
} | |
// We use a special variable to track Hidden Power | |
// so that we can check for all Hidden Powers at once | |
let hasHiddenPower = false; | |
for (const move of moves) { | |
if (move.startsWith('hiddenpower')) hasHiddenPower = true; | |
} | |
// Fix IVs for non-Bottle Cap-able sets | |
if (hasHiddenPower && level < 100) { | |
let hpType; | |
for (const move of moves) { | |
if (move.startsWith('hiddenpower')) hpType = move.substr(11); | |
} | |
if (!hpType) throw new Error(`hasHiddenPower is true, but no Hidden Power move was found.`); | |
const HPivs = ivs.atk === 0 ? ZeroAttackHPIVs[hpType] : this.dex.types.get(hpType).HPivs; | |
let iv: StatID; | |
for (iv in HPivs) { | |
ivs[iv] = HPivs[iv]!; | |
} | |
} | |
// Prepare optimal HP | |
const srImmunity = ability === 'Magic Guard'; | |
const srWeakness = srImmunity ? 0 : this.dex.getEffectiveness('Rock', species); | |
while (evs.hp > 1) { | |
const hp = Math.floor(Math.floor(2 * species.baseStats.hp + ivs.hp + Math.floor(evs.hp / 4) + 100) * level / 100 + 10); | |
if (moves.has('substitute') && !['Black Sludge', 'Leftovers'].includes(item)) { | |
if (item === 'Sitrus Berry') { | |
// Two Substitutes should activate Sitrus Berry | |
if (hp % 4 === 0) break; | |
} else { | |
// Should be able to use Substitute four times from full HP without fainting | |
if (hp % 4 > 0) break; | |
} | |
} else if (moves.has('bellydrum') && (item === 'Sitrus Berry')) { | |
// Belly Drum should activate Sitrus Berry | |
if (hp % 2 === 0) break; | |
} else if (['highjumpkick', 'jumpkick'].some(m => moves.has(m))) { | |
// Crash damage move users want an odd HP to survive two misses | |
if (hp % 2 > 0) break; | |
} else { | |
// Maximize number of Stealth Rock switch-ins | |
if (srWeakness <= 0 || ability === 'Regenerator') break; | |
if (srWeakness === 1 && ['Black Sludge', 'Leftovers', 'Life Orb'].includes(item)) break; | |
if (item !== 'Sitrus Berry' && hp % (4 / srWeakness) > 0) break; | |
// Minimise number of Stealth Rock switch-ins to activate Sitrus Berry | |
if (item === 'Sitrus Berry' && hp % (4 / srWeakness) === 0) break; | |
} | |
evs.hp -= 4; | |
} | |
if (['gyroball', 'metalburst', 'trickroom'].some(m => moves.has(m))) { | |
evs.spe = 0; | |
ivs.spe = (hasHiddenPower && level < 100) ? ivs.spe - 30 : 0; | |
} | |
// shuffle moves to add more randomness to camomons | |
const shuffledMoves = Array.from(moves); | |
this.prng.shuffle(shuffledMoves); | |
// Z-Conversion Porygon-Z should have Shadow Ball first if no Recover, otherwise Thunderbolt | |
if (species.id === 'porygonz' && role === 'Z-Move user') { | |
const firstMove = (moves.has('shadowball') ? 'shadowball' : 'thunderbolt'); | |
this.fastPop(shuffledMoves, shuffledMoves.indexOf(firstMove)); | |
shuffledMoves.unshift(firstMove); | |
} | |
return { | |
name: species.baseSpecies, | |
species: forme, | |
gender: species.baseSpecies === 'Greninja' ? 'M' : species.gender, | |
shiny: this.randomChance(1, 1024), | |
level, | |
moves: shuffledMoves, | |
ability, | |
evs, | |
ivs, | |
item, | |
role, | |
}; | |
} | |
} | |
export default RandomGen7ApexTeams; | |