import BattleScene, { startingWave } from "../battle-scene"; import { ModifierTypeFunc, modifierTypes } from "../modifier/modifier-type"; import { EnemyPokemon } from "../pokemon"; import * as Utils from "../utils"; import { Moves } from "./move"; import { pokemonEvolutions, pokemonPrevolutions } from "./pokemon-evolutions"; import PokemonSpecies, { PokemonSpeciesFilter, getPokemonSpecies } from "./pokemon-species"; import { Species } from "./species"; import { tmSpecies } from "./tms"; import { Type } from "./type"; export enum TrainerType { UNKNOWN, ACE_TRAINER, ARTIST, BACKERS, BACKPACKER, BAKER, BEAUTY, BIKER, BLACK_BELT, BREEDER, CLERK, CYCLIST, DANCER, DEPOT_AGENT, DOCTOR, FISHERMAN, GUITARIST, HARLEQUIN, HIKER, HOOLIGANS, HOOPSTER, INFIELDER, JANITOR, LINEBACKER, MAID, MUSICIAN, NURSE, NURSERY_AIDE, OFFICER, PARASOL_LADY, PILOT, POKEFAN, PRESCHOOLER, PSYCHIC, RANGER, RICH, RICH_KID, ROUGHNECK, SCIENTIST, SMASHER, SNOW_WORKER, STRIKER, STUDENT, SWIMMER, TWINS, VETERAN, WAITER, WORKER, YOUNGSTER, BROCK = 200, MISTY, LT_SURGE, ERIKA, JANINE, SABRINA, BLAINE, GIOVANNI, FALKNER, BUGSY, WHITNEY, MORTY, CHUCK, JASMINE, PRYCE, CLAIR, ROXANNE, BRAWLY, WATTSON, FLANNERY, NORMAN, WINONA, TATE, LIZA, JUAN, ROARK, GARDENIA, MAYLENE, CRASHER_WAKE, FANTINA, BYRON, CANDICE, VOLKNER, CILAN, CHILI, CRESS, CHEREN, LENORA, ROXIE, BURGH, ELESA, CLAY, SKYLA, BRYCEN, DRAYDEN, MARLON, SHAUNTAL = 300, MARSHAL, GRIMSLEY, CAITLIN, BLUE = 325, RED, LANCE, STEVEN, WALLACE, CYNTHIA, ALDER, IRIS, RIVAL = 350, RIVAL_2, RIVAL_3, RIVAL_4, RIVAL_5, RIVAL_6 } export enum TrainerPoolTier { COMMON, UNCOMMON, RARE, SUPER_RARE, ULTRA_RARE } export interface TrainerTierPools { [key: integer]: Species[] } export enum TrainerPartyMemberStrength { WEAKER, WEAK, AVERAGE, STRONG, STRONGER } export class TrainerPartyTemplate { public size: integer; public strength: TrainerPartyMemberStrength; public sameSpecies: boolean; public balanced: boolean; constructor(size: integer, strength: TrainerPartyMemberStrength, sameSpecies?: boolean, balanced?: boolean) { this.size = size; this.strength = strength; this.sameSpecies = !!sameSpecies; this.balanced = !!balanced; } getStrength(index: integer): TrainerPartyMemberStrength { return this.strength; } isSameSpecies(index: integer): boolean { return this.sameSpecies; } isBalanced(index: integer): boolean { return this.balanced; } } export class TrainerPartyCompoundTemplate extends TrainerPartyTemplate { public templates: TrainerPartyTemplate[]; constructor(...templates: TrainerPartyTemplate[]) { super(templates.reduce((total: integer, template: TrainerPartyTemplate) => { total += template.size; return total; }, 0), TrainerPartyMemberStrength.AVERAGE); this.templates = templates; } getStrength(index: integer): TrainerPartyMemberStrength { let t = 0; for (let template of this.templates) { if (t + template.size > index) return template.getStrength(index - t); t += template.size; } return super.getStrength(index); } isSameSpecies(index: integer): boolean { let t = 0; for (let template of this.templates) { if (t + template.size > index) return template.isSameSpecies(index - t); t += template.size; } return super.isSameSpecies(index); } isBalanced(index: integer): boolean { let t = 0; for (let template of this.templates) { if (t + template.size > index) return template.isBalanced(index - t); t += template.size; } return super.isBalanced(index); } } export const trainerPartyTemplates = { ONE_WEAK_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.WEAK), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)), ONE_AVG: new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), ONE_AVG_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)), ONE_STRONG: new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), ONE_STRONGER: new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER), TWO_WEAKER: new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAKER), TWO_WEAK: new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK), TWO_WEAK_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)), TWO_WEAK_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)), TWO_WEAK_SAME_TWO_WEAK_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK, true), new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK, true)), TWO_WEAK_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.WEAK), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)), TWO_AVG: new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE), TWO_AVG_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)), TWO_AVG_SAME_ONE_AVG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)), TWO_AVG_SAME_ONE_STRONG: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)), TWO_AVG_SAME_TWO_AVG_SAME: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true), new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE, true)), TWO_STRONG: new TrainerPartyTemplate(2, TrainerPartyMemberStrength.STRONG), THREE_WEAK: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.WEAK), THREE_WEAK_SAME: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.WEAK, true), THREE_AVG: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE), THREE_AVG_SAME: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, true), THREE_WEAK_BALANCED: new TrainerPartyTemplate(3, TrainerPartyMemberStrength.WEAK, false, true), FOUR_WEAKER: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAKER), FOUR_WEAKER_SAME: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAKER, true), FOUR_WEAK: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAK), FOUR_WEAK_SAME: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAK, true), FOUR_WEAK_BALANCED: new TrainerPartyTemplate(4, TrainerPartyMemberStrength.WEAK, false, true), FIVE_WEAKER: new TrainerPartyTemplate(5, TrainerPartyMemberStrength.WEAKER), FIVE_WEAK: new TrainerPartyTemplate(5, TrainerPartyMemberStrength.WEAK), FIVE_WEAK_BALANCED: new TrainerPartyTemplate(5, TrainerPartyMemberStrength.WEAK, false, true), SIX_WEAK_SAME: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAKER, true), SIX_WEAKER: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAKER), SIX_WEAKER_SAME: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAKER, true), SIX_WEAK_BALANCED: new TrainerPartyTemplate(6, TrainerPartyMemberStrength.WEAK, false, true), GYM_LEADER_1: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER)), GYM_LEADER_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(2, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER)), GYM_LEADER_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER)), GYM_LEADER_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(4, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER)), ELITE_FOUR: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(2, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER)), CHAMPION: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER), new TrainerPartyTemplate(5, TrainerPartyMemberStrength.STRONG, false, true)), RIVAL: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)), RIVAL_2: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE)), RIVAL_3: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE, false, true)), RIVAL_4: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, false, true)), RIVAL_5: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG)), RIVAL_6: new TrainerPartyCompoundTemplate(new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONG), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.AVERAGE), new TrainerPartyTemplate(3, TrainerPartyMemberStrength.AVERAGE, false, true), new TrainerPartyTemplate(1, TrainerPartyMemberStrength.STRONGER)) }; type PartyTemplateFunc = (scene: BattleScene) => TrainerPartyTemplate; type PartyMemberFunc = (scene: BattleScene, level: integer) => EnemyPokemon; export interface PartyMemberFuncs { [key: integer]: PartyMemberFunc } export class TrainerConfig { public trainerType: TrainerType; public name: string; public nameFemale: string; public hasGenders: boolean = false; public isDouble: boolean = false; public moneyMultiplier: number = 1; public isBoss: boolean = false; public hasStaticParty: boolean = false; public useSameSeedForAllMembers: boolean = false; public battleBgm: string; public encounterBgm: string; public femaleEncounterBgm: string; public victoryBgm: string; public modifierRewardFuncs: ModifierTypeFunc[] = []; public partyTemplates: TrainerPartyTemplate[]; public partyTemplateFunc: PartyTemplateFunc; public partyMemberFuncs: PartyMemberFuncs = {}; public speciesPools: TrainerTierPools; public speciesFilter: PokemonSpeciesFilter; public encounterMessages: string[] = []; public victoryMessages: string[] = []; public defeatMessages: string[] = []; public femaleEncounterMessages: string[]; public femaleVictoryMessages: string[]; public femaleDefeatMessages: string[]; constructor(trainerType: TrainerType, allowLegendaries?: boolean) { this.trainerType = trainerType; this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]); this.battleBgm = 'battle_trainer'; this.victoryBgm = 'victory_trainer'; this.partyTemplates = [ trainerPartyTemplates.TWO_AVG ]; this.speciesFilter = species => allowLegendaries || (!species.legendary && !species.pseudoLegendary && !species.mythical); } getKey(female?: boolean): string { let ret = TrainerType[this.getDerivedType()].toString().toLowerCase(); if (this.hasGenders) ret += `_${female ? 'f' : 'm'}`; return ret; } setName(name: string): TrainerConfig { this.name = name; return this; } getDerivedType(): TrainerType { let trainerType = this.trainerType; switch (trainerType) { case TrainerType.RIVAL_2: case TrainerType.RIVAL_3: case TrainerType.RIVAL_4: case TrainerType.RIVAL_5: case TrainerType.RIVAL_6: trainerType = TrainerType.RIVAL; break; } return trainerType; } setHasGenders(nameFemale?: string, femaleEncounterBgm?: TrainerType | string): TrainerConfig { this.hasGenders = true; this.nameFemale = nameFemale; if (femaleEncounterBgm) this.femaleEncounterBgm = typeof femaleEncounterBgm === 'number' ? TrainerType[femaleEncounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : femaleEncounterBgm; return this; } setDouble(): TrainerConfig { this.isDouble = true; return this; } setMoneyMultiplier(moneyMultiplier: number): TrainerConfig { this.moneyMultiplier = moneyMultiplier; return this; } setBoss(): TrainerConfig { this.isBoss = true; return this; } setStaticParty(): TrainerConfig { this.hasStaticParty = true; return this; } setUseSameSeedForAllMembers(): TrainerConfig { this.useSameSeedForAllMembers = true; return this; } setBattleBgm(battleBgm: string): TrainerConfig { this.battleBgm = battleBgm; return this; } setEncounterBgm(encounterBgm: TrainerType | string): TrainerConfig { this.encounterBgm = typeof encounterBgm === 'number' ? TrainerType[encounterBgm].toString().replace(/\_/g, ' ').toLowerCase() : encounterBgm; return this; } setVictoryBgm(victoryBgm: string): TrainerConfig { this.victoryBgm = victoryBgm; return this; } setPartyTemplates(...partyTemplates: TrainerPartyTemplate[]): TrainerConfig { this.partyTemplates = partyTemplates; return this; } setPartyTemplateFunc(partyTemplateFunc: PartyTemplateFunc): TrainerConfig { this.partyTemplateFunc = partyTemplateFunc; return this; } setPartyMemberFunc(slotIndex: integer, partyMemberFunc: PartyMemberFunc): TrainerConfig { this.partyMemberFuncs[slotIndex] = partyMemberFunc; return this; } setSpeciesPools(speciesPools: TrainerTierPools | Species[]): TrainerConfig { this.speciesPools = (Array.isArray(speciesPools) ? { [TrainerPoolTier.COMMON]: speciesPools } : speciesPools) as unknown as TrainerTierPools; return this; } setSpeciesFilter(speciesFilter: PokemonSpeciesFilter, allowLegendaries?: boolean): TrainerConfig { const baseFilter = this.speciesFilter; this.speciesFilter = allowLegendaries ? speciesFilter : species => speciesFilter(species) && baseFilter(species); return this; } setEncounterMessages(messages: string[], femaleMessages?: string[]): TrainerConfig { this.encounterMessages = messages; this.femaleEncounterMessages = femaleMessages; return this; } setVictoryMessages(messages: string[], femaleMessages?: string[]): TrainerConfig { this.victoryMessages = messages; this.femaleVictoryMessages = femaleMessages; return this; } setDefeatMessages(messages: string[], femaleMessages?: string[]): TrainerConfig { this.defeatMessages = messages; this.femaleDefeatMessages = femaleMessages; return this; } setModifierRewardFuncs(...modifierTypeFuncs: (() => ModifierTypeFunc)[]): TrainerConfig { this.modifierRewardFuncs = modifierTypeFuncs.map(func => () => { const modifierTypeFunc = func(); const modifierType = modifierTypeFunc(); modifierType.id = Object.keys(modifierTypes).find(k => modifierTypes[k] === modifierTypeFunc); return modifierType; }); return this; } initForGymLeader(signatureSpecies: Species, specialtyType?: Type): TrainerConfig { this.setPartyTemplateFunc(getGymLeaderPartyTemplate); this.setPartyMemberFunc(-1, getRandomPartyMemberFunc([ signatureSpecies ])); if (specialtyType !== undefined) this.setSpeciesFilter(p => p.isOfType(specialtyType)); this.setMoneyMultiplier(2.5); this.setBoss(); this.setStaticParty(); this.setBattleBgm('battle_gym'); this.setVictoryBgm('victory_gym'); return this; } initForEliteFour(signatureSpecies: Species, specialtyType?: Type): TrainerConfig { this.setPartyTemplates(trainerPartyTemplates.ELITE_FOUR); this.setPartyMemberFunc(-1, getRandomPartyMemberFunc([ signatureSpecies ])); if (specialtyType !== undefined) this.setSpeciesFilter(p => p.isOfType(specialtyType) && p.baseTotal >= 450); else this.setSpeciesFilter(p => p.baseTotal >= 450); this.setMoneyMultiplier(3.25); this.setBoss(); this.setStaticParty(); this.setBattleBgm('battle_elite'); this.setVictoryBgm('victory_gym'); return this; } initForChampion(signatureSpecies: Species): TrainerConfig { this.setPartyTemplates(trainerPartyTemplates.CHAMPION); this.setPartyMemberFunc(-1, getRandomPartyMemberFunc([ signatureSpecies ])); this.setSpeciesFilter(p => p.baseTotal >= 470); this.setMoneyMultiplier(10); this.setBoss(); this.setStaticParty(); this.setBattleBgm('battle_champion'); this.setVictoryBgm('victory_champion'); return this; } getName(female?: boolean): string { let ret = this.name; if (this.hasGenders) { if (this.nameFemale) { if (female) return this.nameFemale; } else ret += !female ? '♂' : '♀'; } return ret; } loadAssets(scene: BattleScene, female: boolean): Promise { return new Promise(resolve => { const trainerKey = this.getKey(female); scene.loadAtlas(trainerKey, 'trainer'); scene.load.once(Phaser.Loader.Events.COMPLETE, () => { const originalWarn = console.warn; // Ignore warnings for missing frames, because there will be a lot console.warn = () => {}; const frameNames = scene.anims.generateFrameNames(trainerKey, { zeroPad: 4, suffix: ".png", start: 1, end: 128 }); console.warn = originalWarn; scene.anims.create({ key: trainerKey, frames: frameNames, frameRate: 24, repeat: -1 }); resolve(); }); if (!scene.load.isLoading()) scene.load.start(); }); } } let t = 0; interface TrainerConfigs { [key: integer]: TrainerConfig } function getWavePartyTemplate(scene: BattleScene, ...templates: TrainerPartyTemplate[]) { return templates[Math.min(Math.max(Math.ceil(((scene.currentBattle?.waveIndex || startingWave) - 10) / 20) - 1, 0), templates.length - 1)]; } function getGymLeaderPartyTemplate(scene: BattleScene) { return getWavePartyTemplate(scene, trainerPartyTemplates.GYM_LEADER_1, trainerPartyTemplates.GYM_LEADER_2, trainerPartyTemplates.GYM_LEADER_3, trainerPartyTemplates.GYM_LEADER_4); } function getRandomPartyMemberFunc(speciesPool: Species[], postProcess?: (enemyPokemon: EnemyPokemon) => void): PartyMemberFunc { return (scene: BattleScene, level: integer) => { const species = getPokemonSpecies(Phaser.Math.RND.pick(speciesPool)).getSpeciesForLevel(level, true); const ret = new EnemyPokemon(scene, getPokemonSpecies(species), level, true); if (postProcess) postProcess(ret); return ret; }; } function getSpeciesFilterRandomPartyMemberFunc(speciesFilter: PokemonSpeciesFilter, allowLegendaries?: boolean, postProcess?: (EnemyPokemon: EnemyPokemon) => void): PartyMemberFunc { const originalSpeciesFilter = speciesFilter; speciesFilter = (species: PokemonSpecies) => allowLegendaries || (!species.legendary && !species.pseudoLegendary && !species.mythical) && originalSpeciesFilter(species); return (scene: BattleScene, level: integer) => { const ret = new EnemyPokemon(scene, scene.randomSpecies(scene.currentBattle.waveIndex, level, false, speciesFilter), level, true); if (postProcess) postProcess(ret); return ret; }; } export const trainerConfigs: TrainerConfigs = { [TrainerType.UNKNOWN]: new TrainerConfig(0).setHasGenders(), [TrainerType.ACE_TRAINER]: new TrainerConfig(++t).setHasGenders().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.ACE_TRAINER) .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.THREE_WEAK_BALANCED, trainerPartyTemplates.FOUR_WEAK_BALANCED, trainerPartyTemplates.FIVE_WEAK_BALANCED, trainerPartyTemplates.SIX_WEAK_BALANCED)), [TrainerType.ARTIST]: new TrainerConfig(++t).setEncounterBgm(TrainerType.RICH).setPartyTemplates(trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.THREE_AVG) .setSpeciesPools([ Species.SMEARGLE ]), [TrainerType.BACKERS]: new TrainerConfig(++t).setHasGenders().setDouble().setEncounterBgm(TrainerType.CYCLIST), [TrainerType.BACKPACKER]: new TrainerConfig(++t).setHasGenders().setSpeciesFilter(s => s.isOfType(Type.FLYING) || s.isOfType(Type.ROCK)).setEncounterBgm(TrainerType.BACKPACKER) .setPartyTemplates(trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.ONE_WEAK_ONE_STRONG, trainerPartyTemplates.ONE_AVG_ONE_STRONG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.RHYHORN, Species.AIPOM, Species.MAKUHITA, Species.MAWILE, Species.NUMEL, Species.LILLIPUP, Species.SANDILE, Species.WOOLOO ], [TrainerPoolTier.UNCOMMON]: [ Species.GIRAFARIG, Species.ZANGOOSE, Species.SEVIPER, Species.CUBCHOO, Species.PANCHAM, Species.SKIDDO, Species.MUDBRAY ], [TrainerPoolTier.RARE]: [ Species.TAUROS, Species.STANTLER, Species.DARUMAKA, Species.BOUFFALANT, Species.DEERLING, Species.IMPIDIMP ], [TrainerPoolTier.SUPER_RARE]: [ Species.GALAR_DARUMAKA, Species.TEDDIURSA ] }), [TrainerType.BAKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setMoneyMultiplier(1.35).setSpeciesFilter(s => s.isOfType(Type.GRASS) || s.isOfType(Type.FIRE)), [TrainerType.BEAUTY]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.PARASOL_LADY), [TrainerType.BIKER]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.POISON)), [TrainerType.BLACK_BELT]: new TrainerConfig(++t).setHasGenders('Battle Girl', TrainerType.PSYCHIC).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.FIGHTING)) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK_ONE_AVG, trainerPartyTemplates.TWO_WEAK_ONE_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_ONE_STRONG, trainerPartyTemplates.THREE_AVG, trainerPartyTemplates.TWO_AVG_ONE_STRONG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.NIDORAN_F, Species.NIDORAN_M, Species.MACHOP, Species.MAKUHITA, Species.MEDITITE, Species.CROAGUNK, Species.TIMBURR ], [TrainerPoolTier.UNCOMMON]: [ Species.MANKEY, Species.POLIWRATH, Species.TYROGUE, Species.BRELOOM, Species.SCRAGGY, Species.MIENFOO, Species.PANCHAM, Species.STUFFUL, Species.CRABRAWLER ], [TrainerPoolTier.RARE]: [ Species.HERACROSS, Species.RIOLU, Species.THROH, Species.SAWK, /* Species.CLOBBOPUS, */ Species.PASSIMIAN ], [TrainerPoolTier.SUPER_RARE]: [ Species.INFERNAPE, Species.GALLADE, Species.HITMONTOP, Species.HAWLUCHA, Species.HAKAMO_O ], [TrainerPoolTier.ULTRA_RARE]: [ Species.KUBFU ] }), [TrainerType.BREEDER]: new TrainerConfig(++t).setMoneyMultiplier(1.325).setEncounterBgm(TrainerType.POKEFAN).setHasGenders().setDouble() .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.FOUR_WEAKER, trainerPartyTemplates.FIVE_WEAKER, trainerPartyTemplates.SIX_WEAKER)), [TrainerType.CLERK]: new TrainerConfig(++t).setHasGenders().setEncounterBgm(TrainerType.CLERK) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_ONE_AVG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.MEOWTH, Species.PSYDUCK, Species.BUDEW, Species.PIDOVE, Species.CINCCINO, Species.LITLEO ], [TrainerPoolTier.UNCOMMON]: [ Species.JIGGLYPUFF, Species.MAGNEMITE, Species.MARILL, Species.COTTONEE, Species.SKIDDO ], [TrainerPoolTier.RARE]: [ Species.BUIZEL, Species.SNEASEL, Species.KLEFKI, Species.INDEEDEE ] }), [TrainerType.CYCLIST]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setHasGenders().setEncounterBgm(TrainerType.CYCLIST).setSpeciesFilter(s => !!s.getLevelMoves().find(plm => plm[1] === Moves.QUICK_ATTACK)) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.ONE_AVG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.PICHU, Species.STARLY, Species.TAILLOW, Species.BOLTUND ], [TrainerPoolTier.UNCOMMON]: [ Species.DODUO, Species.ELECTRIKE, Species.BLITZLE, /* Species.WATTREL */], [TrainerPoolTier.RARE]: [ Species.YANMA, Species.NINJASK, Species.WHIRLIPEDE, Species.EMOLGA ], [TrainerPoolTier.SUPER_RARE]: [ Species.ACCELGOR, Species.DREEPY ] }), [TrainerType.DANCER]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.CYCLIST) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_SAME_TWO_WEAK_SAME) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.RALTS, Species.SPOINK, Species.LOTAD, Species.BUDEW ], [TrainerPoolTier.UNCOMMON]: [ Species.SPINDA, Species.SWABLU, Species.MARACTUS,], [TrainerPoolTier.RARE]: [ Species.BELLOSSOM, Species.HITMONTOP, Species.MIME_JR, Species.ORICORIO ], [TrainerPoolTier.SUPER_RARE]: [ Species.POPPLIO ] }), [TrainerType.DEPOT_AGENT]: new TrainerConfig(++t).setMoneyMultiplier(1.45).setEncounterBgm(TrainerType.CLERK), [TrainerType.DOCTOR]: new TrainerConfig(++t).setMoneyMultiplier(3).setEncounterBgm(TrainerType.CLERK), [TrainerType.FISHERMAN]: new TrainerConfig(++t).setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.BACKPACKER) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.THREE_WEAK_SAME, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.SIX_WEAKER) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.TENTACOOL, Species.MAGIKARP, Species.GOLDEEN, Species.STARYU, Species.REMORAID, Species.SKRELP, Species.CLAUNCHER, Species.ARROKUDA ], [TrainerPoolTier.UNCOMMON]: [ Species.POLIWAG, Species.SHELLDER, Species.KRABBY, Species.HORSEA, Species.CARVANHA, Species.BARBOACH, Species.CORPHISH, Species.FINNEON, Species.TYMPOLE, Species.BASCULIN, Species.FRILLISH, Species.INKAY ], [TrainerPoolTier.RARE]: [ Species.CHINCHOU, Species.CORSOLA, Species.WAILMER, Species.BARBOACH, Species.CLAMPERL, Species.LUVDISC, Species.MANTYKE, Species.ALOMOMOLA, /* Species.TATSUGIRI */ /* Species.VELUZA */ ], [TrainerPoolTier.SUPER_RARE]: [ Species.LAPRAS, Species.FEEBAS, Species.RELICANTH, /* Species.DONDOZO */ ] }), [TrainerType.GUITARIST]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.ELECTRIC)), [TrainerType.HARLEQUIN]: new TrainerConfig(++t).setEncounterBgm(TrainerType.PSYCHIC).setSpeciesFilter(s => tmSpecies[Moves.TRICK_ROOM].indexOf(s.speciesId) > -1), [TrainerType.HIKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.BACKPACKER).setSpeciesFilter(s => s.isOfType(Type.GROUND) || s.isOfType(Type.ROCK)) .setPartyTemplates(trainerPartyTemplates.TWO_AVG_SAME_ONE_AVG, trainerPartyTemplates.TWO_AVG_SAME_ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.FOUR_WEAK, trainerPartyTemplates.ONE_STRONG) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.SANDSHREW, Species.DIGLETT, Species.GEODUDE, Species.MACHOP, Species.ARON, Species.ROGGENROLA, Species.DRILBUR, /* Species.NACLI */ ], [TrainerPoolTier.UNCOMMON]: [ Species.ZUBAT, Species.RHYHORN, Species.ONIX, Species.CUBONE, Species.WOOBAT, Species.SWINUB, Species.NOSEPASS, Species.HIPPOPOTAS, Species.DWEBBLE, /* Species.KLAWF */ /* Species.TOEDSCOOL */ ], [TrainerPoolTier.RARE]: [ Species.TORKOAL, Species.TRAPINCH, Species.BARBOACH, Species.GOLETT, Species.ALOLA_DIGLETT, Species.ALOLA_GEODUDE, Species.GALAR_STUNFISK /* Species.PALDEA_WOOPER */ ], [TrainerPoolTier.SUPER_RARE]: [ Species.MAGBY, Species.LARVITAR ] }), [TrainerType.HOOLIGANS]: new TrainerConfig(++t).setDouble().setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.POISON) || s.isOfType(Type.DARK)), [TrainerType.HOOPSTER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.INFIELDER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.JANITOR]: new TrainerConfig(++t).setMoneyMultiplier(1.1).setEncounterBgm(TrainerType.CLERK), [TrainerType.LINEBACKER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.MAID]: new TrainerConfig(++t).setMoneyMultiplier(1.6).setEncounterBgm(TrainerType.RICH), [TrainerType.MUSICIAN]: new TrainerConfig(++t).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => !!s.getLevelMoves().find(plm => plm[1] === Moves.SING)), [TrainerType.NURSE]: new TrainerConfig(++t).setMoneyMultiplier(1.8).setEncounterBgm('lass').setSpeciesFilter(s => !!s.getLevelMoves().find(plm => plm[1] === Moves.CHARM) || !!s.getLevelMoves().find(plm => plm[1] === Moves.HEAL_PULSE)), [TrainerType.NURSERY_AIDE]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setEncounterBgm('lass'), [TrainerType.OFFICER]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.CLERK) .setPartyTemplates(trainerPartyTemplates.ONE_AVG, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, ) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.VULPIX, Species.GROWLITHE, Species.SNUBBULL, Species.POOCHYENA, Species.ELECTRIKE, Species.LILLIPUP, Species.YAMPER /* , Species.FIDOUGH */ ], [TrainerPoolTier.UNCOMMON]: [ Species.HOUNDOUR, Species.ROCKRUFF /*, Species.MASCHIFF */ ], [TrainerPoolTier.RARE]: [ Species.JOLTEON, Species.RIOLU ], [TrainerPoolTier.SUPER_RARE]: [], [TrainerPoolTier.ULTRA_RARE]: [ Species.ENTEI, Species.SUICUNE, Species.RAIKOU ] }), [TrainerType.PARASOL_LADY]: new TrainerConfig(++t).setMoneyMultiplier(1.55).setEncounterBgm(TrainerType.PARASOL_LADY).setSpeciesFilter(s => s.isOfType(Type.WATER)), [TrainerType.PILOT]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => tmSpecies[Moves.FLY].indexOf(s.speciesId) > -1), [TrainerType.POKEFAN]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setHasGenders().setEncounterBgm(TrainerType.POKEFAN) .setPartyTemplates(trainerPartyTemplates.SIX_WEAKER, trainerPartyTemplates.FOUR_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.ONE_STRONG, trainerPartyTemplates.FOUR_WEAK_SAME, trainerPartyTemplates.FIVE_WEAK, trainerPartyTemplates.SIX_WEAKER_SAME), [TrainerType.PRESCHOOLER]: new TrainerConfig(++t).setMoneyMultiplier(0.2).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders(undefined, 'lass') .setPartyTemplates(trainerPartyTemplates.THREE_WEAK, trainerPartyTemplates.FOUR_WEAKER, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.FIVE_WEAKER) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.CATERPIE, Species.PICHU, Species.SANDSHREW, Species.LEDYBA, Species.BUDEW, Species.BURMY, Species.WOOLOO, /* Species.PAWMI, Species.SMOLIV, */ ], [TrainerPoolTier.UNCOMMON]: [ Species.EEVEE, Species.CLEFFA, Species.IGGLYBUFF, Species.SWINUB, Species.WOOPER, Species.DRIFLOON, Species.DEDENNE, Species.STUFFUL ], [TrainerPoolTier.RARE]: [ Species.RALTS, Species.RIOLU, Species.JOLTIK /* Species.TANDEMAUS, */ ], [TrainerPoolTier.SUPER_RARE]: [ Species.DARUMAKA, /* Species.TINKATINK, */], }), [TrainerType.PSYCHIC]: new TrainerConfig(++t).setHasGenders().setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.PSYCHIC) .setPartyTemplates(trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_WEAK_SAME_ONE_AVG, trainerPartyTemplates.TWO_WEAK_SAME_TWO_WEAK_SAME, trainerPartyTemplates.ONE_STRONGER) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.ABRA, Species.DROWZEE, Species.RALTS, Species.SPOINK, Species.GOTHITA, Species.SOLOSIS, Species.BLIPBUG, Species.ESPURR, Species.HATENNA ], [TrainerPoolTier.UNCOMMON]: [ Species.MIME_JR, Species.EXEGGCUTE, Species.MEDITITE, Species.NATU, Species.EXEGGCUTE, Species.WOOBAT, Species.INKAY, Species.ORANGURU ], [TrainerPoolTier.RARE]: [ Species.ELGYEM, Species.SIGILYPH, Species.BALTOY, Species.GIRAFARIG, Species.MEOWSTIC ], [TrainerPoolTier.SUPER_RARE]: [ Species.BELDUM, Species.ESPEON, Species.WYRDEER ], }), [TrainerType.RANGER]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.BACKPACKER).setHasGenders() .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.PICHU, Species.GROWLITHE, Species.PONYTA, Species.ZIGZAGOON, Species.SEEDOT, Species.BIDOOF, Species.RIOLU, Species.SEWADDLE, Species.SKIDDO, Species.SALANDIT, Species.YAMPER ], [TrainerPoolTier.UNCOMMON]: [ Species.AZURILL, Species.TAUROS, Species.MAREEP, Species.FARFETCHD, Species.TEDDIURSA, Species.SHROOMISH, Species.ELECTRIKE, Species.BUDEW, Species.BUIZEL, Species.MUDBRAY, Species.STUFFUL ], [TrainerPoolTier.RARE]: [ Species.EEVEE, Species.SCYTHER, Species.KANGASKHAN, Species.RALTS, Species.MUNCHLAX, Species.ZORUA, /* Species.PALDEA_TAUROS */ /* Species.TINKATINK */ /* Species.CYCLIZAR */ /* Species.FLAMIGO */ ], [TrainerPoolTier.SUPER_RARE]: [ Species.LARVESTA ], }), [TrainerType.RICH]: new TrainerConfig(++t).setMoneyMultiplier(5).setName('Gentleman').setHasGenders(), [TrainerType.RICH_KID]: new TrainerConfig(++t).setMoneyMultiplier(3.75).setName('Rich Boy').setHasGenders('Lady').setEncounterBgm(TrainerType.RICH), [TrainerType.ROUGHNECK]: new TrainerConfig(++t).setMoneyMultiplier(1.4).setEncounterBgm(TrainerType.ROUGHNECK).setSpeciesFilter(s => s.isOfType(Type.DARK)), [TrainerType.SCIENTIST]: new TrainerConfig(++t).setHasGenders().setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.SCIENTIST) .setSpeciesPools({ [TrainerPoolTier.COMMON]: [ Species.MAGNEMITE, Species.GRIMER, Species.DROWZEE, Species.VOLTORB, Species.KOFFING ], [TrainerPoolTier.UNCOMMON]: [ Species.BALTOY, Species.BRONZOR, Species.FERROSEED, Species.KLINK, Species.CHARJABUG, Species.BLIPBUG, Species.HELIOPTILE ], [TrainerPoolTier.RARE ]: [ Species.ABRA, Species.DITTO, Species.PORYGON, Species.ELEKID, Species.SOLOSIS, Species.GALAR_WEEZING ], [TrainerPoolTier.SUPER_RARE ]: [ Species.OMANYTE, Species.KABUTO, Species.AERODACTYL, Species.LILEEP, Species.ANORITH, Species.CRANIDOS, Species.SHIELDON, Species.TIRTOUGA, Species.ARCHEN, Species.ARCTOVISH, Species.ARCTOZOLT, Species.DRACOVISH, Species.DRACOZOLT ], [TrainerPoolTier.ULTRA_RARE]: [ Species.ROTOM, Species.MELTAN ] }), [TrainerType.SMASHER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.SNOW_WORKER]: new TrainerConfig(++t).setName('Worker').setMoneyMultiplier(1.7).setEncounterBgm(TrainerType.CLERK).setSpeciesFilter(s => s.isOfType(Type.ICE) || s.isOfType(Type.STEEL)), [TrainerType.STRIKER]: new TrainerConfig(++t).setMoneyMultiplier(1.2).setEncounterBgm(TrainerType.CYCLIST), [TrainerType.STUDENT]: new TrainerConfig(++t).setHasGenders(), [TrainerType.SWIMMER]: new TrainerConfig(++t).setMoneyMultiplier(1.3).setEncounterBgm(TrainerType.PARASOL_LADY).setHasGenders().setSpeciesFilter(s => s.isOfType(Type.WATER)), [TrainerType.TWINS]: new TrainerConfig(++t).setDouble().setMoneyMultiplier(0.65).setUseSameSeedForAllMembers() .setPartyTemplateFunc(scene => getWavePartyTemplate(scene, trainerPartyTemplates.TWO_WEAK, trainerPartyTemplates.TWO_AVG, trainerPartyTemplates.TWO_STRONG)) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.PLUSLE, Species.VOLBEAT, Species.PACHIRISU, Species.SILCOON, Species.METAPOD, Species.IGGLYBUFF, Species.PETILIL, Species.EEVEE ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.MINUN, Species.ILLUMISE, Species.EMOLGA, Species.CASCOON, Species.KAKUNA, Species.CLEFFA, Species.COTTONEE, Species.EEVEE ])) .setEncounterBgm(TrainerType.TWINS), [TrainerType.VETERAN]: new TrainerConfig(++t).setHasGenders().setMoneyMultiplier(2.5).setEncounterBgm(TrainerType.RICH), [TrainerType.WAITER]: new TrainerConfig(++t).setHasGenders().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.CLERK), [TrainerType.WORKER]: new TrainerConfig(++t).setEncounterBgm(TrainerType.CLERK).setMoneyMultiplier(1.7).setSpeciesFilter(s => s.isOfType(Type.ROCK) || s.isOfType(Type.STEEL)), [TrainerType.YOUNGSTER]: new TrainerConfig(++t).setMoneyMultiplier(0.5).setEncounterBgm(TrainerType.YOUNGSTER).setHasGenders('Lass', 'lass').setPartyTemplates(trainerPartyTemplates.TWO_WEAKER) .setSpeciesPools( [ Species.CATERPIE, Species.WEEDLE, Species.RATTATA, Species.SENTRET, Species.POOCHYENA, Species.ZIGZAGOON, Species.WURMPLE, Species.BIDOOF, Species.PATRAT, Species.LILLIPUP ] ).setEncounterMessages([ `Hey, wanna battle?`, `Are you a new trainer too?`, `Hey, I haven't seen you before. Let's battle!` ], [ `Let's have a battle, shall we?`, `You look like a new trainer. Let's have a battle!`, `I don't recognize you. How about a battle?` ]).setVictoryMessages([ `Wow! You're strong!`, `I didn't stand a chance, huh.`, `I'll find you again when I'm older and beat you!` ], [ `That was impressive! I've got a lot to learn.`, `I didn't think you'd beat me that bad…`, `I hope we get to have a rematch some day.` ]), [TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)).initForGymLeader(Species.GEODUDE, Type.ROCK), [TrainerType.MISTY]: new TrainerConfig(++t).initForGymLeader(Species.STARYU, Type.WATER), [TrainerType.LT_SURGE]: new TrainerConfig(++t).initForGymLeader(Species.ELECTABUZZ, Type.ELECTRIC), [TrainerType.ERIKA]: new TrainerConfig(++t).initForGymLeader(Species.TANGELA, Type.GRASS), [TrainerType.JANINE]: new TrainerConfig(++t).initForGymLeader(Species.VENONAT, Type.POISON), [TrainerType.SABRINA]: new TrainerConfig(++t).initForGymLeader(Species.ALAKAZAM, Type.PSYCHIC), [TrainerType.BLAINE]: new TrainerConfig(++t).initForGymLeader(Species.MAGMAR, Type.FIRE), [TrainerType.GIOVANNI]: new TrainerConfig(++t).initForGymLeader(Species.SANDILE, Type.DARK), [TrainerType.FALKNER]: new TrainerConfig(++t).initForGymLeader(Species.PIDGEY, Type.FLYING), [TrainerType.BUGSY]: new TrainerConfig(++t).initForGymLeader(Species.SCYTHER, Type.BUG), [TrainerType.WHITNEY]: new TrainerConfig(++t).initForGymLeader(Species.MILTANK, Type.FAIRY), [TrainerType.MORTY]: new TrainerConfig(++t).initForGymLeader(Species.GASTLY, Type.GHOST), [TrainerType.CHUCK]: new TrainerConfig(++t).initForGymLeader(Species.POLIWRATH, Type.FIGHTING), [TrainerType.JASMINE]: new TrainerConfig(++t).initForGymLeader(Species.STEELIX, Type.STEEL), [TrainerType.PRYCE]: new TrainerConfig(++t).initForGymLeader(Species.SWINUB, Type.ICE), [TrainerType.CLAIR]: new TrainerConfig(++t).initForGymLeader(Species.DRATINI, Type.DRAGON), [TrainerType.ROXANNE]: new TrainerConfig(++t).initForGymLeader(Species.NOSEPASS, Type.ROCK) .setEncounterMessages([ `Would you kindly demonstrate how you battle?`, `You can learn many things by battling many trainers.`, `Oh, you caught me strategizing.\nWould you like to battle?` ]).setVictoryMessages([ `Oh, I appear to have lost.\nI understand.`, `It seems that I still have so much more to learn when it comes to battle.`, `I'll take what I learned here today to heart.` ]).setDefeatMessages([ `I have learned many things from our battle.\nI hope you have too.`, `I look forward to battling you again.\nI hope you'll use what you've learned here.`, `I won due to everything I have learned.` ]), [TrainerType.BRAWLY]: new TrainerConfig(++t).initForGymLeader(Species.MAKUHITA, Type.FIGHTING) .setEncounterMessages([ `Oh man, a challenger!\nLet's see what you can do!`, `You seem like a big splash.\nLet's battle!`, `Time to create a storm!\nLet's go!` ]).setVictoryMessages([ `Oh woah, you've washed me out!`, `You surfed my wave and crashed me down!`, `I feel like I'm lost in Granite Cave!` ]).setDefeatMessages([ `Haha, I surfed the big wave!\nChallenge me again sometime.`, `Surf with me again some time!`, `Just like the tides come in and out, I hope you return to challenge me again.` ]), [TrainerType.WATTSON]: new TrainerConfig(++t).initForGymLeader(Species.ELECTRIKE, Type.ELECTRIC) .setEncounterMessages([ `Time to get shocked!\nWahahahaha!`, `I'll make sparks fly!\nWahahahaha!`, `I hope you brought Paralyz Heal!\nWahahahaha!` ]).setVictoryMessages([ `Seems like I'm out of charge!\nWahahahaha!`, `You've completely grounded me!\nWahahahaha!`, `Thanks for the thrill!\nWahahahaha!` ]).setDefeatMessages([ `Recharge your batteries and challenge me again sometime!\nWahahahaha!`, `I hope you found our battle electrifying!\nWahahahaha!`, `Aren't you shocked I won?\nWahahahaha!` ]), [TrainerType.FLANNERY]: new TrainerConfig(++t).initForGymLeader(Species.TORKOAL, Type.FIRE) .setEncounterMessages([ `Nice to meet you! Wait, no…\nI will crush you!`, `I've only been a leader for a little while, but I'll smoke you!`, `It's time to demonstrate the moves my grandfather has taught me! Let's battle!` ]).setVictoryMessages([ `You remind me of my grandfather…\nNo wonder I lost.`, `Am I trying too hard?\nI should relax, can't get too heated.`, `Losing isn't going to smother me out.\nTime to reignite training!` ]).setDefeatMessages([ `I hope I've made my grandfather proud…\nLet's battle again some time.`, `I…I can't believe I won!\nDoing things my way worked!`, `Let's exchange burning hot moves again soon!` ]), [TrainerType.NORMAN]: new TrainerConfig(++t).initForGymLeader(Species.SLAKOTH, Type.NORMAL) .setEncounterMessages([ `I'm surprised you managed to get here.\nLet's battle.`, `I'll do everything in my power as a Gym Leader to win.\nLet's go!`, `You better give this your all.\nIt's time to battle!` ]).setVictoryMessages([ `I lost to you…?\nRules are rules, though.`, `Was moving from Olivine a mistake…?`, `I can't believe it.\nThat was a great match.` ]).setDefeatMessages([ `We both tried our best.\nI hope we can battle again soon.`, `You should try challenging my kid instead.\nYou might learn something!`, `Thank you for the excellent battle.\nBetter luck next time.` ]), [TrainerType.WINONA]: new TrainerConfig(++t).initForGymLeader(Species.SWABLU, Type.FLYING) .setEncounterMessages([ `I've been soaring the skies looking for prey…\nAnd you're my target!`, `No matter how our battle is, my Flying Pokémon and I will triumph with grace. Let's battle!`, `I hope you aren't scared of heights.\nLet's ascend!` ]).setVictoryMessages([ `You're the first Trainer I've seen with more grace than I.\nExcellently played.`, `Oh, my Flying Pokémon have plummeted!\nVery well.`, `Though I may have fallen, my Pokémon will continue to fly!` ]).setDefeatMessages([ `My Flying Pokémon and I will forever dance elegantly!`, `I hope you enjoyed our show.\nOur graceful dance is finished.`, `Won't you come see our elegant choreography again?` ]), [TrainerType.TATE]: new TrainerConfig(++t).initForGymLeader(Species.SOLROCK, Type.PSYCHIC) .setEncounterMessages([ `Hehehe…\nWere you surprised to see me without my sister?`, `I can see what you're thinking…\nYou want to battle!`, `How can you defeat someone…\nWho knows your every move?` ]).setVictoryMessages([ `It can't be helped…\nI miss Liza…`, `Your bond with your Pokémon was stronger than mine.`, `If I were with Liza, we would have won.\nWe can finish each other's thoughts!` ]).setDefeatMessages([ `My Pokémon and I are superior!`, `If you can't even defeat me, you'll never be able to defeat Liza either.`, `It's all thanks to my strict training with Liza.\nI can make myself one with Pokémon.` ]), [TrainerType.LIZA]: new TrainerConfig(++t).initForGymLeader(Species.LUNATONE, Type.PSYCHIC) .setEncounterMessages([ `Fufufu…\nWere you surprised to see me without my brother?`, `I can determine what you desire…\nYou want to battle, don't you?`, `How can you defeat someone…\nWho's one with their Pokémon?` ]).setVictoryMessages([ `It can't be helped…\nI miss Tate…`, `Your bond with your Pokémon…\nIt's stronger than mine.`, `If I were with Tate, we would have won.\nWe can finish each other's sentences!` ]).setDefeatMessages([ `My Pokémon and I are victorious.`, `If you can't even defeat me, you'll never be able to defeat Tate either.`, `It's all thanks to my strict training with Tate.\nI can synchronize myself with my Pokémon.` ]), [TrainerType.JUAN]: new TrainerConfig(++t).initForGymLeader(Species.HORSEA, Type.WATER) .setEncounterMessages([ `Now's not the time to act coy.\nLet's battle!`, `Ahahaha, You'll be witness to my artistry with Water Pokémon!`, `A typhoon approaches!\nWill you be able to test me?` ]).setVictoryMessages([ `You may be a genius who can take on Wallace!`, `I focused on elegance while you trained.\nIt's only natural that you defeated me.`, `Ahahaha!\nVery well, You have won this time.` ]).setDefeatMessages([ `My Pokémon and I have sculpted an illusion of Water and come out victorious.`, `Ahahaha, I have won, and you have lost.`, `Shall I loan you my outfit? It may help you battle!\nAhahaha, I jest!` ]), [TrainerType.ROARK]: new TrainerConfig(++t).initForGymLeader(Species.CRANIDOS, Type.ROCK), [TrainerType.GARDENIA]: new TrainerConfig(++t).initForGymLeader(Species.ROSELIA, Type.GRASS), [TrainerType.MAYLENE]: new TrainerConfig(++t).initForGymLeader(Species.LUCARIO, Type.FIGHTING), [TrainerType.CRASHER_WAKE]: new TrainerConfig(++t).initForGymLeader(Species.BUIZEL, Type.WATER), [TrainerType.FANTINA]: new TrainerConfig(++t).initForGymLeader(Species.MISDREAVUS, Type.GHOST), [TrainerType.BYRON]: new TrainerConfig(++t).initForGymLeader(Species.SHIELDON, Type.STEEL), [TrainerType.CANDICE]: new TrainerConfig(++t).initForGymLeader(Species.SNEASEL, Type.ICE), [TrainerType.VOLKNER]: new TrainerConfig(++t).initForGymLeader(Species.SHINX, Type.ELECTRIC), [TrainerType.CILAN]: new TrainerConfig(++t).initForGymLeader(Species.PANSAGE, Type.GRASS), [TrainerType.CHILI]: new TrainerConfig(++t).initForGymLeader(Species.PANSEAR, Type.FIRE), [TrainerType.CRESS]: new TrainerConfig(++t).initForGymLeader(Species.PANPOUR, Type.WATER), [TrainerType.CHEREN]: new TrainerConfig(++t).initForGymLeader(Species.LILLIPUP, Type.NORMAL), [TrainerType.LENORA]: new TrainerConfig(++t).initForGymLeader(Species.KANGASKHAN, Type.NORMAL), [TrainerType.ROXIE]: new TrainerConfig(++t).initForGymLeader(Species.SCOLIPEDE, Type.POISON), [TrainerType.BURGH]: new TrainerConfig(++t).initForGymLeader(Species.SEWADDLE, Type.BUG), [TrainerType.ELESA]: new TrainerConfig(++t).initForGymLeader(Species.EMOLGA, Type.ELECTRIC), [TrainerType.CLAY]: new TrainerConfig(++t).initForGymLeader(Species.DRILBUR, Type.GROUND), [TrainerType.SKYLA]: new TrainerConfig(++t).initForGymLeader(Species.DUCKLETT, Type.FLYING), [TrainerType.BRYCEN]: new TrainerConfig(++t).initForGymLeader(Species.CRYOGONAL, Type.ICE), [TrainerType.DRAYDEN]: new TrainerConfig(++t).initForGymLeader(Species.DRUDDIGON, Type.DRAGON), [TrainerType.MARLON]: new TrainerConfig(++t).initForGymLeader(Species.WAILMER, Type.WATER), [TrainerType.SHAUNTAL]: new TrainerConfig((t = TrainerType.SHAUNTAL)).initForEliteFour(Species.LITWICK, Type.GHOST), [TrainerType.MARSHAL]: new TrainerConfig(++t).initForEliteFour(Species.TIMBURR, Type.FIGHTING), [TrainerType.GRIMSLEY]: new TrainerConfig(++t).initForEliteFour(Species.PAWNIARD, Type.DARK), [TrainerType.CAITLIN]: new TrainerConfig(++t).initForEliteFour(Species.GOTHITA, Type.PSYCHIC), [TrainerType.BLUE]: new TrainerConfig((t = TrainerType.BLUE)).initForChampion(Species.GYARADOS), [TrainerType.RED]: new TrainerConfig(++t).initForChampion(Species.CHARIZARD), [TrainerType.LANCE]: new TrainerConfig(++t).initForChampion(Species.DRAGONITE), [TrainerType.STEVEN]: new TrainerConfig(++t).initForChampion(Species.BELDUM), [TrainerType.WALLACE]: new TrainerConfig(++t).initForChampion(Species.MILOTIC), [TrainerType.CYNTHIA]: new TrainerConfig(++t).initForChampion(Species.GARCHOMP).setBattleBgm('battle_cynthia'), [TrainerType.ALDER]: new TrainerConfig(++t).initForChampion(Species.VOLCARONA), [TrainerType.IRIS]: new TrainerConfig(++t).initForChampion(Species.AXEW), [TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)).setStaticParty().setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL).setEncounterMessages([ `There you are! I've been looking everywhere for you!\nDid you forget to say goodbye to your best friend? $So you're finally pursuing your dream, huh?\nI knew you'd do it one day… $Anyway, I'll forgive you for forgetting me, but on one condition. You have to battle me! $You'd better give it your best! Wouldn't want your adventure to be over before it started, right?` ]).setVictoryMessages([ `You already have three Pokémon?!\nThat's not fair at all! $Just kidding! I lost fair and square, and now I know you'll do fine out there. $By the way, the professor wanted me to give you some items. Hopefully they're helpful! $Do your best like always! I believe in you!` ]).setModifierRewardFuncs(() => modifierTypes.SUPER_EXP_CHARM, () => modifierTypes.EXP_SHARE).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.BULBASAUR, Species.CHARMANDER, Species.SQUIRTLE, Species.CHIKORITA, Species.CYNDAQUIL, Species.TOTODILE, Species.TREECKO, Species.TORCHIC, Species.MUDKIP, Species.TURTWIG, Species.CHIMCHAR, Species.PIPLUP, Species.SNIVY, Species.TEPIG, Species.OSHAWOTT, Species.CHESPIN, Species.FENNEKIN, Species.FROAKIE, Species.ROWLET, Species.LITTEN, Species.POPPLIO ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEY, Species.TAILLOW, Species.STARLY, Species.PIDOVE, Species.FLETCHLING, Species.PIKIPEK ])), [TrainerType.RIVAL_2]: new TrainerConfig(++t).setStaticParty().setMoneyMultiplier(1.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_2).setEncounterMessages([ `Oh, fancy meeting you here. Looks like you're still undefeated. Right on! $I know what you're thinking, and no, I wasn't following you. I just happened to be in the area. $I'm happy for you but I just want to let you know that it's OK to lose sometimes. $We learn from our mistakes, often more than we would if we kept succeeding. $In any case, I've been training hard for our rematch, so you'd better give it your all!` ]).setVictoryMessages([ `I… wasn't supposed to lose that time…` ]).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.IVYSAUR, Species.CHARMELEON, Species.WARTORTLE, Species.BAYLEEF, Species.QUILAVA, Species.CROCONAW, Species.GROVYLE, Species.COMBUSKEN, Species.MARSHTOMP, Species.GROTLE, Species.MONFERNO, Species.PRINPLUP, Species.SERVINE, Species.PIGNITE, Species.DEWOTT, Species.QUILLADIN, Species.BRAIXEN, Species.FROGADIER, Species.DARTRIX, Species.TORRACAT, Species.BRIONNE ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOTTO, Species.TAILLOW, Species.STARAVIA, Species.TRANQUILL, Species.FLETCHINDER, Species.TRUMBEAK ])) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)), [TrainerType.RIVAL_3]: new TrainerConfig(++t).setStaticParty().setMoneyMultiplier(1.5).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival').setPartyTemplates(trainerPartyTemplates.RIVAL_3).setEncounterMessages([ `Long time no see! Still haven't lost, huh.\nYou're starting to get on my nerves. Just kidding! $But really, I think it's about time you came home.\nYour family and friends miss you, you know. $I know your dream means a lot to you, but the reality is you're going to lose sooner or later. $And when you do, I'll be there for you like always.\nNow, let me show you how strong I've become!` ]).setVictoryMessages([ `After all that… it wasn't enough…?` ]).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON ])) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540), [TrainerType.RIVAL_4]: new TrainerConfig(++t).setBoss().setStaticParty().setMoneyMultiplier(1.75).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival_2').setPartyTemplates(trainerPartyTemplates.RIVAL_4).setEncounterMessages([ `It's me! You didn't forget about me again did you? $You made it really far! I'm proud of you.\nBut it looks like it's the end of your journey. $You've awoken something in me I never knew was there.\nIt seems like all I do now is train. $I hardly even eat or sleep now, I just train my Pokémon all day, getting stronger every time. $And now, I've finally reached peak performance.\nI don't think anyone could beat me now. $And you know what? It's all because of you.\nI don't know whether to thank you or hate you. $Prepare yourself.` ]).setVictoryMessages([ `What…@d{64} what are you?` ]).setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON ])) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540), [TrainerType.RIVAL_5]: new TrainerConfig(++t).setBoss().setStaticParty().setMoneyMultiplier(2.25).setEncounterBgm(TrainerType.RIVAL).setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_5).setEncounterMessages([ `…` ]).setVictoryMessages([ '…' ]) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON ])) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ])), [TrainerType.RIVAL_6]: new TrainerConfig(++t).setBoss().setStaticParty().setMoneyMultiplier(3).setEncounterBgm('final').setBattleBgm('battle_rival_3').setPartyTemplates(trainerPartyTemplates.RIVAL_6) .setPartyMemberFunc(0, getRandomPartyMemberFunc([ Species.VENUSAUR, Species.CHARIZARD, Species.BLASTOISE, Species.MEGANIUM, Species.TYPHLOSION, Species.FERALIGATR, Species.SCEPTILE, Species.BLAZIKEN, Species.SWAMPERT, Species.TORTERRA, Species.INFERNAPE, Species.EMPOLEON, Species.SERPERIOR, Species.EMBOAR, Species.SAMUROTT, Species.CHESNAUGHT, Species.DELPHOX, Species.GRENINJA, Species.DECIDUEYE, Species.INCINEROAR, Species.PRIMARINA ])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.PIDGEOT, Species.SWELLOW, Species.STARAPTOR, Species.UNFEZANT, Species.TALONFLAME, Species.TOUCANNON ])) .setPartyMemberFunc(2, getSpeciesFilterRandomPartyMemberFunc((species: PokemonSpecies) => !pokemonEvolutions.hasOwnProperty(species.speciesId) && !pokemonPrevolutions.hasOwnProperty(species.speciesId) && species.baseTotal >= 450)) .setSpeciesFilter(species => species.baseTotal >= 540) .setPartyMemberFunc(5, getRandomPartyMemberFunc([ Species.RAYQUAZA ], p => p.formIndex = 1)), }