diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index 3475fe4fdea..e936afcdc08 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -15,7 +15,7 @@ export const speciesEggMoves = { [SpeciesId.SPEAROW]: [ MoveId.FLOATY_FALL, MoveId.EXTREME_SPEED, MoveId.KNOCK_OFF, MoveId.TRIPLE_ARROWS ], [SpeciesId.EKANS]: [ MoveId.NOXIOUS_TORQUE, MoveId.DRAGON_DANCE, MoveId.SLACK_OFF, MoveId.SHED_TAIL ], [SpeciesId.SANDSHREW]: [ MoveId.HIGH_HORSEPOWER, MoveId.DIRE_CLAW, MoveId.SHORE_UP, MoveId.MIGHTY_CLEAVE ], - [SpeciesId.NIDORAN_F]: [ MoveId.CALM_MIND, MoveId.MOONLIGHT, MoveId.MALIGNANT_CHAIN, MoveId.SANDSEAR_STORM ], + [SpeciesId.NIDORAN_F]: [ MoveId.BANEFUL_BUNKER, MoveId.MOONLIGHT, MoveId.BARB_BARRAGE, MoveId.THOUSAND_WAVES ], [SpeciesId.NIDORAN_M]: [ MoveId.DRAGON_DANCE, MoveId.MOUNTAIN_GALE, MoveId.NOXIOUS_TORQUE, MoveId.PRECIPICE_BLADES ], [SpeciesId.VULPIX]: [ MoveId.MOONBLAST, MoveId.INFERNAL_PARADE, MoveId.MORNING_SUN, MoveId.TAIL_GLOW ], [SpeciesId.ZUBAT]: [ MoveId.FLOATY_FALL, MoveId.DIRE_CLAW, MoveId.SWORDS_DANCE, MoveId.COLLISION_COURSE ], @@ -293,7 +293,7 @@ export const speciesEggMoves = { [SpeciesId.ARCHEN]: [ MoveId.ROOST, MoveId.EARTHQUAKE, MoveId.FLOATY_FALL, MoveId.MIGHTY_CLEAVE ], [SpeciesId.TRUBBISH]: [ MoveId.COIL, MoveId.RECOVER, MoveId.DIRE_CLAW, MoveId.GIGATON_HAMMER ], [SpeciesId.ZORUA]: [ MoveId.MALIGNANT_CHAIN, MoveId.MOONBLAST, MoveId.SECRET_SWORD, MoveId.FIERY_WRATH ], - [SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.KNOCK_OFF, MoveId.POPULATION_BOMB ], + [SpeciesId.MINCCINO]: [ MoveId.ICICLE_SPEAR, MoveId.TIDY_UP, MoveId.LOW_KICK, MoveId.POPULATION_BOMB ], [SpeciesId.GOTHITA]: [ MoveId.RECOVER, MoveId.MOONBLAST, MoveId.AURA_SPHERE, MoveId.LUMINA_CRASH ], [SpeciesId.SOLOSIS]: [ MoveId.MIST_BALL, MoveId.SPEED_SWAP, MoveId.FLAMETHROWER, MoveId.LIGHT_OF_RUIN ], [SpeciesId.DUCKLETT]: [ MoveId.SPLISHY_SPLASH, MoveId.SANDSEAR_STORM, MoveId.WILDBOLT_STORM, MoveId.QUIVER_DANCE ], @@ -310,7 +310,7 @@ export const speciesEggMoves = { [SpeciesId.TYNAMO]: [ MoveId.SCALD, MoveId.STRENGTH_SAP, MoveId.FIRE_LASH, MoveId.AURA_WHEEL ], [SpeciesId.ELGYEM]: [ MoveId.THUNDERCLAP, MoveId.BADDY_BAD, MoveId.AURA_SPHERE, MoveId.PHOTON_GEYSER ], [SpeciesId.LITWICK]: [ MoveId.GIGA_DRAIN, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.TORCH_SONG ], - [SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.BITTER_BLADE, MoveId.GLAIVE_RUSH ], + [SpeciesId.AXEW]: [ MoveId.STONE_AXE, MoveId.DIRE_CLAW, MoveId.RAGING_FURY, MoveId.BITTER_BLADE ], [SpeciesId.CUBCHOO]: [ MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.ICE_SHARD, MoveId.COLLISION_COURSE ], [SpeciesId.CRYOGONAL]: [ MoveId.FREEZING_GLARE, MoveId.AURORA_VEIL, MoveId.NASTY_PLOT, MoveId.ORIGIN_PULSE ], [SpeciesId.SHELMET]: [ MoveId.POWER_GEM, MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.STEAM_ERUPTION ], @@ -448,7 +448,7 @@ export const speciesEggMoves = { [SpeciesId.ROOKIDEE]: [ MoveId.ROOST, MoveId.BODY_PRESS, MoveId.KINGS_SHIELD, MoveId.BEHEMOTH_BASH ], [SpeciesId.BLIPBUG]: [ MoveId.HEAL_ORDER, MoveId.LUSTER_PURGE, MoveId.SLEEP_POWDER, MoveId.TAIL_GLOW ], [SpeciesId.NICKIT]: [ MoveId.BADDY_BAD, MoveId.MYSTICAL_FIRE, MoveId.SPARKLY_SWIRL, MoveId.MAKE_IT_RAIN ], - [SpeciesId.GOSSIFLEUR]: [ MoveId.PARTING_SHOT, MoveId.STRENGTH_SAP, MoveId.SAPPY_SEED, MoveId.SEED_FLARE ], + [SpeciesId.GOSSIFLEUR]: [ MoveId.BATON_PASS, MoveId.TAILWIND, MoveId.SAPPY_SEED, MoveId.SPORE ], [SpeciesId.WOOLOO]: [ MoveId.NUZZLE, MoveId.MILK_DRINK, MoveId.BODY_PRESS, MoveId.MULTI_ATTACK ], [SpeciesId.CHEWTLE]: [ MoveId.ICE_FANG, MoveId.PSYCHIC_FANGS, MoveId.SHELL_SMASH, MoveId.MIGHTY_CLEAVE ], [SpeciesId.YAMPER]: [ MoveId.ICE_FANG, MoveId.SWORDS_DANCE, MoveId.THUNDER_FANG, MoveId.BOLT_STRIKE ], @@ -514,7 +514,7 @@ export const speciesEggMoves = { [SpeciesId.TAROUNTULA]: [ MoveId.STONE_AXE, MoveId.LEECH_LIFE, MoveId.FAKE_OUT, MoveId.SPORE ], [SpeciesId.NYMBLE]: [ MoveId.KNOCK_OFF, MoveId.FELL_STINGER, MoveId.ATTACK_ORDER, MoveId.WICKED_BLOW ], [SpeciesId.PAWMI]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.JET_PUNCH, MoveId.PLASMA_FISTS ], - [SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.COVET, MoveId.SIZZLY_SLIDE, MoveId.REVIVAL_BLESSING ], + [SpeciesId.TANDEMAUS]: [ MoveId.BATON_PASS, MoveId.FAKE_OUT, MoveId.POWER_UP_PUNCH, MoveId.REVIVAL_BLESSING ], [SpeciesId.FIDOUGH]: [ MoveId.SOFT_BOILED, MoveId.HIGH_HORSEPOWER, MoveId.SIZZLY_SLIDE, MoveId.TIDY_UP ], [SpeciesId.SMOLIV]: [ MoveId.STRENGTH_SAP, MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.BOOMBURST ], [SpeciesId.SQUAWKABILLY]: [ MoveId.PARTING_SHOT, MoveId.EARTHQUAKE, MoveId.FLARE_BLITZ, MoveId.EXTREME_SPEED ], diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index c0f84d90cf0..64fa9b87138 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -36,9 +36,9 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.ARBOK]: { 0: AbilityId.REGENERATOR }, [SpeciesId.SANDSHREW]: { 0: AbilityId.TOUGH_CLAWS }, [SpeciesId.SANDSLASH]: { 0: AbilityId.TOUGH_CLAWS }, - [SpeciesId.NIDORAN_F]: { 0: AbilityId.FLARE_BOOST }, - [SpeciesId.NIDORINA]: { 0: AbilityId.FLARE_BOOST }, - [SpeciesId.NIDOQUEEN]: { 0: AbilityId.FLARE_BOOST }, + [SpeciesId.NIDORAN_F]: { 0: AbilityId.TOXIC_DEBRIS }, + [SpeciesId.NIDORINA]: { 0: AbilityId.TOXIC_DEBRIS }, + [SpeciesId.NIDOQUEEN]: { 0: AbilityId.TOXIC_DEBRIS }, [SpeciesId.NIDORAN_M]: { 0: AbilityId.GUTS }, [SpeciesId.NIDORINO]: { 0: AbilityId.GUTS }, [SpeciesId.NIDOKING]: { 0: AbilityId.GUTS }, @@ -220,8 +220,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.YANMEGA]: { 0: AbilityId.SHEER_FORCE }, [SpeciesId.WOOPER]: { 0: AbilityId.WATER_VEIL }, [SpeciesId.QUAGSIRE]: { 0: AbilityId.COMATOSE }, - [SpeciesId.MURKROW]: { 0: AbilityId.DARK_AURA }, - [SpeciesId.HONCHKROW]: { 0: AbilityId.DARK_AURA }, + [SpeciesId.MURKROW]: { 0: AbilityId.UNNERVE }, + [SpeciesId.HONCHKROW]: { 0: AbilityId.INTIMIDATE }, [SpeciesId.MISDREAVUS]: { 0: AbilityId.BEADS_OF_RUIN }, [SpeciesId.MISMAGIUS]: { 0: AbilityId.BEADS_OF_RUIN }, [SpeciesId.UNOWN]: { 0: AbilityId.ADAPTABILITY, 1: AbilityId.BEAST_BOOST, 2: AbilityId.CONTRARY, 3: AbilityId.DAZZLING, 4: AbilityId.EMERGENCY_EXIT, 5: AbilityId.FRIEND_GUARD, 6: AbilityId.GOOD_AS_GOLD, 7: AbilityId.HONEY_GATHER, 8: AbilityId.IMPOSTER, 9: AbilityId.JUSTIFIED, 10: AbilityId.KLUTZ, 11: AbilityId.LIBERO, 12: AbilityId.MOODY, 13: AbilityId.NEUTRALIZING_GAS, 14: AbilityId.OPPORTUNIST, 15: AbilityId.PICKUP, 16: AbilityId.QUICK_DRAW, 17: AbilityId.RUN_AWAY, 18: AbilityId.SIMPLE, 19: AbilityId.TRACE, 20: AbilityId.UNNERVE, 21: AbilityId.VICTORY_STAR, 22: AbilityId.WANDERING_SPIRIT, 23: AbilityId.FAIRY_AURA, 24: AbilityId.DARK_AURA, 25: AbilityId.AURA_BREAK, 26: AbilityId.PURE_POWER, 27: AbilityId.UNAWARE }, @@ -391,7 +391,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.BANETTE]: { 0: AbilityId.SHADOW_SHIELD, 1: AbilityId.SHADOW_SHIELD }, [SpeciesId.DUSKULL]: { 0: AbilityId.UNNERVE }, [SpeciesId.DUSCLOPS]: { 0: AbilityId.UNNERVE }, - [SpeciesId.DUSKNOIR]: { 0: AbilityId.UNNERVE }, + [SpeciesId.DUSKNOIR]: { 0: AbilityId.LEVITATE }, [SpeciesId.TROPIUS]: { 0: AbilityId.RIPEN }, [SpeciesId.ABSOL]: { 0: AbilityId.SHARPNESS, 1: AbilityId.SHARPNESS }, [SpeciesId.WYNAUT]: { 0: AbilityId.STURDY }, @@ -640,9 +640,9 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.LITWICK]: { 0: AbilityId.SHADOW_TAG }, [SpeciesId.LAMPENT]: { 0: AbilityId.SHADOW_TAG }, [SpeciesId.CHANDELURE]: { 0: AbilityId.SHADOW_TAG }, - [SpeciesId.AXEW]: { 0: AbilityId.DRAGONS_MAW }, - [SpeciesId.FRAXURE]: { 0: AbilityId.DRAGONS_MAW }, - [SpeciesId.HAXORUS]: { 0: AbilityId.DRAGONS_MAW }, + [SpeciesId.AXEW]: { 0: AbilityId.OWN_TEMPO }, + [SpeciesId.FRAXURE]: { 0: AbilityId.OWN_TEMPO }, + [SpeciesId.HAXORUS]: { 0: AbilityId.OWN_TEMPO }, [SpeciesId.CUBCHOO]: { 0: AbilityId.FUR_COAT }, [SpeciesId.BEARTIC]: { 0: AbilityId.FUR_COAT }, [SpeciesId.CRYOGONAL]: { 0: AbilityId.SNOW_WARNING }, @@ -827,7 +827,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.TAPU_LELE]: { 0: AbilityId.BERSERK }, [SpeciesId.TAPU_BULU]: { 0: AbilityId.FLOWER_VEIL }, [SpeciesId.TAPU_FINI]: { 0: AbilityId.FAIRY_AURA }, - [SpeciesId.COSMOG]: { 0: AbilityId.PICKUP }, + [SpeciesId.COSMOG]: { 0: AbilityId.POWER_SPOT }, [SpeciesId.COSMOEM]: { 0: AbilityId.POWER_SPOT }, [SpeciesId.SOLGALEO]: { 0: AbilityId.BEAST_BOOST }, [SpeciesId.LUNALA]: { 0: AbilityId.BEAST_BOOST }, diff --git a/src/data/balance/signature-species.ts b/src/data/balance/signature-species.ts index fba91f6fe3d..557bcdfed16 100644 --- a/src/data/balance/signature-species.ts +++ b/src/data/balance/signature-species.ts @@ -30,7 +30,7 @@ export const signatureSpecies: SignatureSpecies = new Proxy({ FALKNER: [SpeciesId.PIDGEY, SpeciesId.HOOTHOOT, SpeciesId.NATU, SpeciesId.MURKROW], BUGSY: [SpeciesId.SCYTHER, SpeciesId.SHUCKLE, SpeciesId.YANMA, [SpeciesId.PINSIR, SpeciesId.HERACROSS]], WHITNEY: [SpeciesId.MILTANK, SpeciesId.AIPOM, SpeciesId.IGGLYBUFF, [SpeciesId.GIRAFARIG, SpeciesId.STANTLER]], - MORTY: [SpeciesId.GASTLY, SpeciesId.MISDREAVUS, SpeciesId.DUSKULL, SpeciesId.SABLEYE], + MORTY: [SpeciesId.GASTLY, SpeciesId.MISDREAVUS, SpeciesId.DUSKULL, SpeciesId.HISUI_TYPHLOSION], CHUCK: [SpeciesId.POLIWRATH, SpeciesId.MANKEY, SpeciesId.TYROGUE, SpeciesId.MACHOP], JASMINE: [SpeciesId.STEELIX, SpeciesId.MAGNEMITE, SpeciesId.PINECO, SpeciesId.SKARMORY], PRYCE: [SpeciesId.SWINUB, SpeciesId.SEEL, SpeciesId.SHELLDER, SpeciesId.SNEASEL], diff --git a/src/data/balance/starters.ts b/src/data/balance/starters.ts index 8b91c12ae2d..99d5ad62e47 100644 --- a/src/data/balance/starters.ts +++ b/src/data/balance/starters.ts @@ -566,7 +566,7 @@ export const speciesStarterCosts = { [SpeciesId.FLITTLE]: 3, [SpeciesId.TINKATINK]: 4, [SpeciesId.WIGLETT]: 2, - [SpeciesId.BOMBIRDIER]: 3, + [SpeciesId.BOMBIRDIER]: 4, [SpeciesId.FINIZEN]: 3, [SpeciesId.VAROOM]: 4, [SpeciesId.CYCLIZAR]: 4, diff --git a/src/data/trainers/trainer-config.ts b/src/data/trainers/trainer-config.ts index 6c643737778..7ae157ded96 100644 --- a/src/data/trainers/trainer-config.ts +++ b/src/data/trainers/trainer-config.ts @@ -3791,27 +3791,28 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTrainerType(TrainerType.RED) .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.ALAKAZAM])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.MACHAMP])) .setPartyMemberFunc( - 2, - getRandomPartyMemberFunc([SpeciesId.HO_OH], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; - }), - ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.RHYPERIOR, SpeciesId.ELECTIVIRE])) - .setPartyMemberFunc( - 4, + 1, getRandomPartyMemberFunc( [SpeciesId.ARCANINE, SpeciesId.EXEGGUTOR, SpeciesId.GYARADOS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.setBoss(true, 2); + p.teraType = p.species.type1; }, ), ) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.RHYPERIOR, SpeciesId.ELECTIVIRE])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.MACHAMP])) + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([SpeciesId.HO_OH], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + p.abilityIndex = 2; // Regenerator + }), + ) .setPartyMemberFunc( 5, getRandomPartyMemberFunc([SpeciesId.PIDGEOT], TrainerSlot.TRAINER, true, p => { @@ -3819,9 +3820,10 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.MALE; + p.setBoss(true, 2); }), ) - .setInstantTera(3), // Tera Ground or Rock Rhyperior / Electric Electivire / Fire Magmortar + .setInstantTera(2), // Tera Fire Arcanine, Tera Grass Exeggutor, Tera Water Gyarados [TrainerType.RED]: new TrainerConfig(++t) .initForChampion(true) .setBattleBgm("battle_johto_champion") @@ -3832,26 +3834,24 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc( 0, getRandomPartyMemberFunc([SpeciesId.PIKACHU], TrainerSlot.TRAINER, true, p => { - p.formIndex = 8; // G-Max Pikachu - p.generateAndPopulateMoveset(); - p.generateName(); + p.formIndex = 1; // Partner Pikachu p.gender = Gender.MALE; + p.generateAndPopulateMoveset(); + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === MoveId.VOLT_TACKLE)) { + // Check if Volt Tackle is in the moveset, if not, replace the first move with Volt Tackle. + p.moveset[0] = new PokemonMove(MoveId.VOLT_TACKLE); + } }), ) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.ESPEON, SpeciesId.UMBREON, SpeciesId.SYLVEON])) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.MEGANIUM, SpeciesId.TYPHLOSION, SpeciesId.FERALIGATR])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.ESPEON, SpeciesId.UMBREON, SpeciesId.SYLVEON])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.SNORLAX])) .setPartyMemberFunc( - 2, + 4, getRandomPartyMemberFunc([SpeciesId.LUGIA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; - }), - ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.MEGANIUM, SpeciesId.TYPHLOSION, SpeciesId.FERALIGATR])) - .setPartyMemberFunc( - 4, - getRandomPartyMemberFunc([SpeciesId.SNORLAX], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.setBoss(true, 2); + p.abilityIndex = 2; // Multiscale }), ) .setPartyMemberFunc( @@ -3865,10 +3865,11 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.MALE; + p.setBoss(true, 2); }, ), ) - .setInstantTera(3), // Tera Grass Meganium / Fire Typhlosion / Water Feraligatr + .setInstantTera(0), // Tera Electric Pikachu [TrainerType.LANCE_CHAMPION]: new TrainerConfig(++t) .setName("Lance") .initForChampion(true) @@ -3876,37 +3877,38 @@ export const trainerConfigs: TrainerConfigs = { .setMixedBattleBgm("battle_johto_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.GYARADOS, SpeciesId.KINGDRA])) .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.AERODACTYL])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.CHARIZARD])) .setPartyMemberFunc( - 2, + 3, + getRandomPartyMemberFunc( + [SpeciesId.TYRANITAR, SpeciesId.GARCHOMP, SpeciesId.HYDREIGON], + TrainerSlot.TRAINER, + true, + p => { + p.abilityIndex = 2; // Unnerve Tyranitar, Rough Skin Garchomp, Levitate Hydreigon + p.generateAndPopulateMoveset(); + }, + ), + ) + .setPartyMemberFunc( + 4, getRandomPartyMemberFunc([SpeciesId.SALAMENCE], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // Mega Salamence p.generateAndPopulateMoveset(); p.generateName(); }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.CHARIZARD])) - .setPartyMemberFunc( - 4, - getRandomPartyMemberFunc( - [SpeciesId.TYRANITAR, SpeciesId.GARCHOMP, SpeciesId.KOMMO_O], - TrainerSlot.TRAINER, - true, - p => { - p.teraType = PokemonType.DRAGON; - p.generateAndPopulateMoveset(); - p.abilityIndex = p.species.speciesId === SpeciesId.KOMMO_O ? 1 : 2; // Soundproof Kommo-o, Unnerve Tyranitar, Rough Skin Garchomp - }, - ), - ) .setPartyMemberFunc( 5, getRandomPartyMemberFunc([SpeciesId.DRAGONITE], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); + p.abilityIndex = 2; // Multiscale p.gender = Gender.MALE; p.setBoss(true, 2); + p.teraType = PokemonType.DRAGON; }), ) - .setInstantTera(4), // Tera Dragon Tyranitar / Garchomp / Kommo-o + .setInstantTera(5), // Tera Dragon Dragonite [TrainerType.STEVEN]: new TrainerConfig(++t) .initForChampion(true) .setBattleBgm("battle_hoenn_champion_g5") @@ -3914,16 +3916,22 @@ export const trainerConfigs: TrainerConfigs = { .setHasDouble("steven_wallace_double") .setDoubleTrainerType(TrainerType.WALLACE) .setDoubleTitle("champion_double") - .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.SKARMORY])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.CRADILY, SpeciesId.ARMALDO])) .setPartyMemberFunc( - 2, - getRandomPartyMemberFunc([SpeciesId.AGGRON], TrainerSlot.TRAINER, true, p => { + 0, + getRandomPartyMemberFunc([SpeciesId.GIGALITH], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 1; // Sand Stream + p.generateAndPopulateMoveset(); + }), + ) + .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.SKARMORY, SpeciesId.CLAYDOL])) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.AGGRON])) + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([SpeciesId.GOLURK, SpeciesId.RUNERIGUS], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 0; // Iron Fist Golurk, Wandering Spirit Runerigus p.generateAndPopulateMoveset(); - p.setBoss(true, 2); }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.GOLURK, SpeciesId.RUNERIGUS])) .setPartyMemberFunc( 4, getRandomPartyMemberFunc( @@ -3942,6 +3950,7 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 1; // Mega Metagross p.generateAndPopulateMoveset(); p.generateName(); + p.setBoss(true, 2); }), ) .setInstantTera(4), // Tera Rock Regirock / Ice Regice / Steel Registeel @@ -3959,22 +3968,34 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); }), ) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.LUDICOLO])) .setPartyMemberFunc( - 2, - getRandomPartyMemberFunc([SpeciesId.LATIAS, SpeciesId.LATIOS], TrainerSlot.TRAINER, true, p => { - p.formIndex = 1; // Mega Latios or Mega Latias + 1, + getRandomPartyMemberFunc([SpeciesId.LUDICOLO], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 0; // Swift Swim p.generateAndPopulateMoveset(); - p.generateName(); - p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.SWAMPERT, SpeciesId.GASTRODON, SpeciesId.SEISMITOAD])) + .setPartyMemberFunc( + 2, + getRandomPartyMemberFunc([SpeciesId.TENTACRUEL, SpeciesId.WALREIN], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = p.species.speciesId === SpeciesId.TENTACRUEL ? 2 : 0; // Rain Dish Tentacruel, Thick Fat Walrein + p.generateAndPopulateMoveset(); + }), + ) + .setPartyMemberFunc( + 3, + getRandomPartyMemberFunc([SpeciesId.LATIAS, SpeciesId.LATIOS], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.generateName(); + p.pokeball = PokeballType.ULTRA_BALL; + }), + ) .setPartyMemberFunc( 4, - getRandomPartyMemberFunc([SpeciesId.REGIELEKI, SpeciesId.REGIDRAGO], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.SWAMPERT], TrainerSlot.TRAINER, true, p => { + p.formIndex = 1; // Mega Swampert p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; + p.generateName(); }), ) .setPartyMemberFunc( @@ -3985,22 +4006,14 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); }), ) - .setInstantTera(4), // Tera Electric Regieleki / Dragon Regidrago + .setInstantTera(5), // Tera Water Milotic [TrainerType.CYNTHIA]: new TrainerConfig(++t) .initForChampion(false) .setBattleBgm("battle_sinnoh_champion") .setMixedBattleBgm("battle_sinnoh_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.SPIRITOMB])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.LUCARIO])) .setPartyMemberFunc( - 2, - getRandomPartyMemberFunc([SpeciesId.GIRATINA], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; - }), - ) - .setPartyMemberFunc( - 3, + 1, getRandomPartyMemberFunc( [SpeciesId.MILOTIC, SpeciesId.ROSERADE, SpeciesId.HISUI_ARCANINE], TrainerSlot.TRAINER, @@ -4011,11 +4024,13 @@ export const trainerConfigs: TrainerConfigs = { }, ), ) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.TOGEKISS])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.LUCARIO])) .setPartyMemberFunc( 4, - getRandomPartyMemberFunc([SpeciesId.TOGEKISS], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.GIRATINA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.setBoss(true, 2); + p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc( @@ -4025,9 +4040,10 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.FEMALE; + p.setBoss(true, 2); }), ) - .setInstantTera(3), // Tera Water Milotic / Grass Roserade / Fire Hisuian Arcanine + .setInstantTera(1), // Tera Water Milotic / Grass Roserade / Fire Hisuian Arcanine [TrainerType.ALDER]: new TrainerConfig(++t) .initForChampion(true) .setHasDouble("alder_iris_double") @@ -4050,29 +4066,26 @@ export const trainerConfigs: TrainerConfigs = { ) .setPartyMemberFunc( 2, - getRandomPartyMemberFunc([SpeciesId.ZEKROM], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; - }), + getRandomPartyMemberFunc([SpeciesId.CHANDELURE, SpeciesId.KROOKODILE, SpeciesId.REUNICLUS, SpeciesId.CONKELDURR]), ) .setPartyMemberFunc( 3, getRandomPartyMemberFunc([SpeciesId.KELDEO], TrainerSlot.TRAINER, true, p => { + p.pokeball = PokeballType.ROGUE_BALL; p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === MoveId.SECRET_SWORD)) { + // Check if Secret Sword is in the moveset, if not, replace the third move with Secret Sword. + p.moveset[2] = new PokemonMove(MoveId.SECRET_SWORD); + } + p.formIndex = 1; // Resolute Form }), ) .setPartyMemberFunc( 4, - getRandomPartyMemberFunc( - [SpeciesId.CHANDELURE, SpeciesId.KROOKODILE, SpeciesId.REUNICLUS, SpeciesId.CONKELDURR], - TrainerSlot.TRAINER, - true, - p => { - p.generateAndPopulateMoveset(); - p.teraType = p.species.speciesId === SpeciesId.KROOKODILE ? PokemonType.DARK : p.species.type1; - }, - ), + getRandomPartyMemberFunc([SpeciesId.ZEKROM], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + }), ) .setPartyMemberFunc( 5, @@ -4080,9 +4093,10 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); + p.teraType = PokemonType.FIRE; }), ) - .setInstantTera(4), // Tera Ghost Chandelure / Dark Krookodile / Psychic Reuniclus / Fighting Conkeldurr + .setInstantTera(5), // Tera Fire Volcarona [TrainerType.IRIS]: new TrainerConfig(++t) .initForChampion(false) .setBattleBgm("battle_champion_iris") @@ -4091,34 +4105,29 @@ export const trainerConfigs: TrainerConfigs = { .setDoubleTrainerType(TrainerType.ALDER) .setDoubleTitle("champion_double") .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.DRUDDIGON])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.ARCHEOPS])) .setPartyMemberFunc( - 2, - getRandomPartyMemberFunc([SpeciesId.RESHIRAM], TrainerSlot.TRAINER, true, p => { + 1, + getRandomPartyMemberFunc([SpeciesId.ARCHEOPS], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 2; // Emergency Exit p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc( - 3, - getRandomPartyMemberFunc( - [SpeciesId.SALAMENCE, SpeciesId.HYDREIGON, SpeciesId.ARCHALUDON], - TrainerSlot.TRAINER, - true, - p => { - p.generateAndPopulateMoveset(); - p.teraType = PokemonType.DRAGON; - }, - ), - ) - .setPartyMemberFunc( - 4, + 2, getRandomPartyMemberFunc([SpeciesId.LAPRAS], TrainerSlot.TRAINER, true, p => { p.formIndex = 1; // G-Max Lapras p.generateAndPopulateMoveset(); p.generateName(); }), ) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.AGGRON, SpeciesId.HYDREIGON, SpeciesId.ARCHALUDON])) + .setPartyMemberFunc( + 4, + getRandomPartyMemberFunc([SpeciesId.RESHIRAM], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.pokeball = PokeballType.MASTER_BALL; + }), + ) .setPartyMemberFunc( 5, getRandomPartyMemberFunc([SpeciesId.HAXORUS], TrainerSlot.TRAINER, true, p => { @@ -4128,37 +4137,32 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); }), ) - .setInstantTera(3), // Tera Dragon Salamence / Hydreigon / Archaludon + .setInstantTera(5), // Tera Dragon Haxorus [TrainerType.DIANTHA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_kalos_champion") + .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.HAWLUCHA])) .setPartyMemberFunc( - 0, - getRandomPartyMemberFunc([SpeciesId.HAWLUCHA], TrainerSlot.TRAINER, true, p => { + 1, + getRandomPartyMemberFunc([SpeciesId.TREVENANT, SpeciesId.GOURGEIST], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 2; // Harvest Trevenant, Insomnia Gourgeist p.generateAndPopulateMoveset(); }), ) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.TREVENANT, SpeciesId.GOURGEIST])) .setPartyMemberFunc( 2, - getRandomPartyMemberFunc([SpeciesId.XERNEAS], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; - }), - ) - .setPartyMemberFunc( - 3, getRandomPartyMemberFunc([SpeciesId.TYRANTRUM, SpeciesId.AURORUS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.abilityIndex = 2; // Rock Head Tyrantrum, Snow Warning Aurorus p.teraType = p.species.type2!; }), ) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.GOODRA])) .setPartyMemberFunc( 4, - getRandomPartyMemberFunc([SpeciesId.GOODRA], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.XERNEAS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.setBoss(true, 2); + p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc( @@ -4168,9 +4172,10 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.FEMALE; + p.setBoss(true, 2); }), ) - .setInstantTera(3), // Tera Dragon Tyrantrum / Ice Aurorus + .setInstantTera(2), // Tera Dragon Tyrantrum / Ice Aurorus [TrainerType.KUKUI]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_champion_kukui") @@ -4181,7 +4186,13 @@ export const trainerConfigs: TrainerConfigs = { p.formIndex = 2; // Dusk Lycanroc }), ) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.MAGNEZONE, SpeciesId.ALOLA_NINETALES])) + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc([SpeciesId.MAGNEZONE, SpeciesId.ALOLA_NINETALES], TrainerSlot.TRAINER, true, p => { + p.generateAndPopulateMoveset(); + p.abilityIndex = p.species.speciesId === SpeciesId.MAGNEZONE ? 1 : 2; // Sturdy Magnezone, Snow Warning Ninetales + }), + ) .setPartyMemberFunc( 2, getRandomPartyMemberFunc( @@ -4191,16 +4202,16 @@ export const trainerConfigs: TrainerConfigs = { p => { p.formIndex = 1; // Therian Formes p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; + p.pokeball = PokeballType.ROGUE_BALL; }, ), ) .setPartyMemberFunc( 3, - getRandomPartyMemberFunc([SpeciesId.TAPU_KOKO, SpeciesId.TAPU_FINI], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.TAPU_LELE, SpeciesId.TAPU_FINI], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.setBoss(true, 2); p.pokeball = PokeballType.ULTRA_BALL; + p.abilityIndex = 0; // Psychic / Misty Surge }), ) .setPartyMemberFunc( @@ -4216,6 +4227,7 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.teraType = p.species.type2!; + p.setBoss(true, 2); }), ) .setInstantTera(5), // Tera Dark Incineroar / Fighting Hisuian Decidueye @@ -4223,28 +4235,33 @@ export const trainerConfigs: TrainerConfigs = { .initForChampion(true) .setMixedBattleBgm("battle_alola_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.ALOLA_RAICHU])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.NOIVERN])) + .setPartyMemberFunc( + 1, + getRandomPartyMemberFunc([SpeciesId.NOIVERN], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 1; // Infiltrator + p.generateAndPopulateMoveset(); + }), + ) .setPartyMemberFunc( 2, - getRandomPartyMemberFunc([SpeciesId.SOLGALEO], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.BLACEPHALON, SpeciesId.STAKATAKA], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; + p.pokeball = PokeballType.ROGUE_BALL; }), ) .setPartyMemberFunc( 3, - getRandomPartyMemberFunc([SpeciesId.TAPU_LELE, SpeciesId.TAPU_BULU], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.TAPU_KOKO, SpeciesId.TAPU_BULU], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; - p.teraType = p.species.type1; + p.abilityIndex = 0; // Electric / Grassy Surge }), ) .setPartyMemberFunc( 4, - getRandomPartyMemberFunc([SpeciesId.ZYGARDE], TrainerSlot.TRAINER, true, p => { - p.formIndex = 1; // Zygarde 10% forme, Aura Break + getRandomPartyMemberFunc([SpeciesId.SOLGALEO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ROGUE_BALL; + p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc( @@ -4253,34 +4270,35 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.setBoss(true, 2); p.gender = p.species.speciesId === SpeciesId.PRIMARINA ? Gender.FEMALE : Gender.MALE; + p.teraType = p.species.speciesId === SpeciesId.PRIMARINA ? PokemonType.WATER : PokemonType.GHOST; }), ) - .setInstantTera(3), // Tera Psychic Tapu Lele / Grass Tapu Bulu + .setInstantTera(5), // Tera Ghost Decidueye, Water Primarina [TrainerType.LEON]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_galar_champion") .setPartyMemberFunc(0, getRandomPartyMemberFunc([SpeciesId.AEGISLASH])) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.RHYPERIOR, SpeciesId.SEISMITOAD, SpeciesId.MR_RIME])) .setPartyMemberFunc( - 2, + 1, + getRandomPartyMemberFunc( + [SpeciesId.RHYPERIOR, SpeciesId.SEISMITOAD, SpeciesId.MR_RIME], + TrainerSlot.TRAINER, + true, + p => { + p.abilityIndex = 1; // Solid Rock Rhyperior, Poison Touch Seismitoad, Screen Cleaner Mr. Rime + p.generateAndPopulateMoveset(); + }, + ), + ) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.DRAGAPULT])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.RILLABOOM, SpeciesId.CINDERACE, SpeciesId.INTELEON])) + .setPartyMemberFunc( + 4, getRandomPartyMemberFunc([SpeciesId.ZACIAN], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.DRAGAPULT])) - .setPartyMemberFunc( - 4, - getRandomPartyMemberFunc( - [SpeciesId.RILLABOOM, SpeciesId.CINDERACE, SpeciesId.INTELEON], - TrainerSlot.TRAINER, - true, - p => { - p.generateAndPopulateMoveset(); - p.setBoss(true, 2); - }, - ), - ) .setPartyMemberFunc( 5, getRandomPartyMemberFunc([SpeciesId.CHARIZARD], TrainerSlot.TRAINER, true, p => { @@ -4288,22 +4306,23 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.generateName(); p.gender = Gender.MALE; + p.setBoss(true, 2); }), ) - .setInstantTera(3), // Tera Dragapult to Ghost or Dragon + .setInstantTera(3), // Tera Grass Rillaboom, Fire Cinderace, Water Inteleon [TrainerType.MUSTARD]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_mustard") .setPartyMemberFunc( 0, - getRandomPartyMemberFunc([SpeciesId.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.MIENSHAO], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), ) .setPartyMemberFunc( 1, - getRandomPartyMemberFunc([SpeciesId.KOMMO_O], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.CORVIKNIGHT], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.ULTRA_BALL; }), @@ -4312,36 +4331,46 @@ export const trainerConfigs: TrainerConfigs = { 2, getRandomPartyMemberFunc([SpeciesId.GALAR_SLOWBRO, SpeciesId.GALAR_SLOWKING], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); + p.abilityIndex = p.species.speciesId === SpeciesId.GALAR_SLOWBRO ? 0 : 2; // Quick Draw Galar Slowbro, Regenerator Galar Slowking p.pokeball = PokeballType.ULTRA_BALL; - p.teraType = p.species.type1; }), ) .setPartyMemberFunc( 3, - getRandomPartyMemberFunc([SpeciesId.GALAR_DARMANITAN], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); + getRandomPartyMemberFunc([SpeciesId.VENUSAUR, SpeciesId.BLASTOISE], TrainerSlot.TRAINER, true, p => { p.pokeball = PokeballType.ULTRA_BALL; }), ) .setPartyMemberFunc( 4, - getRandomPartyMemberFunc([SpeciesId.BLASTOISE, SpeciesId.VENUSAUR], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.KOMMO_O], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.setBoss(true, 2); p.pokeball = PokeballType.ULTRA_BALL; + p.generateAndPopulateMoveset(); }), ) .setPartyMemberFunc( 5, getRandomPartyMemberFunc([SpeciesId.URSHIFU], TrainerSlot.TRAINER, true, p => { - p.formIndex = randSeedIntRange(2, 3); // Random G-Max Urshifu - p.generateAndPopulateMoveset(); + p.formIndex = randSeedIntRange(2, 3); // Random G-Max Urshifu form p.generateName(); p.gender = Gender.MALE; p.pokeball = PokeballType.ULTRA_BALL; + p.setBoss(true, 2); + if (p.formIndex === 2) { + p.moveset[0] = new PokemonMove(MoveId.WICKED_BLOW); + p.moveset[1] = new PokemonMove(MoveId.BRICK_BREAK); + p.moveset[2] = new PokemonMove(randSeedItem([MoveId.FIRE_PUNCH, MoveId.THUNDER_PUNCH, MoveId.ICE_PUNCH])); + p.moveset[3] = new PokemonMove(MoveId.FOCUS_ENERGY); + } else if (p.formIndex === 3) { + p.moveset[0] = new PokemonMove(MoveId.SURGING_STRIKES); + p.moveset[1] = new PokemonMove(MoveId.BRICK_BREAK); + p.moveset[2] = new PokemonMove(randSeedItem([MoveId.FIRE_PUNCH, MoveId.THUNDER_PUNCH, MoveId.ICE_PUNCH])); + p.moveset[3] = new PokemonMove(MoveId.FOCUS_ENERGY); + } }), ) - .setInstantTera(2), // Tera Poison Galar-Slowbro / Galar-Slowking + .setInstantTera(4), // Tera Fighting Kommo-o [TrainerType.GEETA]: new TrainerConfig(++t) .initForChampion(false) .setMixedBattleBgm("battle_champion_geeta") @@ -4353,16 +4382,22 @@ export const trainerConfigs: TrainerConfigs = { p.setBoss(true, 2); }), ) - .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.ESPATHRA, SpeciesId.VELUZA])) .setPartyMemberFunc( - 2, + 1, + getRandomPartyMemberFunc([SpeciesId.ESPATHRA], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 0; // Opportunist + p.generateAndPopulateMoveset(); + }), + ) + .setPartyMemberFunc(2, getRandomPartyMemberFunc([SpeciesId.BAXCALIBUR])) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.CHESNAUGHT, SpeciesId.DELPHOX, SpeciesId.GRENINJA])) + .setPartyMemberFunc( + 4, getRandomPartyMemberFunc([SpeciesId.MIRAIDON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.BAXCALIBUR])) - .setPartyMemberFunc(4, getRandomPartyMemberFunc([SpeciesId.CHESNAUGHT, SpeciesId.DELPHOX, SpeciesId.GRENINJA])) .setPartyMemberFunc( 5, getRandomPartyMemberFunc([SpeciesId.KINGAMBIT], TrainerSlot.TRAINER, true, p => { @@ -4389,19 +4424,19 @@ export const trainerConfigs: TrainerConfigs = { .setPartyMemberFunc(1, getRandomPartyMemberFunc([SpeciesId.PAWMOT])) .setPartyMemberFunc( 2, + getRandomPartyMemberFunc([SpeciesId.DUDUNSPARCE], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 0; // Serene Grace + p.generateAndPopulateMoveset(); + }), + ) + .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.ARMAROUGE, SpeciesId.CERULEDGE])) + .setPartyMemberFunc( + 4, getRandomPartyMemberFunc([SpeciesId.KORAIDON], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); p.pokeball = PokeballType.MASTER_BALL; }), ) - .setPartyMemberFunc(3, getRandomPartyMemberFunc([SpeciesId.GHOLDENGO])) - .setPartyMemberFunc( - 4, - getRandomPartyMemberFunc([SpeciesId.ARMAROUGE, SpeciesId.CERULEDGE], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); - p.teraType = p.species.type2!; - }), - ) .setPartyMemberFunc( 5, getRandomPartyMemberFunc( @@ -4412,10 +4447,11 @@ export const trainerConfigs: TrainerConfigs = { p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); + p.teraType = p.species.type2!; }, ), ) - .setInstantTera(4), // Tera Psychic Armarouge / Ghost Ceruledge + .setInstantTera(5), // Tera Dark Meowscarada, Ghost Skeledirge, Fighting Quaquaval [TrainerType.KIERAN]: new TrainerConfig(++t) .initForChampion(true) .setMixedBattleBgm("battle_champion_kieran") @@ -4429,9 +4465,9 @@ export const trainerConfigs: TrainerConfigs = { ) .setPartyMemberFunc( 2, - getRandomPartyMemberFunc([SpeciesId.TERAPAGOS], TrainerSlot.TRAINER, true, p => { + getRandomPartyMemberFunc([SpeciesId.DRAGONITE], TrainerSlot.TRAINER, true, p => { + p.abilityIndex = 2; // Multiscale p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc( @@ -4443,25 +4479,29 @@ export const trainerConfigs: TrainerConfigs = { ) .setPartyMemberFunc( 4, - getRandomPartyMemberFunc([SpeciesId.OGERPON], TrainerSlot.TRAINER, true, p => { - p.formIndex = randSeedInt(4); // Random Ogerpon Tera Mask + getRandomPartyMemberFunc([SpeciesId.TERAPAGOS], TrainerSlot.TRAINER, true, p => { p.generateAndPopulateMoveset(); - p.pokeball = PokeballType.ULTRA_BALL; - if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === MoveId.IVY_CUDGEL)) { - // Check if Ivy Cudgel is in the moveset, if not, replace the first move with Ivy Cudgel. - p.moveset[0] = new PokemonMove(MoveId.IVY_CUDGEL); + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === MoveId.TERA_STARSTORM)) { + // Check if Tera Starstorm is in the moveset, if not, replace the first move with Tera Starstorm. + p.moveset[0] = new PokemonMove(MoveId.TERA_STARSTORM); } + p.pokeball = PokeballType.MASTER_BALL; }), ) .setPartyMemberFunc( 5, getRandomPartyMemberFunc([SpeciesId.HYDRAPPLE], TrainerSlot.TRAINER, true, p => { - p.generateAndPopulateMoveset(); p.gender = Gender.MALE; p.setBoss(true, 2); + p.teraType = PokemonType.FIGHTING; + p.generateAndPopulateMoveset(); + if (!p.moveset.some(move => !isNullOrUndefined(move) && move.moveId === MoveId.TERA_BLAST)) { + // Check if Tera Blast is in the moveset, if not, replace the third move with Tera Blast. + p.moveset[2] = new PokemonMove(MoveId.TERA_BLAST); + } }), ) - .setInstantTera(4), // Tera Ogerpon + .setInstantTera(5), // Tera Fighting Hydrapple [TrainerType.RIVAL]: new TrainerConfig((t = TrainerType.RIVAL)) .setName("Finn") diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 9e5c32b3326..0d28467488f 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -830,7 +830,8 @@ export class MoveEffectPhase extends PokemonPhase { const substituteTag = target.getTag(SubstituteTag); const isBlockedBySubstitute = substituteTag && this.move.hitsSubstitute(user, target); if (isBlockedBySubstitute) { - substituteTag.hp -= dmg; + user.turnData.lastMoveDamageDealt[target.getBattlerIndex()] += Math.min(dmg, substitute.hp); + substitute.hp -= dmg; } else if (!target.isPlayer() && dmg >= target.hp) { globalScene.applyModifiers(EnemyEndureChanceModifier, false, target); } diff --git a/test/moves/recoil-moves.test.ts b/test/moves/recoil-moves.test.ts new file mode 100644 index 00000000000..6fc69c932ac --- /dev/null +++ b/test/moves/recoil-moves.test.ts @@ -0,0 +1,84 @@ +import { AbilityId } from "#enums/ability-id"; +import { BattlerTagType } from "#enums/battler-tag-type"; +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; +import { GameManager } from "#test/test-utils/game-manager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Moves - Recoil Moves", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + game.override + .battleStyle("single") + .enemySpecies(SpeciesId.PIDOVE) + .startingLevel(1) + .enemyLevel(100) + .enemyMoveset(MoveId.SUBSTITUTE) + .criticalHits(false) + .ability(AbilityId.NO_GUARD) + .enemyAbility(AbilityId.BALL_FETCH); + }); + + it.each([ + { moveName: "Double Edge", moveId: MoveId.DOUBLE_EDGE }, + { moveName: "Brave Bird", moveId: MoveId.BRAVE_BIRD }, + { moveName: "Flare Blitz", moveId: MoveId.FLARE_BLITZ }, + { moveName: "Head Charge", moveId: MoveId.HEAD_CHARGE }, + { moveName: "Head Smash", moveId: MoveId.HEAD_SMASH }, + { moveName: "Light of Ruin", moveId: MoveId.LIGHT_OF_RUIN }, + { moveName: "Struggle", moveId: MoveId.STRUGGLE }, + { moveName: "Submission", moveId: MoveId.SUBMISSION }, + { moveName: "Take Down", moveId: MoveId.TAKE_DOWN }, + { moveName: "Volt Tackle", moveId: MoveId.VOLT_TACKLE }, + { moveName: "Wave Crash", moveId: MoveId.WAVE_CRASH }, + { moveName: "Wild Charge", moveId: MoveId.WILD_CHARGE }, + { moveName: "Wood Hammer", moveId: MoveId.WOOD_HAMMER }, + ])("$moveName causes recoil damage when hitting a substitute", async ({ moveId }) => { + await game.classicMode.startBattle([SpeciesId.TOGEPI]); + + game.move.use(moveId); + await game.phaseInterceptor.to("MoveEndPhase"); // Pidove substitute + + const pidove = game.field.getEnemyPokemon(); + const subTag = pidove.getTag(BattlerTagType.SUBSTITUTE)!; + expect(subTag).toBeDefined(); + const subInitialHp = subTag.hp; + + await game.phaseInterceptor.to("MoveEndPhase"); // player attack + + expect(subTag.hp).toBeLessThan(subInitialHp); + + const playerPokemon = game.field.getPlayerPokemon(); + expect(playerPokemon.hp).toBeLessThan(playerPokemon.getMaxHp()); + }); + + it("causes recoil damage when hitting a substitute in a double battle", async () => { + game.override.battleStyle("double"); + + await game.classicMode.startBattle([SpeciesId.TOGEPI, SpeciesId.TOGEPI]); + + const [playerPokemon1, playerPokemon2] = game.scene.getPlayerField(); + + game.move.use(MoveId.DOUBLE_EDGE, 0); + game.move.use(MoveId.DOUBLE_EDGE, 1); + + await game.toNextTurn(); + + expect(playerPokemon1.hp).toBeLessThan(playerPokemon1.getMaxHp()); + expect(playerPokemon2.hp).toBeLessThan(playerPokemon2.getMaxHp()); + }); +});