From eea07e15f75953a846d733e257dbe0a75de70d6c Mon Sep 17 00:00:00 2001 From: Blitzy <118096277+Blitz425@users.noreply.github.com> Date: Mon, 27 Oct 2025 20:21:01 -0500 Subject: [PATCH 01/58] [Balance] 1.11 Eggs, Passives, and Starter Cost updates (#6699) Eggs, Passives, and Starter Cost updates --- src/data/balance/egg-moves.ts | 68 +++++++++++++++++------------------ src/data/balance/passives.ts | 38 ++++++++++---------- src/data/balance/starters.ts | 2 +- 3 files changed, 54 insertions(+), 54 deletions(-) diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index 1184de70b07..4374305c183 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -13,9 +13,9 @@ export const speciesEggMoves = { [SpeciesId.SQUIRTLE]: [ MoveId.FREEZE_DRY, MoveId.ARMOR_CANNON, MoveId.SHORE_UP, MoveId.ORIGIN_PULSE ], [SpeciesId.CATERPIE]: [ MoveId.SANDSEAR_STORM, MoveId.SILK_TRAP, MoveId.TWIN_BEAM, MoveId.BLEAKWIND_STORM ], [SpeciesId.WEEDLE]: [ MoveId.THOUSAND_ARROWS, MoveId.NOXIOUS_TORQUE, MoveId.ATTACK_ORDER, MoveId.VICTORY_DANCE ], - [SpeciesId.PIDGEY]: [ MoveId.BLEAKWIND_STORM, MoveId.SANDSEAR_STORM, MoveId.CALM_MIND, MoveId.BOOMBURST ], + [SpeciesId.PIDGEY]: [ MoveId.BLEAKWIND_STORM, MoveId.FOCUS_BLAST, MoveId.CALM_MIND, MoveId.BOOMBURST ], [SpeciesId.RATTATA]: [ MoveId.HYPER_FANG, MoveId.PSYCHIC_FANGS, MoveId.FIRE_FANG, MoveId.EXTREME_SPEED ], - [SpeciesId.SPEAROW]: [ MoveId.FLOATY_FALL, MoveId.EXTREME_SPEED, MoveId.KNOCK_OFF, MoveId.TRIPLE_ARROWS ], + [SpeciesId.SPEAROW]: [ MoveId.FLOATY_FALL, MoveId.HYPER_DRILL, MoveId.SWORDS_DANCE, 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.BANEFUL_BUNKER, MoveId.MOONLIGHT, MoveId.BARB_BARRAGE, MoveId.THOUSAND_WAVES ], @@ -38,17 +38,17 @@ export const speciesEggMoves = { [SpeciesId.GEODUDE]: [ MoveId.FLARE_BLITZ, MoveId.HEAD_SMASH, MoveId.SHORE_UP, MoveId.SHELL_SMASH ], [SpeciesId.PONYTA]: [ MoveId.HEADLONG_RUSH, MoveId.HIGH_JUMP_KICK, MoveId.SWORDS_DANCE, MoveId.VOLT_TACKLE ], [SpeciesId.SLOWPOKE]: [ MoveId.SPLISHY_SPLASH, MoveId.FROST_BREATH, MoveId.SHED_TAIL, MoveId.MYSTICAL_POWER ], - [SpeciesId.MAGNEMITE]: [ MoveId.PARABOLIC_CHARGE, MoveId.FLAMETHROWER, MoveId.ICE_BEAM, MoveId.THUNDERCLAP ], + [SpeciesId.MAGNEMITE]: [ MoveId.PARABOLIC_CHARGE, MoveId.FLAMETHROWER, MoveId.THUNDERCLAP, MoveId.ICE_BEAM ], [SpeciesId.FARFETCHD]: [ MoveId.IVY_CUDGEL, MoveId.TRIPLE_ARROWS, MoveId.DRILL_RUN, MoveId.VICTORY_DANCE ], [SpeciesId.DODUO]: [ MoveId.TRIPLE_AXEL, MoveId.HYPER_DRILL, MoveId.FLOATY_FALL, MoveId.TRIPLE_ARROWS ], [SpeciesId.SEEL]: [ MoveId.FREEZE_DRY, MoveId.BOUNCY_BUBBLE, MoveId.SLACK_OFF, MoveId.STEAM_ERUPTION ], [SpeciesId.GRIMER]: [ MoveId.SUCKER_PUNCH, MoveId.CURSE, MoveId.NOXIOUS_TORQUE, MoveId.STRENGTH_SAP ], - [SpeciesId.SHELLDER]: [ MoveId.ROCK_BLAST, MoveId.WATER_SHURIKEN, MoveId.BANEFUL_BUNKER, MoveId.BONE_RUSH ], + [SpeciesId.SHELLDER]: [ MoveId.ROCK_BLAST, MoveId.WATER_SHURIKEN, MoveId.FREEZE_DRY, MoveId.BONE_RUSH ], [SpeciesId.GASTLY]: [ MoveId.MALIGNANT_CHAIN, MoveId.AURA_SPHERE, MoveId.PARTING_SHOT, MoveId.DARK_VOID ], [SpeciesId.ONIX]: [ MoveId.SHORE_UP, MoveId.THOUSAND_WAVES, MoveId.COIL, MoveId.DIAMOND_STORM ], [SpeciesId.DROWZEE]: [ MoveId.BADDY_BAD, MoveId.STRENGTH_SAP, MoveId.LUMINA_CRASH, MoveId.DARK_VOID ], [SpeciesId.KRABBY]: [ MoveId.DIRE_CLAW, MoveId.DRAGON_HAMMER, MoveId.IVY_CUDGEL, MoveId.JET_PUNCH ], - [SpeciesId.VOLTORB]: [ MoveId.NASTY_PLOT, MoveId.FUSION_FLARE, MoveId.FROST_BREATH, MoveId.ELECTRO_DRIFT ], + [SpeciesId.VOLTORB]: [ MoveId.NASTY_PLOT, MoveId.FUSION_FLARE, MoveId.ENERGY_BALL, MoveId.ELECTRO_DRIFT ], [SpeciesId.EXEGGCUTE]: [ MoveId.FICKLE_BEAM, MoveId.APPLE_ACID, MoveId.HEAT_WAVE, MoveId.LUMINA_CRASH ], [SpeciesId.CUBONE]: [ MoveId.HEAD_SMASH, MoveId.WOOD_HAMMER, MoveId.SHADOW_SNEAK, MoveId.BITTER_BLADE ], [SpeciesId.LICKITUNG]: [ MoveId.CRUSH_GRIP, MoveId.FIRE_LASH, MoveId.SLACK_OFF, MoveId.MAGICAL_TORQUE ], @@ -69,7 +69,7 @@ export const speciesEggMoves = { [SpeciesId.PORYGON]: [ MoveId.THUNDERCLAP, MoveId.DAZZLING_GLEAM, MoveId.FLAMETHROWER, MoveId.TECHNO_BLAST ], [SpeciesId.OMANYTE]: [ MoveId.FREEZE_DRY, MoveId.GIGA_DRAIN, MoveId.POWER_GEM, MoveId.STEAM_ERUPTION ], [SpeciesId.KABUTO]: [ MoveId.CEASELESS_EDGE, MoveId.HIGH_HORSEPOWER, MoveId.MIGHTY_CLEAVE, MoveId.CRABHAMMER ], - [SpeciesId.AERODACTYL]: [ MoveId.FLOATY_FALL, MoveId.HIGH_HORSEPOWER, MoveId.STONE_AXE, MoveId.SWORDS_DANCE ], + [SpeciesId.AERODACTYL]: [ MoveId.ACROBATICS, MoveId.HIGH_HORSEPOWER, MoveId.STONE_AXE, MoveId.SWORDS_DANCE ], [SpeciesId.ARTICUNO]: [ MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.AURORA_VEIL, MoveId.AEROBLAST ], [SpeciesId.ZAPDOS]: [ MoveId.BLEAKWIND_STORM, MoveId.CALM_MIND, MoveId.SANDSEAR_STORM, MoveId.ELECTRO_SHOT ], [SpeciesId.MOLTRES]: [ MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.AEROBLAST, MoveId.TORCH_SONG ], @@ -86,23 +86,23 @@ export const speciesEggMoves = { [SpeciesId.SPINARAK]: [ MoveId.PARTING_SHOT, MoveId.ATTACK_ORDER, MoveId.GASTRO_ACID, MoveId.STRENGTH_SAP ], [SpeciesId.CHINCHOU]: [ MoveId.THUNDERCLAP, MoveId.BOUNCY_BUBBLE, MoveId.THUNDER_CAGE, MoveId.TAIL_GLOW ], [SpeciesId.PICHU]: [ MoveId.MOONBLAST, MoveId.TRIPLE_AXEL, MoveId.FIERY_DANCE, MoveId.AURA_WHEEL ], - [SpeciesId.CLEFFA]: [ MoveId.CALM_MIND, MoveId.EARTH_POWER, MoveId.WISH, MoveId.LIGHT_OF_RUIN ], + [SpeciesId.CLEFFA]: [ MoveId.CALM_MIND, MoveId.EARTH_POWER, MoveId.LUNAR_BLESSING, MoveId.LIGHT_OF_RUIN ], [SpeciesId.IGGLYBUFF]: [ MoveId.DRAIN_PUNCH, MoveId.GRAV_APPLE, MoveId.SOFT_BOILED, MoveId.EXTREME_SPEED ], [SpeciesId.TOGEPI]: [ MoveId.SCORCHING_SANDS, MoveId.SPLISHY_SPLASH, MoveId.RELIC_SONG, MoveId.FIERY_DANCE ], [SpeciesId.NATU]: [ MoveId.REVIVAL_BLESSING, MoveId.NASTY_PLOT, MoveId.MOONBLAST, MoveId.OBLIVION_WING ], - [SpeciesId.MAREEP]: [ MoveId.ICE_BEAM, MoveId.PARABOLIC_CHARGE, MoveId.CORE_ENFORCER, MoveId.TAIL_GLOW ], + [SpeciesId.MAREEP]: [ MoveId.FLAMETHROWER, MoveId.PARABOLIC_CHARGE, MoveId.CORE_ENFORCER, MoveId.TAIL_GLOW ], [SpeciesId.HOPPIP]: [ MoveId.FLOATY_FALL, MoveId.STRENGTH_SAP, MoveId.SAPPY_SEED, MoveId.SPORE ], [SpeciesId.AIPOM]: [ MoveId.ROCK_BLAST, MoveId.STORM_THROW, MoveId.FAKE_OUT, MoveId.SWORDS_DANCE ], [SpeciesId.SUNKERN]: [ MoveId.SPORE, MoveId.QUIVER_DANCE, MoveId.FIERY_DANCE, MoveId.HYDRO_STEAM ], [SpeciesId.YANMA]: [ MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.HEAT_WAVE, MoveId.BLEAKWIND_STORM ], [SpeciesId.WOOPER]: [ MoveId.SIZZLY_SLIDE, MoveId.RECOVER, MoveId.SHED_TAIL, MoveId.SURGING_STRIKES ], - [SpeciesId.MURKROW]: [ MoveId.TRIPLE_ARROWS, MoveId.FLOATY_FALL, MoveId.TIDY_UP, MoveId.WICKED_BLOW ], + [SpeciesId.MURKROW]: [ MoveId.CROSS_CHOP, MoveId.FLOATY_FALL, MoveId.TIDY_UP, MoveId.WICKED_BLOW ], [SpeciesId.MISDREAVUS]: [ MoveId.TAKE_HEART, MoveId.MOONBLAST, MoveId.AURA_SPHERE, MoveId.MOONGEIST_BEAM ], [SpeciesId.UNOWN]: [ MoveId.NATURE_POWER, MoveId.COSMIC_POWER, MoveId.ANCIENT_POWER, MoveId.MYSTICAL_POWER ], [SpeciesId.GIRAFARIG]: [ MoveId.MYSTICAL_POWER, MoveId.NIGHT_DAZE, MoveId.RECOVER, MoveId.BOOMBURST ], [SpeciesId.PINECO]: [ MoveId.METAL_BURST, MoveId.RECOVER, MoveId.LEECH_LIFE, MoveId.SPIN_OUT ], [SpeciesId.DUNSPARCE]: [ MoveId.WICKED_TORQUE, MoveId.MAGICAL_TORQUE, MoveId.BLAZING_TORQUE, MoveId.EXTREME_SPEED ], - [SpeciesId.GLIGAR]: [ MoveId.FLOATY_FALL, MoveId.THOUSAND_WAVES, MoveId.SPIKY_SHIELD, MoveId.MIGHTY_CLEAVE ], + [SpeciesId.GLIGAR]: [ MoveId.FLY, MoveId.THOUSAND_WAVES, MoveId.BANEFUL_BUNKER, MoveId.MIGHTY_CLEAVE ], [SpeciesId.SNUBBULL]: [ MoveId.FACADE, MoveId.HIGH_HORSEPOWER, MoveId.SWORDS_DANCE, MoveId.EXTREME_SPEED ], [SpeciesId.QWILFISH]: [ MoveId.BARB_BARRAGE, MoveId.BANEFUL_BUNKER, MoveId.RECOVER, MoveId.FISHIOUS_REND ], [SpeciesId.SHUCKLE]: [ MoveId.STUFF_CHEEKS, MoveId.HEAL_ORDER, MoveId.BODY_PRESS, MoveId.SALT_CURE ], @@ -132,7 +132,7 @@ export const speciesEggMoves = { [SpeciesId.HO_OH]: [ MoveId.BRAVE_BIRD, MoveId.DRAGON_DANCE, MoveId.REVIVAL_BLESSING, MoveId.BOLT_BEAK ], [SpeciesId.CELEBI]: [ MoveId.PHOTON_GEYSER, MoveId.MATCHA_GOTCHA, MoveId.REVIVAL_BLESSING, MoveId.QUIVER_DANCE ], - [SpeciesId.TREECKO]: [ MoveId.NASTY_PLOT, MoveId.CORE_ENFORCER, MoveId.FLAMETHROWER, MoveId.SEED_FLARE ], + [SpeciesId.TREECKO]: [ MoveId.NASTY_PLOT, MoveId.CLANGING_SCALES, MoveId.SECRET_SWORD, MoveId.SEED_FLARE ], [SpeciesId.TORCHIC]: [ MoveId.THUNDEROUS_KICK, MoveId.ZING_ZAP, MoveId.BURNING_BULWARK, MoveId.PYRO_BALL ], [SpeciesId.MUDKIP]: [ MoveId.SHORE_UP, MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.PRECIPICE_BLADES ], [SpeciesId.POOCHYENA]: [ MoveId.KNOCK_OFF, MoveId.CLOSE_COMBAT, MoveId.DIRE_CLAW, MoveId.VICTORY_DANCE ], @@ -207,7 +207,7 @@ export const speciesEggMoves = { [SpeciesId.DEOXYS]: [ MoveId.COLLISION_COURSE, MoveId.FUSION_FLARE, MoveId.PARTING_SHOT, MoveId.LUMINA_CRASH ], [SpeciesId.TURTWIG]: [ MoveId.SHELL_SMASH, MoveId.STONE_AXE, MoveId.ICE_SPINNER, MoveId.SAPPY_SEED ], - [SpeciesId.CHIMCHAR]: [ MoveId.THUNDERBOLT, MoveId.SECRET_SWORD, MoveId.TRIPLE_AXEL, MoveId.SACRED_FIRE ], + [SpeciesId.CHIMCHAR]: [ MoveId.THUNDERBOLT, MoveId.SECRET_SWORD, MoveId.ICE_PUNCH, MoveId.SACRED_FIRE ], [SpeciesId.PIPLUP]: [ MoveId.KINGS_SHIELD, MoveId.TACHYON_CUTTER, MoveId.FREEZE_DRY, MoveId.STEAM_ERUPTION ], [SpeciesId.STARLY]: [ MoveId.SWORDS_DANCE, MoveId.HEAD_CHARGE, MoveId.FLARE_BLITZ, MoveId.EXTREME_SPEED ], [SpeciesId.BIDOOF]: [ MoveId.EXTREME_SPEED, MoveId.COSMIC_POWER, MoveId.POWER_TRIP, MoveId.AQUA_STEP ], @@ -234,7 +234,7 @@ export const speciesEggMoves = { [SpeciesId.CHATOT]: [ MoveId.SPARKLING_ARIA, MoveId.BOOMBURST, MoveId.BATON_PASS, MoveId.TORCH_SONG ], [SpeciesId.SPIRITOMB]: [ MoveId.PARTING_SHOT, MoveId.BADDY_BAD, MoveId.BITTER_MALICE, MoveId.STRENGTH_SAP ], [SpeciesId.GIBLE]: [ MoveId.METEOR_MASH, MoveId.BITTER_BLADE, MoveId.LANDS_WRATH, MoveId.DRAGON_DANCE ], - [SpeciesId.MUNCHLAX]: [ MoveId.STUFF_CHEEKS, MoveId.GRAV_APPLE, MoveId.SLACK_OFF, MoveId.EXTREME_SPEED ], + [SpeciesId.MUNCHLAX]: [ MoveId.OBSTRUCT, MoveId.GRAV_APPLE, MoveId.SUCKER_PUNCH, MoveId.SLACK_OFF ], [SpeciesId.RIOLU]: [ MoveId.THUNDEROUS_KICK, MoveId.TACHYON_CUTTER, MoveId.TRIPLE_AXEL, MoveId.SUNSTEEL_STRIKE ], [SpeciesId.HIPPOPOTAS]: [ MoveId.SHORE_UP, MoveId.STONE_AXE, MoveId.BULK_UP, MoveId.SALT_CURE ], [SpeciesId.SKORUPI]: [ MoveId.COIL, MoveId.DIRE_CLAW, MoveId.CRABHAMMER, MoveId.WICKED_BLOW ], @@ -260,7 +260,7 @@ export const speciesEggMoves = { [SpeciesId.ARCEUS]: [ MoveId.NO_RETREAT, MoveId.COLLISION_COURSE, MoveId.ASTRAL_BARRAGE, MoveId.MULTI_ATTACK ], [SpeciesId.VICTINI]: [ MoveId.BLUE_FLARE, MoveId.BOLT_STRIKE, MoveId.LUSTER_PURGE, MoveId.VICTORY_DANCE ], - [SpeciesId.SNIVY]: [ MoveId.FLAMETHROWER, MoveId.CLANGING_SCALES, MoveId.MAKE_IT_RAIN, MoveId.FLEUR_CANNON ], + [SpeciesId.SNIVY]: [ MoveId.BURNING_JEALOUSY, MoveId.LEECH_LIFE, MoveId.SUPERPOWER, MoveId.DRACO_METEOR ], [SpeciesId.TEPIG]: [ MoveId.WAVE_CRASH, MoveId.VOLT_TACKLE, MoveId.AXE_KICK, MoveId.VICTORY_DANCE ], [SpeciesId.OSHAWOTT]: [ MoveId.FREEZE_DRY, MoveId.SHELL_SIDE_ARM, MoveId.SACRED_SWORD, MoveId.SHELL_SMASH ], [SpeciesId.PATRAT]: [ MoveId.FAKE_OUT, MoveId.INSTRUCT, MoveId.DYNAMIC_PUNCH, MoveId.EXTREME_SPEED ], @@ -289,7 +289,7 @@ export const speciesEggMoves = { [SpeciesId.DARUMAKA]: [ MoveId.DRAIN_PUNCH, MoveId.ZIPPY_ZAP, MoveId.HEADLONG_RUSH, MoveId.PYRO_BALL ], [SpeciesId.MARACTUS]: [ MoveId.EARTH_POWER, MoveId.SIZZLY_SLIDE, MoveId.FIERY_DANCE, MoveId.QUIVER_DANCE ], [SpeciesId.DWEBBLE]: [ MoveId.CRABHAMMER, MoveId.STONE_AXE, MoveId.LEECH_LIFE, MoveId.MIGHTY_CLEAVE ], - [SpeciesId.SCRAGGY]: [ MoveId.SUCKER_PUNCH, MoveId.BULLET_PUNCH, MoveId.NOXIOUS_TORQUE, MoveId.VICTORY_DANCE ], + [SpeciesId.SCRAGGY]: [ MoveId.SUCKER_PUNCH, MoveId.SLACK_OFF, MoveId.GUNK_SHOT, MoveId.THUNDEROUS_KICK ], [SpeciesId.SIGILYPH]: [ MoveId.MOONBLAST, MoveId.PSYCHO_SHIFT, MoveId.ESPER_WING, MoveId.OBLIVION_WING ], [SpeciesId.YAMASK]: [ MoveId.STRENGTH_SAP, MoveId.GLARE, MoveId.AURA_SPHERE, MoveId.ASTRAL_BARRAGE ], [SpeciesId.TIRTOUGA]: [ MoveId.ICE_SPINNER, MoveId.AQUA_STEP, MoveId.SHORE_UP, MoveId.MIGHTY_CLEAVE ], @@ -323,12 +323,12 @@ export const speciesEggMoves = { [SpeciesId.GOLETT]: [ MoveId.SHIFT_GEAR, MoveId.DRAIN_PUNCH, MoveId.HEADLONG_RUSH, MoveId.RAGE_FIST ], [SpeciesId.PAWNIARD]: [ MoveId.SUCKER_PUNCH, MoveId.SPIRIT_BREAK, MoveId.LAST_RESPECTS, MoveId.BITTER_BLADE ], [SpeciesId.BOUFFALANT]: [ MoveId.HORN_LEECH, MoveId.HIGH_JUMP_KICK, MoveId.HEAD_SMASH, MoveId.FLARE_BLITZ ], - [SpeciesId.RUFFLET]: [ MoveId.FLOATY_FALL, MoveId.AURA_SPHERE, MoveId.NO_RETREAT, MoveId.BOLT_BEAK ], + [SpeciesId.RUFFLET]: [ MoveId.FLOATY_FALL, MoveId.AURA_SPHERE, MoveId.DRILL_RUN, MoveId.NO_RETREAT ], [SpeciesId.VULLABY]: [ MoveId.FOUL_PLAY, MoveId.BODY_PRESS, MoveId.ROOST, MoveId.RUINATION ], [SpeciesId.HEATMOR]: [ MoveId.EARTH_POWER, MoveId.OVERHEAT, MoveId.SUPERCELL_SLAM, MoveId.V_CREATE ], [SpeciesId.DURANT]: [ MoveId.HIGH_HORSEPOWER, MoveId.FIRST_IMPRESSION, MoveId.U_TURN, MoveId.BEHEMOTH_BASH ], [SpeciesId.DEINO]: [ MoveId.FIERY_WRATH, MoveId.ESPER_WING, MoveId.SLUDGE_BOMB, MoveId.FICKLE_BEAM ], - [SpeciesId.LARVESTA]: [ MoveId.THUNDERBOLT, MoveId.DAZZLING_GLEAM, MoveId.EARTH_POWER, MoveId.HYDRO_STEAM ], + [SpeciesId.LARVESTA]: [ MoveId.THUNDERBOLT, MoveId.DAZZLING_GLEAM, MoveId.SCALD, MoveId.SANDSEAR_STORM ], [SpeciesId.COBALION]: [ MoveId.BEHEMOTH_BLADE, MoveId.MIGHTY_CLEAVE, MoveId.CEASELESS_EDGE, MoveId.VICTORY_DANCE ], [SpeciesId.TERRAKION]: [ MoveId.MIGHTY_CLEAVE, MoveId.HEADLONG_RUSH, MoveId.KNOCK_OFF, MoveId.VICTORY_DANCE ], [SpeciesId.VIRIZION]: [ MoveId.SAPPY_SEED, MoveId.PSYBLADE, MoveId.STONE_AXE, MoveId.VICTORY_DANCE ], @@ -348,7 +348,7 @@ export const speciesEggMoves = { [SpeciesId.BUNNELBY]: [ MoveId.DRAIN_PUNCH, MoveId.TIDY_UP, MoveId.LANDS_WRATH, MoveId.EXTREME_SPEED ], [SpeciesId.FLETCHLING]: [ MoveId.DRILL_RUN, MoveId.BURNING_BULWARK, MoveId.HEAD_SMASH, MoveId.VOLT_TACKLE ], [SpeciesId.SCATTERBUG]: [ MoveId.FOCUS_BLAST, MoveId.AFTER_YOU, MoveId.DECORATE, MoveId.BLIZZARD ], - [SpeciesId.LITLEO]: [ MoveId.EARTH_POWER, MoveId.NASTY_PLOT, MoveId.BURNING_BULWARK, MoveId.BLUE_FLARE ], + [SpeciesId.LITLEO]: [ MoveId.EARTH_POWER, MoveId.TAKE_HEART, MoveId.BURNING_BULWARK, MoveId.BOOMBURST ], [SpeciesId.FLABEBE]: [ MoveId.GLITZY_GLOW, MoveId.MYSTICAL_FIRE, MoveId.TAKE_HEART, MoveId.SEED_FLARE ], [SpeciesId.SKIDDO]: [ MoveId.HIGH_HORSEPOWER, MoveId.GRASSY_GLIDE, MoveId.STONE_AXE, MoveId.SAPPY_SEED ], [SpeciesId.PANCHAM]: [ MoveId.DRAIN_PUNCH, MoveId.SUCKER_PUNCH, MoveId.METEOR_MASH, MoveId.WICKED_BLOW ], @@ -358,7 +358,7 @@ export const speciesEggMoves = { [SpeciesId.SPRITZEE]: [ MoveId.SPEED_SWAP, MoveId.REVIVAL_BLESSING, MoveId.ROOST, MoveId.TORCH_SONG ], [SpeciesId.SWIRLIX]: [ MoveId.BELLY_DRUM, MoveId.HEADLONG_RUSH, MoveId.MAGICAL_TORQUE, MoveId.REVIVAL_BLESSING ], [SpeciesId.INKAY]: [ MoveId.POWER_TRIP, MoveId.SPIN_OUT, MoveId.RECOVER, MoveId.PSYCHO_BOOST ], - [SpeciesId.BINACLE]: [ MoveId.TRIPLE_AXEL, MoveId.CRABHAMMER, MoveId.DIRE_CLAW, MoveId.MIGHTY_CLEAVE ], + [SpeciesId.BINACLE]: [ MoveId.ICE_PUNCH, MoveId.CRABHAMMER, MoveId.METEOR_MASH, MoveId.MIGHTY_CLEAVE ], [SpeciesId.SKRELP]: [ MoveId.STRENGTH_SAP, MoveId.TRICK_ROOM, MoveId.CALM_MIND, MoveId.CORE_ENFORCER ], [SpeciesId.CLAUNCHER]: [ MoveId.SHELL_SMASH, MoveId.ARMOR_CANNON, MoveId.ENERGY_BALL, MoveId.ORIGIN_PULSE ], [SpeciesId.HELIOPTILE]: [ MoveId.WEATHER_BALL, MoveId.HYDRO_STEAM, MoveId.EARTH_POWER, MoveId.BOOMBURST ], @@ -379,26 +379,26 @@ export const speciesEggMoves = { [SpeciesId.DIANCIE]: [ MoveId.MAGICAL_TORQUE, MoveId.FIERY_DANCE, MoveId.SHORE_UP, MoveId.GEOMANCY ], [SpeciesId.HOOPA]: [ MoveId.PHOTON_GEYSER, MoveId.SECRET_SWORD, MoveId.FIERY_WRATH, MoveId.SHELL_SMASH ], [SpeciesId.VOLCANION]: [ MoveId.HYDRO_STEAM, MoveId.CALM_MIND, MoveId.SEARING_SHOT, MoveId.THUNDERCLAP ], - [SpeciesId.ETERNAL_FLOETTE]: [ MoveId.MIND_BLOWN, MoveId.CHLOROBLAST, MoveId.LUSTER_PURGE, MoveId.QUIVER_DANCE ], + [SpeciesId.ETERNAL_FLOETTE]: [ MoveId.MYSTICAL_FIRE, MoveId.CHLOROBLAST, MoveId.LUSTER_PURGE, MoveId.QUIVER_DANCE ], [SpeciesId.ROWLET]: [ MoveId.THOUSAND_ARROWS, MoveId.SHADOW_BONE, MoveId.FIRST_IMPRESSION, MoveId.VICTORY_DANCE ], [SpeciesId.LITTEN]: [ MoveId.SUCKER_PUNCH, MoveId.PARTING_SHOT, MoveId.SLACK_OFF, MoveId.SACRED_FIRE ], [SpeciesId.POPPLIO]: [ MoveId.PSYCHIC_NOISE, MoveId.MOONLIGHT, MoveId.OVERDRIVE, MoveId.TORCH_SONG ], [SpeciesId.PIKIPEK]: [ MoveId.TRAILBLAZE, MoveId.BONE_RUSH, MoveId.BURNING_BULWARK, MoveId.POPULATION_BOMB ], [SpeciesId.YUNGOOS]: [ MoveId.FAKE_OUT, MoveId.HIGH_HORSEPOWER, MoveId.TIDY_UP, MoveId.EXTREME_SPEED ], - [SpeciesId.GRUBBIN]: [ MoveId.ICE_BEAM, MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.THUNDERCLAP ], + [SpeciesId.GRUBBIN]: [ MoveId.THUNDERCLAP, MoveId.EARTH_POWER, MoveId.CALM_MIND, MoveId.ICE_BEAM ], [SpeciesId.CRABRAWLER]: [ MoveId.JET_PUNCH, MoveId.SHORE_UP, MoveId.MACH_PUNCH, MoveId.SURGING_STRIKES ], [SpeciesId.ORICORIO]: [ MoveId.QUIVER_DANCE, MoveId.FIERY_DANCE, MoveId.THUNDERCLAP, MoveId.OBLIVION_WING ], [SpeciesId.CUTIEFLY]: [ MoveId.STICKY_WEB, MoveId.SLEEP_POWDER, MoveId.HEAT_WAVE, MoveId.SPARKLY_SWIRL ], [SpeciesId.ROCKRUFF]: [ MoveId.HIGH_HORSEPOWER, MoveId.TIDY_UP, MoveId.ICE_SPINNER, MoveId.MIGHTY_CLEAVE ], [SpeciesId.WISHIWASHI]: [ MoveId.HEAL_ORDER, MoveId.FREEZE_DRY, MoveId.WATER_SHURIKEN, MoveId.TAIL_GLOW ], - [SpeciesId.MAREANIE]: [ MoveId.CEASELESS_EDGE, MoveId.SIZZLY_SLIDE, MoveId.BODY_PRESS, MoveId.LEECH_SEED ], + [SpeciesId.MAREANIE]: [ MoveId.CEASELESS_EDGE, MoveId.BARB_BARRAGE, MoveId.BODY_PRESS, MoveId.FLIP_TURN ], [SpeciesId.MUDBRAY]: [ MoveId.BODY_PRESS, MoveId.YAWN, MoveId.SHORE_UP, MoveId.THOUSAND_WAVES ], [SpeciesId.DEWPIDER]: [ MoveId.AQUA_STEP, MoveId.SILK_TRAP, MoveId.SWORDS_DANCE, MoveId.JET_PUNCH ], [SpeciesId.FOMANTIS]: [ MoveId.SUPERPOWER, MoveId.HEADLONG_RUSH, MoveId.ICE_HAMMER, MoveId.BITTER_BLADE ], [SpeciesId.MORELULL]: [ MoveId.CALM_MIND, MoveId.SAPPY_SEED, MoveId.DRAINING_KISS, MoveId.MATCHA_GOTCHA ], [SpeciesId.SALANDIT]: [ MoveId.SCALD, MoveId.MALIGNANT_CHAIN, MoveId.CORE_ENFORCER, MoveId.ERUPTION ], - [SpeciesId.STUFFUL]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.TRIPLE_AXEL, MoveId.RAGE_FIST ], + [SpeciesId.STUFFUL]: [ MoveId.DRAIN_PUNCH, MoveId.METEOR_MASH, MoveId.ICE_HAMMER, MoveId.CRUSH_GRIP ], [SpeciesId.BOUNSWEET]: [ MoveId.TRIPLE_AXEL, MoveId.AQUA_STEP, MoveId.THUNDEROUS_KICK, MoveId.FLOWER_TRICK ], [SpeciesId.COMFEY]: [ MoveId.REVIVAL_BLESSING, MoveId.TAKE_HEART, MoveId.STRENGTH_SAP, MoveId.MATCHA_GOTCHA ], [SpeciesId.ORANGURU]: [ MoveId.JUNGLE_HEALING, MoveId.YAWN, MoveId.FOLLOW_ME, MoveId.LUMINA_CRASH ], @@ -416,7 +416,7 @@ export const speciesEggMoves = { [SpeciesId.DRAMPA]: [ MoveId.SLACK_OFF, MoveId.TRICK_ROOM, MoveId.CORE_ENFORCER, MoveId.BOOMBURST ], [SpeciesId.DHELMISE]: [ MoveId.SHADOW_BONE, MoveId.IVY_CUDGEL, MoveId.TRIPLE_DIVE, MoveId.STRENGTH_SAP ], [SpeciesId.JANGMO_O]: [ MoveId.BODY_PRESS, MoveId.SHELL_SIDE_ARM, MoveId.SECRET_SWORD, MoveId.GLAIVE_RUSH ], - [SpeciesId.TAPU_KOKO]: [ MoveId.MAGICAL_TORQUE, MoveId.TRIPLE_AXEL, MoveId.SWORDS_DANCE, MoveId.BOLT_STRIKE ], + [SpeciesId.TAPU_KOKO]: [ MoveId.PLAY_ROUGH, MoveId.ZING_ZAP, MoveId.SWORDS_DANCE, MoveId.TRIPLE_AXEL ], [SpeciesId.TAPU_LELE]: [ MoveId.MOONLIGHT, MoveId.NASTY_PLOT, MoveId.HEAT_WAVE, MoveId.EXPANDING_FORCE ], [SpeciesId.TAPU_BULU]: [ MoveId.SAPPY_SEED, MoveId.LANDS_WRATH, MoveId.MAGICAL_TORQUE, MoveId.VICTORY_DANCE ], [SpeciesId.TAPU_FINI]: [ MoveId.SPRINGTIDE_STORM, MoveId.EARTH_POWER, MoveId.RECOVER, MoveId.QUIVER_DANCE ], @@ -429,11 +429,11 @@ export const speciesEggMoves = { [SpeciesId.KARTANA]: [ MoveId.MIGHTY_CLEAVE, MoveId.DUAL_CHOP, MoveId.BEHEMOTH_BLADE, MoveId.BITTER_BLADE ], [SpeciesId.GUZZLORD]: [ MoveId.SUCKER_PUNCH, MoveId.COMEUPPANCE, MoveId.SLACK_OFF, MoveId.SHED_TAIL ], [SpeciesId.NECROZMA]: [ MoveId.DYNAMAX_CANNON, MoveId.SACRED_FIRE, MoveId.ASTRAL_BARRAGE, MoveId.CLANGOROUS_SOUL ], - [SpeciesId.MAGEARNA]: [ MoveId.STRENGTH_SAP, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.MAKE_IT_RAIN ], + [SpeciesId.MAGEARNA]: [ MoveId.RECOVER, MoveId.EARTH_POWER, MoveId.MOONBLAST, MoveId.MAKE_IT_RAIN ], [SpeciesId.MARSHADOW]: [ MoveId.POWER_UP_PUNCH, MoveId.BONEMERANG, MoveId.METEOR_MASH, MoveId.TRIPLE_AXEL ], [SpeciesId.POIPOLE]: [ MoveId.MALIGNANT_CHAIN, MoveId.ICE_BEAM, MoveId.ARMOR_CANNON, MoveId.CLANGING_SCALES ], [SpeciesId.STAKATAKA]: [ MoveId.HEAVY_SLAM, MoveId.HEAL_ORDER, MoveId.CURSE, MoveId.SALT_CURE ], - [SpeciesId.BLACEPHALON]: [ MoveId.STEEL_BEAM, MoveId.MOONBLAST, MoveId.CHLOROBLAST, MoveId.MOONGEIST_BEAM ], + [SpeciesId.BLACEPHALON]: [ MoveId.CHILLY_RECEPTION, MoveId.MOONBLAST, MoveId.ENERGY_BALL, MoveId.MOONGEIST_BEAM ], [SpeciesId.ZERAORA]: [ MoveId.SWORDS_DANCE, MoveId.FIRE_LASH, MoveId.COLLISION_COURSE, MoveId.TRIPLE_AXEL ], [SpeciesId.MELTAN]: [ MoveId.BULLET_PUNCH, MoveId.DRAIN_PUNCH, MoveId.BULK_UP, MoveId.PLASMA_FISTS ], [SpeciesId.ALOLA_RATTATA]: [ MoveId.FALSE_SURRENDER, MoveId.PSYCHIC_FANGS, MoveId.COIL, MoveId.EXTREME_SPEED ], @@ -455,7 +455,7 @@ export const speciesEggMoves = { [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 ], - [SpeciesId.ROLYCOLY]: [ MoveId.BITTER_BLADE, MoveId.BODY_PRESS, MoveId.BULK_UP, MoveId.DIAMOND_STORM ], + [SpeciesId.ROLYCOLY]: [ MoveId.BLAZING_TORQUE, MoveId.BURNING_BULWARK, MoveId.RECOVER, MoveId.DIAMOND_STORM ], [SpeciesId.APPLIN]: [ MoveId.CORE_ENFORCER, MoveId.COMBAT_TORQUE, MoveId.SAPPY_SEED, MoveId.MATCHA_GOTCHA ], [SpeciesId.SILICOBRA]: [ MoveId.SHORE_UP, MoveId.SHED_TAIL, MoveId.MOUNTAIN_GALE, MoveId.THOUSAND_ARROWS ], [SpeciesId.CRAMORANT]: [ MoveId.APPLE_ACID, MoveId.SURF, MoveId.BOLT_BEAK, MoveId.OBLIVION_WING ], @@ -467,19 +467,19 @@ export const speciesEggMoves = { [SpeciesId.HATENNA]: [ MoveId.RECOVER, MoveId.MOONBLAST, MoveId.BUZZY_BUZZ, MoveId.TORCH_SONG ], [SpeciesId.IMPIDIMP]: [ MoveId.SLACK_OFF, MoveId.PARTING_SHOT, MoveId.OCTOLOCK, MoveId.WICKED_BLOW ], [SpeciesId.MILCERY]: [ MoveId.MOONBLAST, MoveId.CHILLY_RECEPTION, MoveId.EARTH_POWER, MoveId.GEOMANCY ], - [SpeciesId.FALINKS]: [ MoveId.BATON_PASS, MoveId.POWER_TRIP, MoveId.COMBAT_TORQUE, MoveId.HEAL_ORDER ], + [SpeciesId.FALINKS]: [ MoveId.BATON_PASS, MoveId.POWER_TRIP, MoveId.SACRED_SWORD, MoveId.HEAL_ORDER ], [SpeciesId.PINCURCHIN]: [ MoveId.TRICK_ROOM, MoveId.VOLT_SWITCH, MoveId.STRENGTH_SAP, MoveId.THUNDERCLAP ], [SpeciesId.SNOM]: [ MoveId.FROST_BREATH, MoveId.HEAL_ORDER, MoveId.EARTH_POWER, MoveId.SPORE ], [SpeciesId.STONJOURNER]: [ MoveId.AXE_KICK, MoveId.HELPING_HAND, MoveId.ACCELEROCK, MoveId.DIAMOND_STORM ], [SpeciesId.EISCUE]: [ MoveId.TRIPLE_AXEL, MoveId.AQUA_STEP, MoveId.AXE_KICK, MoveId.SHELL_SMASH ], [SpeciesId.INDEEDEE]: [ MoveId.MATCHA_GOTCHA, MoveId.EXPANDING_FORCE, MoveId.MOONBLAST, MoveId.REVIVAL_BLESSING ], - [SpeciesId.MORPEKO]: [ MoveId.TRIPLE_AXEL, MoveId.OBSTRUCT, MoveId.SWORDS_DANCE, MoveId.COLLISION_COURSE ], + [SpeciesId.MORPEKO]: [ MoveId.ICE_SPINNER, MoveId.OBSTRUCT, MoveId.STUFF_CHEEKS, MoveId.COLLISION_COURSE ], [SpeciesId.CUFANT]: [ MoveId.LIQUIDATION, MoveId.CURSE, MoveId.COMBAT_TORQUE, MoveId.GIGATON_HAMMER ], [SpeciesId.DRACOZOLT]: [ MoveId.TRIPLE_AXEL, MoveId.GUNK_SHOT, MoveId.FIRE_LASH, MoveId.DRAGON_DANCE ], [SpeciesId.ARCTOZOLT]: [ MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.HIGH_HORSEPOWER, MoveId.SHIFT_GEAR ], [SpeciesId.DRACOVISH]: [ MoveId.TRIPLE_AXEL, MoveId.DRAGON_HAMMER, MoveId.THUNDER_FANG, MoveId.DRAGON_DANCE ], [SpeciesId.ARCTOVISH]: [ MoveId.ICE_FANG, MoveId.THUNDER_FANG, MoveId.HIGH_HORSEPOWER, MoveId.SHIFT_GEAR ], - [SpeciesId.DURALUDON]: [ MoveId.CORE_ENFORCER, MoveId.BODY_PRESS, MoveId.RECOVER, MoveId.TACHYON_CUTTER ], + [SpeciesId.DURALUDON]: [ MoveId.DAZZLING_GLEAM, MoveId.BODY_PRESS, MoveId.THUNDERCLAP, MoveId.CORE_ENFORCER ], [SpeciesId.DREEPY]: [ MoveId.SHADOW_BONE, MoveId.POWER_UP_PUNCH, MoveId.FIRE_LASH, MoveId.DIRE_CLAW ], [SpeciesId.ZACIAN]: [ MoveId.MAGICAL_TORQUE, MoveId.MIGHTY_CLEAVE, MoveId.EARTHQUAKE, MoveId.BITTER_BLADE ], [SpeciesId.ZAMAZENTA]: [ MoveId.BULK_UP, MoveId.BODY_PRESS, MoveId.POWER_TRIP, MoveId.SLACK_OFF ], @@ -505,7 +505,7 @@ export const speciesEggMoves = { [SpeciesId.GALAR_YAMASK]: [ MoveId.STRENGTH_SAP, MoveId.DIRE_CLAW, MoveId.THOUSAND_WAVES, MoveId.SPECTRAL_THIEF ], [SpeciesId.GALAR_STUNFISK]: [ MoveId.SPIKY_SHIELD, MoveId.THOUSAND_ARROWS, MoveId.STRENGTH_SAP, MoveId.DOUBLE_IRON_BASH ], [SpeciesId.HISUI_GROWLITHE]: [ MoveId.WAVE_CRASH, MoveId.HEAD_SMASH, MoveId.VOLT_TACKLE, MoveId.DRAGON_DANCE ], - [SpeciesId.HISUI_VOLTORB]: [ MoveId.FROST_BREATH, MoveId.NASTY_PLOT, MoveId.APPLE_ACID, MoveId.ELECTRO_DRIFT ], + [SpeciesId.HISUI_VOLTORB]: [ MoveId.DAZZLING_GLEAM, MoveId.LEECH_SEED, MoveId.APPLE_ACID, MoveId.MIND_BLOWN ], [SpeciesId.HISUI_QWILFISH]: [ MoveId.CEASELESS_EDGE, MoveId.BANEFUL_BUNKER, MoveId.RECOVER, MoveId.FISHIOUS_REND ], [SpeciesId.HISUI_SNEASEL]: [ MoveId.DRAIN_PUNCH, MoveId.KNOCK_OFF, MoveId.PSYCHIC_FANGS, MoveId.TRIPLE_AXEL ], [SpeciesId.HISUI_ZORUA]: [ MoveId.MOONBLAST, MoveId.SECRET_SWORD, MoveId.PARTING_SHOT, MoveId.BLOOD_MOON ], @@ -520,7 +520,7 @@ export const speciesEggMoves = { [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 ], + [SpeciesId.SQUAWKABILLY]: [ MoveId.PARTING_SHOT, MoveId.BULK_UP, MoveId.CLOSE_COMBAT, MoveId.EXTREME_SPEED ], [SpeciesId.NACLI]: [ MoveId.KNOCK_OFF, MoveId.TOXIC, MoveId.SAND_TOMB, MoveId.DIAMOND_STORM ], [SpeciesId.CHARCADET]: [ MoveId.SACRED_SWORD, MoveId.PHOTON_GEYSER, MoveId.MOONBLAST, MoveId.SPECTRAL_THIEF ], [SpeciesId.TADBULB]: [ MoveId.PARABOLIC_CHARGE, MoveId.SCALD, MoveId.EARTH_POWER, MoveId.ELECTRO_SHOT ], @@ -552,7 +552,7 @@ export const speciesEggMoves = { [SpeciesId.BRUTE_BONNET]: [ MoveId.SAPPY_SEED, MoveId.STRENGTH_SAP, MoveId.EARTHQUAKE, MoveId.WICKED_BLOW ], [SpeciesId.FLUTTER_MANE]: [ MoveId.MOONLIGHT, MoveId.NASTY_PLOT, MoveId.EARTH_POWER, MoveId.MOONGEIST_BEAM ], [SpeciesId.SLITHER_WING]: [ MoveId.ROCK_SLIDE, MoveId.THUNDEROUS_KICK, MoveId.SUNSTEEL_STRIKE, MoveId.VICTORY_DANCE ], - [SpeciesId.SANDY_SHOCKS]: [ MoveId.MORNING_SUN, MoveId.ICE_BEAM, MoveId.NASTY_PLOT, MoveId.THUNDERCLAP ], + [SpeciesId.SANDY_SHOCKS]: [ MoveId.MORNING_SUN, MoveId.THUNDERCLAP, MoveId.NASTY_PLOT, MoveId.ICE_BEAM ], [SpeciesId.IRON_TREADS]: [ MoveId.FUSION_BOLT, MoveId.SHIFT_GEAR, MoveId.SHORE_UP, MoveId.SUNSTEEL_STRIKE ], [SpeciesId.IRON_BUNDLE]: [ MoveId.EARTH_POWER, MoveId.SPLISHY_SPLASH, MoveId.VOLT_SWITCH, MoveId.NASTY_PLOT ], [SpeciesId.IRON_HANDS]: [ MoveId.DRAIN_PUNCH, MoveId.BULK_UP, MoveId.PLASMA_FISTS, MoveId.ICE_HAMMER ], @@ -582,7 +582,7 @@ export const speciesEggMoves = { [SpeciesId.IRON_CROWN]: [ MoveId.NASTY_PLOT, MoveId.SECRET_SWORD, MoveId.PSYSTRIKE, MoveId.ELECTRO_DRIFT ], [SpeciesId.TERAPAGOS]: [ MoveId.MOONBLAST, MoveId.NASTY_PLOT, MoveId.ASTRAL_BARRAGE, MoveId.RECOVER ], [SpeciesId.PECHARUNT]: [ MoveId.TAKE_HEART, MoveId.BODY_PRESS, MoveId.SAPPY_SEED, MoveId.ASTRAL_BARRAGE ], - [SpeciesId.PALDEA_TAUROS]: [ MoveId.NO_RETREAT, MoveId.BLAZING_TORQUE, MoveId.AQUA_STEP, MoveId.THUNDEROUS_KICK ], + [SpeciesId.PALDEA_TAUROS]: [ MoveId.U_TURN, MoveId.SUCKER_PUNCH, MoveId.HORN_LEECH, MoveId.THUNDEROUS_KICK ], [SpeciesId.PALDEA_WOOPER]: [ MoveId.STONE_AXE, MoveId.RECOVER, MoveId.BANEFUL_BUNKER, MoveId.BARB_BARRAGE ], [SpeciesId.BLOODMOON_URSALUNA]: [ MoveId.NASTY_PLOT, MoveId.ROCK_POLISH, MoveId.SANDSEAR_STORM, MoveId.BOOMBURST ] } satisfies Partial>; diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index 1297ad71c36..592cee69d7d 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -16,9 +16,9 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.CHARMANDER]: { 0: AbilityId.SHEER_FORCE }, [SpeciesId.CHARMELEON]: { 0: AbilityId.BEAST_BOOST }, [SpeciesId.CHARIZARD]: { 0: AbilityId.BEAST_BOOST, 1: AbilityId.LEVITATE, 2: AbilityId.TURBOBLAZE, 3: AbilityId.UNNERVE }, - [SpeciesId.SQUIRTLE]: { 0: AbilityId.DAUNTLESS_SHIELD }, - [SpeciesId.WARTORTLE]: { 0: AbilityId.DAUNTLESS_SHIELD }, - [SpeciesId.BLASTOISE]: { 0: AbilityId.DAUNTLESS_SHIELD, 1: AbilityId.BULLETPROOF, 2: AbilityId.BULLETPROOF }, + [SpeciesId.SQUIRTLE]: { 0: AbilityId.BULLETPROOF }, + [SpeciesId.WARTORTLE]: { 0: AbilityId.BULLETPROOF }, + [SpeciesId.BLASTOISE]: { 0: AbilityId.BULLETPROOF, 1: AbilityId.BULLETPROOF, 2: AbilityId.BULLETPROOF }, [SpeciesId.CATERPIE]: { 0: AbilityId.GLUTTONY }, [SpeciesId.METAPOD]: { 0: AbilityId.STURDY }, [SpeciesId.BUTTERFREE]: { 0: AbilityId.MAGICIAN, 1: AbilityId.MAGICIAN }, @@ -30,8 +30,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.PIDGEOT]: { 0: AbilityId.SHEER_FORCE, 1: AbilityId.SHEER_FORCE }, [SpeciesId.RATTATA]: { 0: AbilityId.STRONG_JAW }, [SpeciesId.RATICATE]: { 0: AbilityId.STRONG_JAW }, - [SpeciesId.SPEAROW]: { 0: AbilityId.MOXIE }, - [SpeciesId.FEAROW]: { 0: AbilityId.MOXIE }, + [SpeciesId.SPEAROW]: { 0: AbilityId.SPEED_BOOST }, + [SpeciesId.FEAROW]: { 0: AbilityId.SPEED_BOOST }, [SpeciesId.EKANS]: { 0: AbilityId.REGENERATOR }, [SpeciesId.ARBOK]: { 0: AbilityId.REGENERATOR }, [SpeciesId.SANDSHREW]: { 0: AbilityId.TOUGH_CLAWS }, @@ -101,9 +101,9 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.MUK]: { 0: AbilityId.WATER_ABSORB }, [SpeciesId.SHELLDER]: { 0: AbilityId.STURDY }, [SpeciesId.CLOYSTER]: { 0: AbilityId.ICE_SCALES }, - [SpeciesId.GASTLY]: { 0: AbilityId.SHADOW_SHIELD }, - [SpeciesId.HAUNTER]: { 0: AbilityId.SHADOW_SHIELD }, - [SpeciesId.GENGAR]: { 0: AbilityId.SHADOW_SHIELD, 1: AbilityId.UNNERVE, 2: AbilityId.GLUTTONY }, + [SpeciesId.GASTLY]: { 0: AbilityId.PRANKSTER }, + [SpeciesId.HAUNTER]: { 0: AbilityId.PRANKSTER }, + [SpeciesId.GENGAR]: { 0: AbilityId.LEVITATE, 1: AbilityId.UNNERVE, 2: AbilityId.REGENERATOR }, [SpeciesId.ONIX]: { 0: AbilityId.ROCKY_PAYLOAD }, [SpeciesId.STEELIX]: { 0: AbilityId.ROCKY_PAYLOAD, 1: AbilityId.SAND_SPIT }, [SpeciesId.DROWZEE]: { 0: AbilityId.MAGICIAN }, @@ -589,8 +589,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.MARACTUS]: { 0: AbilityId.WELL_BAKED_BODY }, [SpeciesId.DWEBBLE]: { 0: AbilityId.ROCKY_PAYLOAD }, [SpeciesId.CRUSTLE]: { 0: AbilityId.ROCKY_PAYLOAD }, - [SpeciesId.SCRAGGY]: { 0: AbilityId.PROTEAN }, - [SpeciesId.SCRAFTY]: { 0: AbilityId.PROTEAN }, + [SpeciesId.SCRAGGY]: { 0: AbilityId.UNBURDEN }, + [SpeciesId.SCRAFTY]: { 0: AbilityId.UNBURDEN }, [SpeciesId.SIGILYPH]: { 0: AbilityId.FLARE_BOOST }, [SpeciesId.YAMASK]: { 0: AbilityId.PURIFYING_SALT }, [SpeciesId.COFAGRIGUS]: { 0: AbilityId.PURIFYING_SALT }, @@ -669,7 +669,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.ZWEILOUS]: { 0: AbilityId.NO_GUARD }, [SpeciesId.HYDREIGON]: { 0: AbilityId.PARENTAL_BOND }, [SpeciesId.LARVESTA]: { 0: AbilityId.FLASH_FIRE }, - [SpeciesId.VOLCARONA]: { 0: AbilityId.DROUGHT }, + [SpeciesId.VOLCARONA]: { 0: AbilityId.FLASH_FIRE }, [SpeciesId.COBALION]: { 0: AbilityId.INTREPID_SWORD }, [SpeciesId.TERRAKION]: { 0: AbilityId.ROCKY_PAYLOAD }, [SpeciesId.VIRIZION]: { 0: AbilityId.SHARPNESS }, @@ -689,9 +689,9 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.FENNEKIN]: { 0: AbilityId.FLUFFY }, [SpeciesId.BRAIXEN]: { 0: AbilityId.PSYCHIC_SURGE }, [SpeciesId.DELPHOX]: { 0: AbilityId.PSYCHIC_SURGE }, - [SpeciesId.FROAKIE]: { 0: AbilityId.TECHNICIAN, 1: AbilityId.STAKEOUT }, - [SpeciesId.FROGADIER]: { 0: AbilityId.TECHNICIAN, 1: AbilityId.STAKEOUT }, - [SpeciesId.GRENINJA]: { 0: AbilityId.TECHNICIAN, 1: AbilityId.STAKEOUT, 2: AbilityId.SUPER_LUCK }, + [SpeciesId.FROAKIE]: { 0: AbilityId.STAKEOUT, 1: AbilityId.STAKEOUT }, + [SpeciesId.FROGADIER]: { 0: AbilityId.STAKEOUT, 1: AbilityId.STAKEOUT }, + [SpeciesId.GRENINJA]: { 0: AbilityId.STAKEOUT, 1: AbilityId.STAKEOUT, 2: AbilityId.SUPER_LUCK }, [SpeciesId.BUNNELBY]: { 0: AbilityId.INNER_FOCUS }, [SpeciesId.DIGGERSBY]: { 0: AbilityId.THICK_FAT }, [SpeciesId.FLETCHLING]: { 0: AbilityId.FLAME_BODY }, @@ -700,8 +700,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.SCATTERBUG]: { 0: AbilityId.RUN_AWAY, 1: AbilityId.RUN_AWAY, 2: AbilityId.RUN_AWAY, 3: AbilityId.RUN_AWAY, 4: AbilityId.RUN_AWAY, 5: AbilityId.RUN_AWAY, 6: AbilityId.RUN_AWAY, 7: AbilityId.RUN_AWAY, 8: AbilityId.RUN_AWAY, 9: AbilityId.RUN_AWAY, 10: AbilityId.RUN_AWAY, 11: AbilityId.RUN_AWAY, 12: AbilityId.RUN_AWAY, 13: AbilityId.RUN_AWAY, 14: AbilityId.RUN_AWAY, 15: AbilityId.RUN_AWAY, 16: AbilityId.RUN_AWAY, 17: AbilityId.RUN_AWAY, 18: AbilityId.RUN_AWAY, 19: AbilityId.RUN_AWAY }, [SpeciesId.SPEWPA]: { 0: AbilityId.COMPOUND_EYES, 1: AbilityId.COMPOUND_EYES, 2: AbilityId.COMPOUND_EYES, 3: AbilityId.COMPOUND_EYES, 4: AbilityId.COMPOUND_EYES, 5: AbilityId.COMPOUND_EYES, 6: AbilityId.COMPOUND_EYES, 7: AbilityId.COMPOUND_EYES, 8: AbilityId.COMPOUND_EYES, 9: AbilityId.COMPOUND_EYES, 10: AbilityId.COMPOUND_EYES, 11: AbilityId.COMPOUND_EYES, 12: AbilityId.COMPOUND_EYES, 13: AbilityId.COMPOUND_EYES, 14: AbilityId.COMPOUND_EYES, 15: AbilityId.COMPOUND_EYES, 16: AbilityId.COMPOUND_EYES, 17: AbilityId.COMPOUND_EYES, 18: AbilityId.COMPOUND_EYES, 19: AbilityId.COMPOUND_EYES }, [SpeciesId.VIVILLON]: { 0: AbilityId.PRANKSTER, 1: AbilityId.PRANKSTER, 2: AbilityId.PRANKSTER, 3: AbilityId.PRANKSTER, 4: AbilityId.PRANKSTER, 5: AbilityId.PRANKSTER, 6: AbilityId.PRANKSTER, 7: AbilityId.PRANKSTER, 8: AbilityId.PRANKSTER, 9: AbilityId.PRANKSTER, 10: AbilityId.PRANKSTER, 11: AbilityId.PRANKSTER, 12: AbilityId.PRANKSTER, 13: AbilityId.PRANKSTER, 14: AbilityId.PRANKSTER, 15: AbilityId.PRANKSTER, 16: AbilityId.PRANKSTER, 17: AbilityId.PRANKSTER, 18: AbilityId.PRANKSTER, 19: AbilityId.PRANKSTER }, - [SpeciesId.LITLEO]: { 0: AbilityId.BEAST_BOOST }, - [SpeciesId.PYROAR]: { 0: AbilityId.BEAST_BOOST }, + [SpeciesId.LITLEO]: { 0: AbilityId.DROUGHT }, + [SpeciesId.PYROAR]: { 0: AbilityId.DROUGHT }, [SpeciesId.FLABEBE]: { 0: AbilityId.GRASSY_SURGE, 1: AbilityId.GRASSY_SURGE, 2: AbilityId.GRASSY_SURGE, 3: AbilityId.GRASSY_SURGE, 4: AbilityId.GRASSY_SURGE }, [SpeciesId.FLOETTE]: { 0: AbilityId.GRASSY_SURGE, 1: AbilityId.GRASSY_SURGE, 2: AbilityId.GRASSY_SURGE, 3: AbilityId.GRASSY_SURGE, 4: AbilityId.GRASSY_SURGE }, [SpeciesId.FLORGES]: { 0: AbilityId.GRASSY_SURGE, 1: AbilityId.GRASSY_SURGE, 2: AbilityId.GRASSY_SURGE, 3: AbilityId.GRASSY_SURGE, 4: AbilityId.GRASSY_SURGE }, @@ -753,7 +753,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.NOIVERN]: { 0: AbilityId.PUNK_ROCK }, [SpeciesId.XERNEAS]: { 0: AbilityId.HARVEST, 1: AbilityId.HARVEST }, [SpeciesId.YVELTAL]: { 0: AbilityId.SOUL_HEART }, - [SpeciesId.ZYGARDE]: { 0: AbilityId.UNNERVE, 1: AbilityId.MOXIE, 2: AbilityId.UNNERVE, 3: AbilityId.MOXIE, 4: AbilityId.ADAPTABILITY, 5: AbilityId.ADAPTABILITY }, + [SpeciesId.ZYGARDE]: { 0: AbilityId.TERAFORM_ZERO, 1: AbilityId.MOXIE, 2: AbilityId.TERAFORM_ZERO, 3: AbilityId.MOXIE, 4: AbilityId.ADAPTABILITY, 5: AbilityId.ADAPTABILITY }, [SpeciesId.DIANCIE]: { 0: AbilityId.SOLID_ROCK, 1: AbilityId.PRISM_ARMOR }, [SpeciesId.HOOPA]: { 0: AbilityId.OPPORTUNIST, 1: AbilityId.OPPORTUNIST }, [SpeciesId.VOLCANION]: { 0: AbilityId.NEUTRALIZING_GAS }, @@ -975,8 +975,8 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.GALAR_STUNFISK]: { 0: AbilityId.ARENA_TRAP }, [SpeciesId.HISUI_GROWLITHE]: { 0: AbilityId.RECKLESS }, [SpeciesId.HISUI_ARCANINE]: { 0: AbilityId.RECKLESS }, - [SpeciesId.HISUI_VOLTORB]: { 0: AbilityId.TRANSISTOR }, - [SpeciesId.HISUI_ELECTRODE]: { 0: AbilityId.TRANSISTOR }, + [SpeciesId.HISUI_VOLTORB]: { 0: AbilityId.MAGIC_GUARD }, + [SpeciesId.HISUI_ELECTRODE]: { 0: AbilityId.MAGIC_GUARD }, [SpeciesId.HISUI_QWILFISH]: { 0: AbilityId.MERCILESS }, [SpeciesId.OVERQWIL]: { 0: AbilityId.MERCILESS }, [SpeciesId.HISUI_SNEASEL]: { 0: AbilityId.SCRAPPY }, diff --git a/src/data/balance/starters.ts b/src/data/balance/starters.ts index 99d5ad62e47..197a0d318bd 100644 --- a/src/data/balance/starters.ts +++ b/src/data/balance/starters.ts @@ -450,7 +450,7 @@ export const speciesStarterCosts = { [SpeciesId.TAPU_KOKO]: 6, [SpeciesId.TAPU_LELE]: 7, [SpeciesId.TAPU_BULU]: 6, - [SpeciesId.TAPU_FINI]: 5, + [SpeciesId.TAPU_FINI]: 6, [SpeciesId.COSMOG]: 7, [SpeciesId.NIHILEGO]: 6, [SpeciesId.BUZZWOLE]: 6, From 416c9336b6605a8b281b798a2aa71dc79d520433 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Mon, 27 Oct 2025 19:15:06 -0700 Subject: [PATCH 02/58] [Dev] Update `pnpm`, add `core-js` to allowed builds (#6703) --- package.json | 2 +- pnpm-workspace.yaml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a3f922731f2..f018717ed21 100644 --- a/package.json +++ b/package.json @@ -80,5 +80,5 @@ "engines": { "node": ">=24.9.0" }, - "packageManager": "pnpm@10.18.3" + "packageManager": "pnpm@10.19.0" } diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ec73d96e0db..e457e38a05c 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,6 +1,7 @@ onlyBuiltDependencies: + - core-js - esbuild - - msw - lefthook + - msw shellEmulator: true From 1b33f0d8e30f46a05e1e12b8b137fdc703067e06 Mon Sep 17 00:00:00 2001 From: Austin Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Mon, 27 Oct 2025 23:06:06 -0400 Subject: [PATCH 03/58] [Balance] Add functionality for Daily Run starting item event bonus (#6698) --- src/phases/title-phase.ts | 4 ++++ src/timed-event-manager.ts | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index 464f9211d61..bc530d6f0b0 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -1,5 +1,6 @@ import { loggedInUser } from "#app/account"; import { GameMode, getGameMode } from "#app/game-mode"; +import { timedEventManager } from "#app/global-event-manager"; import { globalScene } from "#app/global-scene"; import Overrides from "#app/overrides"; import { Phase } from "#app/phase"; @@ -259,6 +260,9 @@ export class TitlePhase extends Phase { for (const m of modifiers) { globalScene.addModifier(m, true, false, false, true); } + for (const m of timedEventManager.getEventDailyStartingItems()) { + globalScene.addModifier(modifierTypes[m]().newModifier(), true, false, false, true); + } globalScene.updateModifiers(true, true); Promise.all(loadPokemonAssets).then(() => { diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 926a65837cb..391b68d414e 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -75,6 +75,7 @@ interface TimedEvent extends EventBanner { readonly trainerShinyChance?: number; // Odds over 65536 of trainer mon generating as shiny readonly music?: readonly EventMusicReplacement[]; readonly dailyRunChallenges?: readonly EventChallenge[]; + readonly dailyRunStartingItems?: readonly ModifierTypeKeys[]; } const timedEvents: readonly TimedEvent[] = [ @@ -387,6 +388,7 @@ const timedEvents: readonly TimedEvent[] = [ { wave: 8, type: "CATCHING_CHARM" }, { wave: 25, type: "SHINY_CHARM" }, ], + dailyRunStartingItems: ["SHINY_CHARM", "ABILITY_CHARM"], }, ]; @@ -566,6 +568,10 @@ export class TimedEventManager { globalScene.gameMode.setChallengeValue(eventChal.challenge, eventChal.value); } } + + getEventDailyStartingItems(): readonly ModifierTypeKeys[] { + return this.activeEvent()?.dailyRunStartingItems ?? []; + } } export class TimedEventDisplay extends Phaser.GameObjects.Container { From b88cde162a1b28e8625b358ed720abf7b0cf8735 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Tue, 28 Oct 2025 03:14:22 -0500 Subject: [PATCH 04/58] [i18n] Update locales submodule --- locales | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales b/locales index 01a0aa4441b..5ef010497b8 160000 --- a/locales +++ b/locales @@ -1 +1 @@ -Subproject commit 01a0aa4441b85221c61211eb1097d93e004f4334 +Subproject commit 5ef010497b8cc688bd8ee79d40c967bd85ee8192 From c048b344254a473e5576086e4c44bb3f1fab1ccb Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Tue, 28 Oct 2025 21:03:32 -0700 Subject: [PATCH 05/58] [Misc] Add dynamic ordering to non-phase interactions (#6581) * Update interactions to use generator * Fix triggerWeatherBasedFormChanges * Update documentation * Fix arena tag file * Update src/field/pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com> --- src/battle-scene.ts | 4 ++ src/data/abilities/ability.ts | 18 ++++---- src/data/arena-tag.ts | 28 +++++++----- src/data/moves/move.ts | 16 ++++--- src/field/arena.ts | 45 +++++++++---------- src/field/pokemon.ts | 60 +++++++++++++------------ src/modifier/modifier.ts | 4 +- src/phases/attempt-run-phase.ts | 10 ++--- src/phases/check-status-effect-phase.ts | 7 +-- src/phases/faint-phase.ts | 5 ++- src/phases/field-phase.ts | 5 ++- src/phases/move-phase.ts | 15 ++++--- src/phases/mystery-encounter-phases.ts | 10 +++-- src/phases/post-summon-phase.ts | 3 +- src/phases/stat-stage-change-phase.ts | 2 +- src/phases/switch-summon-phase.ts | 8 ++-- src/utils/speed-order.ts | 11 +++-- 17 files changed, 137 insertions(+), 114 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index cc02f7e7ba5..e2dee543c47 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -803,6 +803,10 @@ export class BattleScene extends SceneBase { * @param activeOnly - Whether to consider only active pokemon (as described by {@linkcode Pokemon.isActive()}); default `false`. * If `true`, will also remove all `null` values from the array. * @returns An array of {@linkcode Pokemon}, as described above. + * + * @remarks + * This should *only* be used in instances where speed order is not relevant. + * If speed order matters, use {@linkcode inSpeedOrder}. */ public getField(activeOnly = false): Pokemon[] { const ret: Pokemon[] = new Array(4).fill(null); diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index f3eb6244bce..8d1356ade07 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -66,6 +66,7 @@ import type { Constructor } from "#types/common"; import type { Closed, Exact } from "#types/type-helpers"; import { coerceArray } from "#utils/array"; import { BooleanHolder, NumberHolder, randSeedFloat, randSeedInt, randSeedItem, toDmgValue } from "#utils/common"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import { toCamelCase } from "#utils/strings"; import i18next from "i18next"; @@ -2857,7 +2858,7 @@ export class PostSummonStatStageChangeAbAttr extends PostSummonAbAttr { return; } - for (const opponent of pokemon.getOpponents()) { + for (const opponent of pokemon.getOpponentsGenerator()) { const cancelled = new BooleanHolder(false); if (this.intimidate) { const params: AbAttrParamsWithCancel = { pokemon: opponent, cancelled, simulated }; @@ -3168,10 +3169,8 @@ export class PostSummonUserFieldRemoveStatusEffectAbAttr extends PostSummonAbAtt if (simulated) { return; } - const party = pokemon.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); - const allowedParty = party.filter(p => p.isAllowedInBattle()); - for (const partyPokemon of allowedParty) { + for (const partyPokemon of pokemon.getAlliesGenerator()) { if (partyPokemon.status && this.statusEffect.includes(partyPokemon.status.effect)) { globalScene.phaseManager.queueMessage( getStatusEffectHealText(partyPokemon.status.effect, getPokemonNameWithAffix(partyPokemon)), @@ -4423,7 +4422,7 @@ export class FriskAbAttr extends PostSummonAbAttr { override apply({ simulated, pokemon }: AbAttrBaseParams): void { if (!simulated) { - for (const opponent of pokemon.getOpponents()) { + for (const opponent of pokemon.getOpponentsGenerator()) { globalScene.phaseManager.queueMessage( i18next.t("abilityTriggers:frisk", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), @@ -4992,7 +4991,7 @@ export class PostTurnHurtIfSleepingAbAttr extends PostTurnAbAttr { return; } - for (const opp of pokemon.getOpponents()) { + for (const opp of pokemon.getOpponentsGenerator()) { if ((opp.status?.effect !== StatusEffect.SLEEP && !opp.hasAbility(AbilityId.COMATOSE)) || opp.switchOutStatus) { continue; } @@ -5545,10 +5544,9 @@ export class PostFaintContactDamageAbAttr extends PostFaintAbAttr { } const cancelled = new BooleanHolder(false); - // TODO: This should be in speed order - globalScene - .getField(true) - .forEach(p => applyAbAttrs("FieldPreventExplosiveMovesAbAttr", { pokemon: p, cancelled, simulated })); + for (const p of inSpeedOrder(ArenaTagSide.BOTH)) { + applyAbAttrs("FieldPreventExplosiveMovesAbAttr", { pokemon: p, cancelled, simulated }); + } if (cancelled.value) { return false; diff --git a/src/data/arena-tag.ts b/src/data/arena-tag.ts index a552775a2ee..f8829ee4344 100644 --- a/src/data/arena-tag.ts +++ b/src/data/arena-tag.ts @@ -78,6 +78,7 @@ import type { } from "#types/arena-tags"; import type { Mutable } from "#types/type-helpers"; import { BooleanHolder, type NumberHolder, toDmgValue } from "#utils/common"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import i18next from "i18next"; /** Interface containing the serializable fields of ArenaTagData. */ @@ -247,7 +248,7 @@ export abstract class ArenaTag implements BaseArenaTag { /** * Helper function that retrieves the Pokemon affected. - * @returns An array containing all {@linkcode Pokemon} affected by this Tag. + * @returns An array containing all {@linkcode Pokemon} affected by this Tag, not in speed order. */ protected getAffectedPokemon(): Pokemon[] { switch (this.side) { @@ -1204,7 +1205,7 @@ export class GravityTag extends SerializableArenaTag { onAdd(quiet = false): void { super.onAdd(quiet); - globalScene.getField(true).forEach(pokemon => { + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { if (pokemon !== null) { pokemon.removeTag(BattlerTagType.FLOATING); pokemon.removeTag(BattlerTagType.TELEKINESIS); @@ -1212,7 +1213,7 @@ export class GravityTag extends SerializableArenaTag { pokemon.addTag(BattlerTagType.INTERRUPTED); } } - }); + } } } @@ -1237,10 +1238,13 @@ class TailwindTag extends SerializableArenaTag { onAdd(quiet = false): void { super.onAdd(quiet); + const source = this.getSourcePokemon(); - const field = this.getAffectedPokemon(); + if (source == null) { + return; + } - for (const pokemon of field) { + for (const pokemon of source.getAlliesGenerator()) { // Apply the CHARGED tag to party members with the WIND_POWER ability // TODO: This should not be handled here if (pokemon.hasAbility(AbilityId.WIND_POWER) && !pokemon.getTag(BattlerTagType.CHARGED)) { @@ -1346,11 +1350,11 @@ class FireGrassPledgeTag extends SerializableArenaTag { } override lapse(): boolean { - const field = this.getAffectedPokemon().filter( - pokemon => !pokemon.isOfType(PokemonType.FIRE, true, true) && !pokemon.switchOutStatus, - ); + for (const pokemon of inSpeedOrder(this.side)) { + if (pokemon.isOfType(PokemonType.FIRE) || pokemon.switchOutStatus) { + continue; + } - field.forEach(pokemon => { // "{pokemonNameWithAffix} was hurt by the sea of fire!" globalScene.phaseManager.queueMessage( i18next.t("arenaTag:fireGrassPledgeLapse", { @@ -1365,7 +1369,7 @@ class FireGrassPledgeTag extends SerializableArenaTag { CommonAnim.MAGMA_STORM, ); pokemon.damageAndUpdate(toDmgValue(pokemon.getMaxHp() / 8), { result: HitResult.INDIRECT }); - }); + } return super.lapse(); } @@ -1497,7 +1501,7 @@ export class SuppressAbilitiesTag extends SerializableArenaTag { if (pokemon) { this.playActivationMessage(pokemon); - for (const fieldPokemon of globalScene.getField(true)) { + for (const fieldPokemon of inSpeedOrder(ArenaTagSide.BOTH)) { if (fieldPokemon.id !== pokemon.id) { // TODO: investigate whether we can just remove the foreach and call `applyAbAttrs` directly, providing // the appropriate attributes (preLEaveField and IllusionBreak) @@ -1539,7 +1543,7 @@ export class SuppressAbilitiesTag extends SerializableArenaTag { this.#beingRemoved = true; super.onRemove(quiet); - for (const pokemon of globalScene.getField(true)) { + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { // There is only one pokemon with this attr on the field on removal, so its abilities are already active if (!pokemon.hasAbilityWithAttr("PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr", false)) { [true, false].forEach(passive => { diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 7c5198206ab..b32ed6bbee4 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -98,6 +98,7 @@ import { areAllies } from "#utils/pokemon-utils"; import { toCamelCase, toTitleCase } from "#utils/strings"; import i18next from "i18next"; import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils"; import type { ReadonlyGenericUint8Array } from "#types/typed-arrays"; @@ -1031,8 +1032,9 @@ export abstract class Move implements Localizable { aura.apply({pokemon: source, simulated, opponent: target, move: this, power}); } - const alliedField: Pokemon[] = source.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); - alliedField.forEach(p => applyAbAttrs("UserFieldMoveTypePowerBoostAbAttr", {pokemon: p, opponent: target, move: this, simulated, power})); + for (const p of source.getAlliesGenerator()) { + applyAbAttrs("UserFieldMoveTypePowerBoostAbAttr", {pokemon: p, opponent: target, move: this, simulated, power}); + } power.value *= typeChangeMovePowerMultiplier.value; @@ -6218,8 +6220,10 @@ export class RemoveAllSubstitutesAttr extends MoveEffectAttr { return false; } - globalScene.getField(true).forEach(pokemon => - pokemon.findAndRemoveTags(tag => tag.tagType === BattlerTagType.SUBSTITUTE)); + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { + pokemon.findAndRemoveTags(tag => tag.tagType === BattlerTagType.SUBSTITUTE); + } + return true; } } @@ -8156,7 +8160,9 @@ const failIfDampCondition: MoveConditionFunc = (user, target, move) => { // temporary workaround to prevent displaying the message during enemy command phase // TODO: either move this, or make the move condition func have a `simulated` param const simulated = globalScene.phaseManager.getCurrentPhase()?.is('EnemyCommandPhase'); - globalScene.getField(true).map(p=>applyAbAttrs("FieldPreventExplosiveMovesAbAttr", {pokemon: p, cancelled, simulated})); + for (const p of inSpeedOrder(ArenaTagSide.BOTH)) { + applyAbAttrs("FieldPreventExplosiveMovesAbAttr", {pokemon: p, cancelled, simulated}); + } // Queue a message if an ability prevented usage of the move if (!simulated && cancelled.value) { globalScene.phaseManager.queueMessage(i18next.t("moveTriggers:cannotUseMove", { pokemonName: getPokemonNameWithAffix(user), moveName: move.name })); diff --git a/src/field/arena.ts b/src/field/arena.ts index 18c6702e59f..468e6846d03 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -40,6 +40,7 @@ import type { Constructor } from "#types/common"; import type { AbstractConstructor } from "#types/type-helpers"; import { NumberHolder, randSeedInt } from "#utils/common"; import { getPokemonSpecies } from "#utils/pokemon-utils"; +import { inSpeedOrder } from "#utils/speed-order-generator"; export class Arena { public biomeType: BiomeId; @@ -358,15 +359,12 @@ export class Arena { globalScene.phaseManager.queueMessage(getWeatherClearMessage(oldWeatherType)!); // TODO: is this bang correct? } - globalScene - .getField(true) - .filter(p => p.isOnField()) - .map(pokemon => { - pokemon.findAndRemoveTags( - t => "weatherTypes" in t && !(t.weatherTypes as WeatherType[]).find(t => t === weather), - ); - applyAbAttrs("PostWeatherChangeAbAttr", { pokemon, weather }); - }); + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { + pokemon.findAndRemoveTags( + tag => "weatherTypes" in tag && !(tag.weatherTypes as WeatherType[]).find(t => t === weather), + ); + applyAbAttrs("PostWeatherChangeAbAttr", { pokemon, weather }); + } return true; } @@ -376,11 +374,11 @@ export class Arena { * @param source - The Pokemon causing the changes by removing itself from the field */ triggerWeatherBasedFormChanges(source?: Pokemon): void { - globalScene.getField(true).forEach(p => { + for (const p of inSpeedOrder(ArenaTagSide.BOTH)) { // TODO - This is a bandaid. Abilities leaving the field needs a better approach than // calling this method for every switch out that happens if (p === source) { - return; + continue; } const isCastformWithForecast = p.hasAbility(AbilityId.FORECAST) && p.species.speciesId === SpeciesId.CASTFORM; const isCherrimWithFlowerGift = p.hasAbility(AbilityId.FLOWER_GIFT) && p.species.speciesId === SpeciesId.CHERRIM; @@ -388,23 +386,23 @@ export class Arena { if (isCastformWithForecast || isCherrimWithFlowerGift) { globalScene.triggerPokemonFormChange(p, SpeciesFormChangeWeatherTrigger); } - }); + } } /** * Function to trigger all weather based form changes back into their normal forms */ triggerWeatherBasedFormChangesToNormal(): void { - globalScene.getField(true).forEach(p => { + for (const p of inSpeedOrder(ArenaTagSide.BOTH)) { const isCastformWithForecast = p.hasAbility(AbilityId.FORECAST, false, true) && p.species.speciesId === SpeciesId.CASTFORM; const isCherrimWithFlowerGift = p.hasAbility(AbilityId.FLOWER_GIFT, false, true) && p.species.speciesId === SpeciesId.CHERRIM; if (isCastformWithForecast || isCherrimWithFlowerGift) { - return globalScene.triggerPokemonFormChange(p, SpeciesFormChangeRevertWeatherFormTrigger); + globalScene.triggerPokemonFormChange(p, SpeciesFormChangeRevertWeatherFormTrigger); } - }); + } } /** Returns whether or not the terrain can be set to {@linkcode terrain} */ @@ -453,16 +451,13 @@ export class Arena { globalScene.phaseManager.queueMessage(getTerrainClearMessage(oldTerrainType)); } - globalScene - .getField(true) - .filter(p => p.isOnField()) - .map(pokemon => { - pokemon.findAndRemoveTags( - t => "terrainTypes" in t && !(t.terrainTypes as TerrainType[]).find(t => t === terrain), - ); - applyAbAttrs("PostTerrainChangeAbAttr", { pokemon, terrain }); - applyAbAttrs("TerrainEventTypeChangeAbAttr", { pokemon }); - }); + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { + pokemon.findAndRemoveTags( + t => "terrainTypes" in t && !(t.terrainTypes as TerrainType[]).find(t => t === terrain), + ); + applyAbAttrs("PostTerrainChangeAbAttr", { pokemon, terrain }); + applyAbAttrs("TerrainEventTypeChangeAbAttr", { pokemon }); + } return true; } diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 61c5b62c835..5d50865798e 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -173,6 +173,7 @@ import { import { calculateBossSegmentDamage } from "#utils/damage"; import { getEnumValues } from "#utils/enums"; import { getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import { argbFromRgba, QuantizerCelebi, rgbaFromArgb } from "@material/material-color-utilities"; import i18next from "i18next"; import Phaser from "phaser"; @@ -2347,15 +2348,14 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { /** Holds whether the pokemon is trapped due to an ability */ const trapped = new BooleanHolder(false); - /** - * Contains opposing Pokemon (Enemy/Player Pokemon) depending on perspective - * Afterwards, it filters out Pokemon that have been switched out of the field so trapped abilities/moves do not trigger - */ - const opposingFieldUnfiltered = this.isPlayer() ? globalScene.getEnemyField() : globalScene.getPlayerField(); - const opposingField = opposingFieldUnfiltered.filter(enemyPkm => enemyPkm.switchOutStatus === false); - - for (const opponent of opposingField) { - applyAbAttrs("CheckTrappedAbAttr", { pokemon: opponent, trapped, opponent: this, simulated }, trappedAbMessages); + for (const opponent of inSpeedOrder(this.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER)) { + if (opponent.switchOutStatus === false) { + applyAbAttrs( + "CheckTrappedAbAttr", + { pokemon: opponent, trapped, opponent: this, simulated }, + trappedAbMessages, + ); + } } const side = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; @@ -2468,8 +2468,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { // Do not check queenly majesty unless this is being simulated // This is because the move effect phase should not check queenly majesty, as that is handled by the move phase if (simulated && !cancelledHolder.value) { - const defendingSidePlayField = this.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); - defendingSidePlayField.forEach((p: (typeof defendingSidePlayField)[0]) => { + for (const p of this.getAlliesGenerator()) { applyAbAttrs("FieldPriorityMoveImmunityAbAttr", { pokemon: p, opponent: source, @@ -2477,7 +2476,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { cancelled: cancelledHolder, simulated, }); - }); + } } } @@ -3243,7 +3242,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * Returns the pokemon that oppose this one and are active + * Returns the pokemon that oppose this one and are active in non-speed order * * @param onField - whether to also check if the pokemon is currently on the field (defaults to true) */ @@ -3253,6 +3252,13 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { ); } + /** + * @returns A generator of pokemon that oppose this one in speed order + */ + public getOpponentsGenerator(): Generator { + return inSpeedOrder(this.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER); + } + getOpponentDescriptor(): string { return this.isPlayer() ? i18next.t("arenaTag:opposingTeam") : i18next.t("arenaTag:yourTeam"); } @@ -3262,12 +3268,10 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { } /** - * Gets the Pokémon on the allied field. - * - * @returns An array of Pokémon on the allied field. + * @returns A generator of Pokémon on the allied field in speed order. */ - getAlliedField(): Pokemon[] { - return this.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); + getAlliesGenerator(): Generator { + return inSpeedOrder(this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY); } /** @@ -4020,16 +4024,15 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { const cancelled = new BooleanHolder(false); applyAbAttrs("BattlerTagImmunityAbAttr", { pokemon: this, tag: stubTag, cancelled, simulated: true }); - const userField = this.getAlliedField(); - userField.forEach(pokemon => + for (const pokemon of this.getAlliesGenerator()) { applyAbAttrs("UserFieldBattlerTagImmunityAbAttr", { pokemon, tag: stubTag, cancelled, simulated: true, target: this, - }), - ); + }); + } return !cancelled.value; } @@ -4063,7 +4066,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { return false; } - for (const pokemon of this.getAlliedField()) { + for (const pokemon of this.getAlliesGenerator()) { applyAbAttrs("UserFieldBattlerTagImmunityAbAttr", { pokemon, tag: newTag, cancelled, target: this }); if (cancelled.value) { return false; @@ -4811,7 +4814,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { return false; } - for (const pokemon of this.getAlliedField()) { + for (const pokemon of this.getAlliesGenerator()) { applyAbAttrs("UserFieldStatusEffectImmunityAbAttr", { pokemon, effect, @@ -5619,10 +5622,11 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { leaveField(clearEffects = true, hideInfo = true, destroy = false) { this.resetSprite(); this.resetTurnData(); - globalScene - .getField(true) - .filter(p => p !== this) - .forEach(p => p.removeTagsBySourceId(this.id)); + for (const p of inSpeedOrder(ArenaTagSide.BOTH)) { + if (p !== this) { + p.removeTagsBySourceId(this.id); + } + } if (clearEffects) { this.destroySubstitute(); diff --git a/src/modifier/modifier.ts b/src/modifier/modifier.ts index 3c5b96204ba..cefe8c9367a 100644 --- a/src/modifier/modifier.ts +++ b/src/modifier/modifier.ts @@ -1915,9 +1915,7 @@ export class PokemonInstantReviveModifier extends PokemonHeldItemModifier { // Remove the Pokemon's FAINT status pokemon.resetStatus(true, false, true, false); - // Reapply Commander on the Pokemon's side of the field, if applicable - const field = pokemon.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); - for (const p of field) { + for (const p of pokemon.getAlliesGenerator()) { applyAbAttrs("CommanderAbAttr", { pokemon: p }); } return true; diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index e8212a27243..c43c92ea860 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -1,10 +1,12 @@ import { applyAbAttrs } from "#abilities/apply-ab-attrs"; import { globalScene } from "#app/global-scene"; import Overrides from "#app/overrides"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { Stat } from "#enums/stat"; import { StatusEffect } from "#enums/status-effect"; import { FieldPhase } from "#phases/field-phase"; import { NumberHolder } from "#utils/common"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import i18next from "i18next"; export class AttemptRunPhase extends FieldPhase { @@ -15,16 +17,14 @@ export class AttemptRunPhase extends FieldPhase { // Increment escape attempts count on entry const currentAttempts = globalScene.currentBattle.escapeAttempts++; - - const activePlayerField = globalScene.getPlayerField(true); const enemyField = globalScene.getEnemyField(); const escapeRoll = globalScene.randBattleSeedInt(100); const escapeChance = new NumberHolder(this.calculateEscapeChance(currentAttempts)); - activePlayerField.forEach(pokemon => { + for (const pokemon of inSpeedOrder(ArenaTagSide.PLAYER)) { applyAbAttrs("RunSuccessAbAttr", { pokemon, chance: escapeChance }); - }); + } if (escapeRoll < escapeChance.value) { enemyField.forEach(pokemon => applyAbAttrs("PreLeaveFieldAbAttr", { pokemon })); @@ -56,7 +56,7 @@ export class AttemptRunPhase extends FieldPhase { globalScene.phaseManager.pushNew("NewBattlePhase"); } else { - activePlayerField.forEach(p => { + globalScene.getPlayerField(true).forEach(p => { p.turnData.failedRunAway = true; }); diff --git a/src/phases/check-status-effect-phase.ts b/src/phases/check-status-effect-phase.ts index 5955cd42c55..6a810d68c23 100644 --- a/src/phases/check-status-effect-phase.ts +++ b/src/phases/check-status-effect-phase.ts @@ -1,13 +1,14 @@ import { globalScene } from "#app/global-scene"; import { Phase } from "#app/phase"; +import { ArenaTagSide } from "#enums/arena-tag-side"; +import { inSpeedOrder } from "#utils/speed-order-generator"; export class CheckStatusEffectPhase extends Phase { public readonly phaseName = "CheckStatusEffectPhase"; start() { - const field = globalScene.getField(); - for (const p of field) { - if (p?.status?.isPostTurn()) { + for (const p of inSpeedOrder(ArenaTagSide.BOTH)) { + if (p.status?.isPostTurn()) { globalScene.phaseManager.unshiftNew("PostTurnStatusEffectPhase", p.getBattlerIndex()); } } diff --git a/src/phases/faint-phase.ts b/src/phases/faint-phase.ts index 821d16c6546..4762d39420c 100644 --- a/src/phases/faint-phase.ts +++ b/src/phases/faint-phase.ts @@ -5,6 +5,7 @@ import { FRIENDSHIP_LOSS_FROM_FAINT } from "#balance/starters"; import { allMoves } from "#data/data-lists"; import { battleSpecDialogue } from "#data/dialogue"; import { SpeciesFormChangeActiveTrigger } from "#data/form-change-triggers"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { BattleSpec } from "#enums/battle-spec"; import { BattleType } from "#enums/battle-type"; import type { BattlerIndex } from "#enums/battler-index"; @@ -17,6 +18,7 @@ import type { EnemyPokemon, PlayerPokemon, Pokemon } from "#field/pokemon"; import { PokemonInstantReviveModifier } from "#modifiers/modifier"; import { PokemonMove } from "#moves/pokemon-move"; import { PokemonPhase } from "#phases/pokemon-phase"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import i18next from "i18next"; export class FaintPhase extends PokemonPhase { @@ -126,8 +128,7 @@ export class FaintPhase extends PokemonPhase { applyAbAttrs("PostFaintAbAttr", { pokemon }); } - const alivePlayField = globalScene.getField(true); - for (const p of alivePlayField) { + for (const p of inSpeedOrder(ArenaTagSide.BOTH)) { applyAbAttrs("PostKnockOutAbAttr", { pokemon: p, victim: pokemon }); } if (pokemon.turnData.attacksReceived?.length > 0) { diff --git a/src/phases/field-phase.ts b/src/phases/field-phase.ts index 99de3d9fcf5..03b9c63a7cd 100644 --- a/src/phases/field-phase.ts +++ b/src/phases/field-phase.ts @@ -1,12 +1,13 @@ -import { globalScene } from "#app/global-scene"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import type { Pokemon } from "#field/pokemon"; import { BattlePhase } from "#phases/battle-phase"; +import { inSpeedOrder } from "#utils/speed-order-generator"; type PokemonFunc = (pokemon: Pokemon) => void; export abstract class FieldPhase extends BattlePhase { executeForAll(func: PokemonFunc): void { - for (const pokemon of globalScene.getField(true)) { + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { func(pokemon); } } diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index c18065e061e..6350791e9bb 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -13,6 +13,7 @@ import { getStatusEffectActivationText } from "#data/status-effect"; import { getTerrainBlockMessage } from "#data/terrain"; import { getWeatherBlockMessage } from "#data/weather"; import { AbilityId } from "#enums/ability-id"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { ArenaTagType } from "#enums/arena-tag-type"; import { BattlerIndex } from "#enums/battler-index"; import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; @@ -35,6 +36,7 @@ import type { TurnMove } from "#types/turn-move"; import { applyChallenges } from "#utils/challenge-utils"; import { BooleanHolder, NumberHolder } from "#utils/common"; import { enumValueToKey } from "#utils/enums"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import i18next from "i18next"; export class MovePhase extends PokemonPhase { @@ -321,17 +323,16 @@ export class MovePhase extends PokemonPhase { // check move redirection abilities of every pokemon *except* the user. // TODO: Make storm drain, lightning rod, etc, redirect at this point for type changing moves - globalScene - .getField(true) - .filter(p => p !== this.pokemon) - .forEach(pokemon => { + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { + if (pokemon !== this.pokemon) { applyAbAttrs("RedirectMoveAbAttr", { pokemon, moveId: this.move.moveId, targetIndex: redirectTarget, sourcePokemon: this.pokemon, }); - }); + } + } /** `true` if an Ability is responsible for redirecting the move to another target; `false` otherwise */ let redirectedByAbility = currentTarget !== redirectTarget.value; @@ -848,9 +849,9 @@ export class MovePhase extends PokemonPhase { // TODO: This needs to go at the end of `MoveEffectPhase` to check move results const dancerModes: MoveUseMode[] = [MoveUseMode.INDIRECT, MoveUseMode.REFLECTED] as const; if (this.move.getMove().hasFlag(MoveFlags.DANCE_MOVE) && !dancerModes.includes(this.useMode)) { - globalScene.getField(true).forEach(pokemon => { + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { applyAbAttrs("PostMoveUsedAbAttr", { pokemon, move: this.move, source: user, targets }); - }); + } } } diff --git a/src/phases/mystery-encounter-phases.ts b/src/phases/mystery-encounter-phases.ts index 39b1d1c5667..77fc09fe677 100644 --- a/src/phases/mystery-encounter-phases.ts +++ b/src/phases/mystery-encounter-phases.ts @@ -1,6 +1,7 @@ import { globalScene } from "#app/global-scene"; import { Phase } from "#app/phase"; import { getCharVariantFromDialogue } from "#data/dialogue"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { BattleSpec } from "#enums/battle-spec"; import { BattlerTagLapseType } from "#enums/battler-tag-lapse-type"; import { BattlerTagType } from "#enums/battler-tag-type"; @@ -15,6 +16,7 @@ import { transitionMysteryEncounterIntroVisuals } from "#mystery-encounters/enco import type { MysteryEncounterOption, OptionPhaseCallback } from "#mystery-encounters/mystery-encounter-option"; import { SeenEncounterData } from "#mystery-encounters/mystery-encounter-save-data"; import { randSeedItem } from "#utils/common"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import i18next from "i18next"; /** @@ -216,7 +218,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase { // Lapse any residual flinches/endures but ignore all other turn-end battle tags const includedLapseTags = [BattlerTagType.FLINCHED, BattlerTagType.ENDURING]; - globalScene.getField(true).forEach(pokemon => { + for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { const tags = pokemon.summonData.tags; tags .filter( @@ -229,7 +231,7 @@ export class MysteryEncounterBattleStartCleanupPhase extends Phase { t.onRemove(pokemon); tags.splice(tags.indexOf(t), 1); }); - }); + } // Remove any status tick phases globalScene.phaseManager.removeAllPhasesOfType("PostTurnStatusEffectPhase"); @@ -427,7 +429,9 @@ export class MysteryEncounterBattlePhase extends Phase { } } else { if (availablePartyMembers.length > 1 && availablePartyMembers[1].isOnField()) { - globalScene.getPlayerField().forEach(pokemon => pokemon.lapseTag(BattlerTagType.COMMANDED)); + for (const pokemon of inSpeedOrder(ArenaTagSide.PLAYER)) { + pokemon.lapseTag(BattlerTagType.COMMANDED); + } globalScene.phaseManager.pushNew("ReturnPhase", 1); } globalScene.phaseManager.pushNew("ToggleDoublePositionPhase", false); diff --git a/src/phases/post-summon-phase.ts b/src/phases/post-summon-phase.ts index a985c629b7a..72dcb058be7 100644 --- a/src/phases/post-summon-phase.ts +++ b/src/phases/post-summon-phase.ts @@ -30,8 +30,7 @@ export class PostSummonPhase extends PokemonPhase { ) { pokemon.lapseTag(BattlerTagType.MYSTERY_ENCOUNTER_POST_SUMMON); } - const field = pokemon.isPlayer() ? globalScene.getPlayerField(true) : globalScene.getEnemyField(true); - for (const p of field) { + for (const p of pokemon.getAlliesGenerator()) { applyAbAttrs("CommanderAbAttr", { pokemon: p }); } diff --git a/src/phases/stat-stage-change-phase.ts b/src/phases/stat-stage-change-phase.ts index d89a1817f32..71d9f2a126a 100644 --- a/src/phases/stat-stage-change-phase.ts +++ b/src/phases/stat-stage-change-phase.ts @@ -210,7 +210,7 @@ export class StatStageChangePhase extends PokemonPhase { } if (stages.value > 0 && this.canBeCopied) { - for (const opponent of pokemon.getOpponents()) { + for (const opponent of pokemon.getOpponentsGenerator()) { applyAbAttrs("StatStageChangeCopyAbAttr", { pokemon: opponent, stats: this.stats, numStages: stages.value }); } } diff --git a/src/phases/switch-summon-phase.ts b/src/phases/switch-summon-phase.ts index 8cc7843b55f..9ccc3cc573e 100644 --- a/src/phases/switch-summon-phase.ts +++ b/src/phases/switch-summon-phase.ts @@ -5,12 +5,14 @@ import { SubstituteTag } from "#data/battler-tags"; import { allMoves } from "#data/data-lists"; import { SpeciesFormChangeActiveTrigger } from "#data/form-change-triggers"; import { getPokeballTintColor } from "#data/pokeball"; +import { ArenaTagSide } from "#enums/arena-tag-side"; import { Command } from "#enums/command"; import { SwitchType } from "#enums/switch-type"; import { TrainerSlot } from "#enums/trainer-slot"; import type { Pokemon } from "#field/pokemon"; import { SwitchEffectTransferModifier } from "#modifiers/modifier"; import { SummonPhase } from "#phases/summon-phase"; +import { inSpeedOrder } from "#utils/speed-order-generator"; import i18next from "i18next"; export class SwitchSummonPhase extends SummonPhase { @@ -69,9 +71,9 @@ export class SwitchSummonPhase extends SummonPhase { } const pokemon = this.getPokemon(); - (this.player ? globalScene.getEnemyField() : globalScene.getPlayerField()).forEach(enemyPokemon => - enemyPokemon.removeTagsBySourceId(pokemon.id), - ); + for (const enemyPokemon of inSpeedOrder(this.player ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER)) { + enemyPokemon.removeTagsBySourceId(pokemon.id); + } if (this.switchType === SwitchType.SWITCH || this.switchType === SwitchType.INITIAL_SWITCH) { const substitute = pokemon.getTag(SubstituteTag); diff --git a/src/utils/speed-order.ts b/src/utils/speed-order.ts index 8a671ed7830..f2733a74998 100644 --- a/src/utils/speed-order.ts +++ b/src/utils/speed-order.ts @@ -1,4 +1,4 @@ -import { Pokemon } from "#app/field/pokemon"; +import type { Pokemon } from "#app/field/pokemon"; import { globalScene } from "#app/global-scene"; import { BooleanHolder, randSeedShuffle } from "#app/utils/common"; import { ArenaTagType } from "#enums/arena-tag-type"; @@ -39,11 +39,16 @@ function shufflePokemonList(pokemonList: T[]): T return pokemonList; } +/** Type guard for {@linkcode sortBySpeed} to avoid importing {@linkcode Pokemon} */ +function isPokemon(p: Pokemon | hasPokemon): p is Pokemon { + return typeof (p as hasPokemon).getPokemon !== "function"; +} + /** Sorts an array of {@linkcode Pokemon} by speed (without shuffling) */ function sortBySpeed(pokemonList: T[]): void { pokemonList.sort((a, b) => { - const aSpeed = (a instanceof Pokemon ? a : a.getPokemon()).getEffectiveStat(Stat.SPD); - const bSpeed = (b instanceof Pokemon ? b : b.getPokemon()).getEffectiveStat(Stat.SPD); + const aSpeed = (isPokemon(a) ? a : a.getPokemon()).getEffectiveStat(Stat.SPD); + const bSpeed = (isPokemon(b) ? b : b.getPokemon()).getEffectiveStat(Stat.SPD); return bSpeed - aSpeed; }); From 3c41b2604536eaad37e3ff5d97d2159e549fb254 Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Wed, 29 Oct 2025 05:23:03 -0400 Subject: [PATCH 06/58] [Bug] Sheer Force now disables Wimp Out, Emergency Exit (#6692) --- src/data/abilities/ability.ts | 42 +++++++++++++++++------------------ 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 8d1356ade07..301016d899b 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -4213,28 +4213,26 @@ export class SuppressWeatherEffectAbAttr extends PreWeatherEffectAbAttr { /** * Condition function to applied to abilities related to Sheer Force. * Checks if last move used against target was affected by a Sheer Force user and: - * Disables: Color Change, Pickpocket, Berserk, Anger Shell + * Disables: Color Change, Pickpocket, Berserk, Anger Shell, Wimp Out, Emergency Exit * @returns An {@linkcode AbAttrCondition} to disable the ability under the proper conditions. */ -function getSheerForceHitDisableAbCondition(): AbAttrCondition { - return (pokemon: Pokemon) => { - const lastReceivedAttack = pokemon.turnData.attacksReceived[0]; - if (!lastReceivedAttack) { - return true; - } +const sheerForceHitDisableAbCondition: AbAttrCondition = (pokemon: Pokemon) => { + const lastReceivedAttack = pokemon.turnData.attacksReceived[0]; + if (!lastReceivedAttack) { + return true; + } - const lastAttacker = pokemon.getOpponents().find(p => p.id === lastReceivedAttack.sourceId); - if (!lastAttacker) { - return true; - } + const lastAttacker = pokemon.getOpponents().find(p => p.id === lastReceivedAttack.sourceId); + if (!lastAttacker) { + return true; + } - /** `true` if the last move's chance is above 0 and the last attacker's ability is sheer force */ - const SheerForceAffected = - allMoves[lastReceivedAttack.move].chance >= 0 && lastAttacker.hasAbility(AbilityId.SHEER_FORCE); + /** `true` if the last move's chance is above 0 and the last attacker's ability is sheer force */ + const sheerForceAffected = + allMoves[lastReceivedAttack.move].chance >= 0 && lastAttacker.hasAbility(AbilityId.SHEER_FORCE); - return !SheerForceAffected; - }; -} + return !sheerForceAffected; +}; function getWeatherCondition(...weatherTypes: WeatherType[]): AbAttrCondition { return () => { @@ -6906,7 +6904,7 @@ export function initAbilities() { .build(), new AbBuilder(AbilityId.COLOR_CHANGE, 3) .attr(PostDefendTypeChangeAbAttr) - .condition(getSheerForceHitDisableAbCondition()) + .condition(sheerForceHitDisableAbCondition) .build(), new AbBuilder(AbilityId.IMMUNITY, 3) .attr(StatusEffectImmunityAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) @@ -7342,7 +7340,7 @@ export function initAbilities() { .build(), new AbBuilder(AbilityId.PICKPOCKET, 5) .attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user, target})) - .condition(getSheerForceHitDisableAbCondition()) + .condition(sheerForceHitDisableAbCondition) .build(), new AbBuilder(AbilityId.SHEER_FORCE, 5) .attr(MovePowerBoostAbAttr, (_user, _target, move) => move.chance >= 1, 1.3) @@ -7656,10 +7654,12 @@ export function initAbilities() { .build(), new AbBuilder(AbilityId.WIMP_OUT, 7) .attr(PostDamageForceSwitchAbAttr) + .condition(sheerForceHitDisableAbCondition) .edgeCase() // Should not trigger when hurting itself in confusion, causes Fake Out to fail turn 1 and succeed turn 2 if pokemon is switched out before battle start via playing in Switch Mode .build(), new AbBuilder(AbilityId.EMERGENCY_EXIT, 7) .attr(PostDamageForceSwitchAbAttr) + .condition(sheerForceHitDisableAbCondition) .edgeCase() // Should not trigger when hurting itself in confusion, causes Fake Out to fail turn 1 and succeed turn 2 if pokemon is switched out before battle start via playing in Switch Mode .build(), new AbBuilder(AbilityId.WATER_COMPACTION, 7) @@ -7699,7 +7699,7 @@ export function initAbilities() { .build(), new AbBuilder(AbilityId.BERSERK, 7) .attr(PostDefendHpGatedStatStageChangeAbAttr, (_target, _user, move) => move.category !== MoveCategory.STATUS, 0.5, [ Stat.SPATK ], 1) - .condition(getSheerForceHitDisableAbCondition()) + .condition(sheerForceHitDisableAbCondition) .build(), new AbBuilder(AbilityId.SLUSH_RUSH, 7) .attr(StatMultiplierAbAttr, Stat.SPD, 2) @@ -8059,7 +8059,7 @@ export function initAbilities() { new AbBuilder(AbilityId.ANGER_SHELL, 9) .attr(PostDefendHpGatedStatStageChangeAbAttr, (_target, _user, move) => move.category !== MoveCategory.STATUS, 0.5, [ Stat.ATK, Stat.SPATK, Stat.SPD ], 1) .attr(PostDefendHpGatedStatStageChangeAbAttr, (_target, _user, move) => move.category !== MoveCategory.STATUS, 0.5, [ Stat.DEF, Stat.SPDEF ], -1) - .condition(getSheerForceHitDisableAbCondition()) + .condition(sheerForceHitDisableAbCondition) .build(), new AbBuilder(AbilityId.PURIFYING_SALT, 9) .attr(StatusEffectImmunityAbAttr) From a66f183a30788c68a44237b352f5898e3d0dd632 Mon Sep 17 00:00:00 2001 From: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Date: Wed, 29 Oct 2025 11:20:52 +0100 Subject: [PATCH 07/58] [Bug] Show ribbons for forms of evolutions (#6708) --- src/utils/ribbon-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/ribbon-utils.ts b/src/utils/ribbon-utils.ts index 774ae26a0a6..f45cfef80d8 100644 --- a/src/utils/ribbon-utils.ts +++ b/src/utils/ribbon-utils.ts @@ -65,7 +65,7 @@ export function getAvailableRibbons(species: PokemonSpecies): RibbonFlag[] { data |= getRibbonForType(checkingSpecies.type2); } - for (const form of species.forms) { + for (const form of checkingSpecies.forms) { data |= getRibbonForType(form.type1); if (form.type2 != null) { data |= getRibbonForType(form.type2); From 9e96380bc0525dc8260506e7f10f26b1387c2e95 Mon Sep 17 00:00:00 2001 From: damocleas Date: Wed, 29 Oct 2025 10:56:15 -0400 Subject: [PATCH 08/58] [Beta] Add Ribbon Sprites over stuff (#6704) * ribbons * Remove now-unused comments * Update achv.ts --- src/system/achv.ts | 40 +++++++++---------- src/system/ribbons/ribbon-methods.ts | 57 +++++++++++++++++++++------- 2 files changed, 63 insertions(+), 34 deletions(-) diff --git a/src/system/achv.ts b/src/system/achv.ts index 1a66dc83878..5c714c36ee6 100644 --- a/src/system/achv.ts +++ b/src/system/achv.ts @@ -458,7 +458,7 @@ export const achvs = { CLASSIC_VICTORY: new Achv( "classicVictory", "classicVictory.description", - "relic_crown", + "classic_ribbon_default", 250, _ => globalScene.gameData.gameStats.sessionsWon === 0, ), @@ -483,7 +483,7 @@ export const achvs = { LV_250: new LevelAchv("lv250", 250, "rarer_candy", 25).setSecret(true), LV_1000: new LevelAchv("lv1000", 1000, "candy_jar", 50).setSecret(true), TRANSFER_MAX_STAT_STAGE: new Achv("transferMaxStatStage", "transferMaxStatStage.description", "baton", 25), - MAX_FRIENDSHIP: new Achv("maxFriendship", "maxFriendship.description", "soothe_bell", 25), + MAX_FRIENDSHIP: new Achv("maxFriendship", "maxFriendship.description", "ribbon_friendship", 25), MEGA_EVOLVE: new Achv("megaEvolve", "megaEvolve.description", "mega_bracelet", 50), GIGANTAMAX: new Achv("gigantamax", "gigantamax.description", "dynamax_band", 50), TERASTALLIZE: new Achv("terastallize", "terastallize.description", "tera_orb", 25), @@ -651,7 +651,7 @@ export const achvs = { MONO_NORMAL: new ChallengeAchv( "monoNormal", "monoNormal.description", - "silk_scarf", + "ribbon_normal", 100, c => c instanceof SingleTypeChallenge @@ -663,7 +663,7 @@ export const achvs = { MONO_FIGHTING: new ChallengeAchv( "monoFighting", "monoFighting.description", - "black_belt", + "ribbon_fighting", 100, c => c instanceof SingleTypeChallenge @@ -675,7 +675,7 @@ export const achvs = { MONO_FLYING: new ChallengeAchv( "monoFlying", "monoFlying.description", - "sharp_beak", + "ribbon_flying", 100, c => c instanceof SingleTypeChallenge @@ -687,7 +687,7 @@ export const achvs = { MONO_POISON: new ChallengeAchv( "monoPoison", "monoPoison.description", - "poison_barb", + "ribbon_poison", 100, c => c instanceof SingleTypeChallenge @@ -699,7 +699,7 @@ export const achvs = { MONO_GROUND: new ChallengeAchv( "monoGround", "monoGround.description", - "soft_sand", + "ribbon_ground", 100, c => c instanceof SingleTypeChallenge @@ -711,7 +711,7 @@ export const achvs = { MONO_ROCK: new ChallengeAchv( "monoRock", "monoRock.description", - "hard_stone", + "ribbon_rock", 100, c => c instanceof SingleTypeChallenge @@ -723,7 +723,7 @@ export const achvs = { MONO_BUG: new ChallengeAchv( "monoBug", "monoBug.description", - "silver_powder", + "ribbon_bug", 100, c => c instanceof SingleTypeChallenge @@ -735,7 +735,7 @@ export const achvs = { MONO_GHOST: new ChallengeAchv( "monoGhost", "monoGhost.description", - "spell_tag", + "ribbon_ghost", 100, c => c instanceof SingleTypeChallenge @@ -747,7 +747,7 @@ export const achvs = { MONO_STEEL: new ChallengeAchv( "monoSteel", "monoSteel.description", - "metal_coat", + "ribbon_steel", 100, c => c instanceof SingleTypeChallenge @@ -759,7 +759,7 @@ export const achvs = { MONO_FIRE: new ChallengeAchv( "monoFire", "monoFire.description", - "charcoal", + "ribbon_fire", 100, c => c instanceof SingleTypeChallenge @@ -771,7 +771,7 @@ export const achvs = { MONO_WATER: new ChallengeAchv( "monoWater", "monoWater.description", - "mystic_water", + "ribbon_water", 100, c => c instanceof SingleTypeChallenge @@ -783,7 +783,7 @@ export const achvs = { MONO_GRASS: new ChallengeAchv( "monoGrass", "monoGrass.description", - "miracle_seed", + "ribbon_grass", 100, c => c instanceof SingleTypeChallenge @@ -795,7 +795,7 @@ export const achvs = { MONO_ELECTRIC: new ChallengeAchv( "monoElectric", "monoElectric.description", - "magnet", + "ribbon_electric", 100, c => c instanceof SingleTypeChallenge @@ -807,7 +807,7 @@ export const achvs = { MONO_PSYCHIC: new ChallengeAchv( "monoPsychic", "monoPsychic.description", - "twisted_spoon", + "ribbon_psychic", 100, c => c instanceof SingleTypeChallenge @@ -819,7 +819,7 @@ export const achvs = { MONO_ICE: new ChallengeAchv( "monoIce", "monoIce.description", - "never_melt_ice", + "ribbon_ice", 100, c => c instanceof SingleTypeChallenge @@ -831,7 +831,7 @@ export const achvs = { MONO_DRAGON: new ChallengeAchv( "monoDragon", "monoDragon.description", - "dragon_fang", + "ribbon_dragon", 100, c => c instanceof SingleTypeChallenge @@ -843,7 +843,7 @@ export const achvs = { MONO_DARK: new ChallengeAchv( "monoDark", "monoDark.description", - "black_glasses", + "ribbon_dark", 100, c => c instanceof SingleTypeChallenge @@ -855,7 +855,7 @@ export const achvs = { MONO_FAIRY: new ChallengeAchv( "monoFairy", "monoFairy.description", - "fairy_feather", + "ribbon_fairy", 100, c => c instanceof SingleTypeChallenge diff --git a/src/system/ribbons/ribbon-methods.ts b/src/system/ribbons/ribbon-methods.ts index f86b52b9697..8d667e99bd0 100644 --- a/src/system/ribbons/ribbon-methods.ts +++ b/src/system/ribbons/ribbon-methods.ts @@ -22,8 +22,12 @@ export function ribbonFlagToAssetKey(flag: RibbonFlag): Phaser.GameObjects.Sprit let imageKey: string; switch (flag) { // biome-ignore-start lint/suspicious/noFallthroughSwitchClause: intentional + case RibbonData.CLASSIC: + imageKey ??= "classic_ribbon_default"; + case RibbonData.FRIENDSHIP: + imageKey ??= "ribbon_friendship"; case RibbonData.MONO_GEN_1: - imageKey = "ribbon_gen1"; + imageKey ??= "ribbon_gen1"; case RibbonData.MONO_GEN_2: imageKey ??= "ribbon_gen2"; case RibbonData.MONO_GEN_3: @@ -40,20 +44,45 @@ export function ribbonFlagToAssetKey(flag: RibbonFlag): Phaser.GameObjects.Sprit imageKey ??= "ribbon_gen8"; case RibbonData.MONO_GEN_9: imageKey ??= "ribbon_gen9"; + case RibbonData.MONO_NORMAL: + imageKey ??= "ribbon_normal"; + case RibbonData.MONO_FIGHTING: + imageKey ??= "ribbon_fighting"; + case RibbonData.MONO_FLYING: + imageKey ??= "ribbon_flying"; + case RibbonData.MONO_POISON: + imageKey ??= "ribbon_poison"; + case RibbonData.MONO_GROUND: + imageKey ??= "ribbon_ground"; + case RibbonData.MONO_ROCK: + imageKey ??= "ribbon_rock"; + case RibbonData.MONO_BUG: + imageKey ??= "ribbon_bug"; + case RibbonData.MONO_GHOST: + imageKey ??= "ribbon_ghost"; + case RibbonData.MONO_STEEL: + imageKey ??= "ribbon_steel"; + case RibbonData.MONO_FIRE: + imageKey ??= "ribbon_fire"; + case RibbonData.MONO_WATER: + imageKey ??= "ribbon_water"; + case RibbonData.MONO_GRASS: + imageKey ??= "ribbon_grass"; + case RibbonData.MONO_ELECTRIC: + imageKey ??= "ribbon_electric"; + case RibbonData.MONO_PSYCHIC: + imageKey ??= "ribbon_psychic"; + case RibbonData.MONO_ICE: + imageKey ??= "ribbon_ice"; + case RibbonData.MONO_DRAGON: + imageKey ??= "ribbon_dragon"; + case RibbonData.MONO_DARK: + imageKey ??= "ribbon_dark"; + case RibbonData.MONO_FAIRY: + imageKey ??= "ribbon_fairy"; + default: + imageKey ??= "ribbon_typeless"; return globalScene.add.image(0, 0, "items", imageKey).setDisplaySize(16, 16); // biome-ignore-end lint/suspicious/noFallthroughSwitchClause: done with fallthrough - // Ribbons that don't use the items atlas - // biome-ignore-start lint/suspicious/noFallthroughSwitchClause: Another fallthrough block - case RibbonData.NUZLOCKE: - imageKey = "champion_ribbon_emerald"; - default: - imageKey ??= "champion_ribbon"; - { - const img = globalScene.add.image(0, 0, imageKey); - const target = 12; - const scale = Math.min(target / img.width, target / img.height); - return img.setScale(scale); - } - // biome-ignore-end lint/suspicious/noFallthroughSwitchClause: End fallthrough block } } From 075679eba1f6b64600478858076a1b9739153001 Mon Sep 17 00:00:00 2001 From: damocleas Date: Wed, 29 Oct 2025 12:51:00 -0400 Subject: [PATCH 09/58] [Balance] More 1.11 stuff (#6680) * Update trash-to-treasure-encounter.test.ts * Update trash-to-treasure-encounter.ts * pain and suffering is lessened * rotom is just gonna be random now (arena.ts) * looked at biomes.ts a lot today, not a fan (of rotom, fan) * stares at weather.ts intensely (lots of small changes) * Update init-biomes, slight tweaks to encounters * yay so many more biome.ts please be the last until biome rework * oh I also changed dudunsparce and maushold to 1/16 to match the others * ok, biomes.ts one final I think * minor fixes for biomes.ts * Update init-biomes.ts * Adjust Minimum Party Size and Max Allowed Encounters for some ME's --- src/battle-scene.ts | 7 +- src/data/balance/biomes.ts | 391 ++++----- src/data/balance/init-biomes.ts | 739 ++++++++++-------- .../encounters/bug-type-superfan-encounter.ts | 2 + .../the-winstrate-challenge-encounter.ts | 2 + .../encounters/trash-to-treasure-encounter.ts | 87 ++- .../encounters/weird-dream-encounter.ts | 3 +- src/data/weather.ts | 44 +- src/field/arena.ts | 14 - .../trash-to-treasure-encounter.test.ts | 96 +-- 10 files changed, 751 insertions(+), 634 deletions(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index e2dee543c47..6c60a0caa20 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1625,6 +1625,7 @@ export class BattleScene extends SceneBase { case SpeciesId.UNOWN: case SpeciesId.SHELLOS: case SpeciesId.GASTRODON: + case SpeciesId.ROTOM: case SpeciesId.BASCULIN: case SpeciesId.DEERLING: case SpeciesId.SAWSBUCK: @@ -1644,11 +1645,10 @@ export class BattleScene extends SceneBase { case SpeciesId.TATSUGIRI: case SpeciesId.PALDEA_TAUROS: return randSeedInt(species.forms.length); - case SpeciesId.MAUSHOLD: - case SpeciesId.DUDUNSPARCE: - return !randSeedInt(4) ? 1 : 0; case SpeciesId.SINISTEA: case SpeciesId.POLTEAGEIST: + case SpeciesId.MAUSHOLD: + case SpeciesId.DUDUNSPARCE: case SpeciesId.POLTCHAGEIST: case SpeciesId.SINISTCHA: return !randSeedInt(16) ? 1 : 0; @@ -1718,7 +1718,6 @@ export class BattleScene extends SceneBase { switch (species.speciesId) { case SpeciesId.BURMY: case SpeciesId.WORMADAM: - case SpeciesId.ROTOM: case SpeciesId.LYCANROC: return randSeedInt(species.forms.length); } diff --git a/src/data/balance/biomes.ts b/src/data/balance/biomes.ts index 6e19581fec0..562c07396e0 100644 --- a/src/data/balance/biomes.ts +++ b/src/data/balance/biomes.ts @@ -51,6 +51,7 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.LEDYBA, SpeciesId.HOPPIP, SpeciesId.SUNKERN, + SpeciesId.SILCOON, SpeciesId.STARLY, SpeciesId.PIDOVE, SpeciesId.COTTONEE, @@ -61,6 +62,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ SpeciesId.CATERPIE, SpeciesId.SENTRET, + SpeciesId.LEDYBA, SpeciesId.HOPPIP, SpeciesId.SUNKERN, SpeciesId.SILCOON, @@ -71,20 +73,20 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.YUNGOOS, SpeciesId.SKWOVET ], - [TimeOfDay.DUSK]: [ SpeciesId.WEEDLE, SpeciesId.POOCHYENA, SpeciesId.PATRAT, SpeciesId.PURRLOIN, SpeciesId.BLIPBUG ], - [TimeOfDay.NIGHT]: [ SpeciesId.WEEDLE, SpeciesId.HOOTHOOT, SpeciesId.SPINARAK, SpeciesId.POOCHYENA, SpeciesId.CASCOON, SpeciesId.PATRAT, SpeciesId.PURRLOIN, SpeciesId.BLIPBUG ], - [TimeOfDay.ALL]: [ SpeciesId.PIDGEY, SpeciesId.RATTATA, SpeciesId.SPEAROW, SpeciesId.ZIGZAGOON, SpeciesId.WURMPLE, SpeciesId.TAILLOW, SpeciesId.BIDOOF, SpeciesId.LILLIPUP, SpeciesId.FLETCHLING, SpeciesId.WOOLOO, SpeciesId.LECHONK ] + [TimeOfDay.DUSK]: [ SpeciesId.WEEDLE, SpeciesId.HOOTHOOT, SpeciesId.SPINARAK, SpeciesId.POOCHYENA, SpeciesId.CASCOON, SpeciesId.PURRLOIN, SpeciesId.BLIPBUG ], + [TimeOfDay.NIGHT]: [ SpeciesId.WEEDLE, SpeciesId.HOOTHOOT, SpeciesId.SPINARAK, SpeciesId.POOCHYENA, SpeciesId.CASCOON, SpeciesId.PURRLOIN, SpeciesId.BLIPBUG ], + [TimeOfDay.ALL]: [ SpeciesId.PIDGEY, SpeciesId.RATTATA, SpeciesId.SPEAROW, SpeciesId.ZIGZAGOON, SpeciesId.WURMPLE, SpeciesId.TAILLOW, SpeciesId.BIDOOF, SpeciesId.PATRAT, SpeciesId.LILLIPUP, SpeciesId.FLETCHLING, SpeciesId.WOOLOO, SpeciesId.LECHONK ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.BELLSPROUT, SpeciesId.POOCHYENA, SpeciesId.LOTAD, SpeciesId.SKITTY, SpeciesId.COMBEE, SpeciesId.CHERUBI, SpeciesId.PATRAT, SpeciesId.MINCCINO, SpeciesId.PAWMI ], - [TimeOfDay.DAY]: [ SpeciesId.NIDORAN_F, SpeciesId.NIDORAN_M, SpeciesId.BELLSPROUT, SpeciesId.POOCHYENA, SpeciesId.LOTAD, SpeciesId.SKITTY, SpeciesId.COMBEE, SpeciesId.CHERUBI, SpeciesId.PATRAT, SpeciesId.MINCCINO, SpeciesId.PAWMI ], - [TimeOfDay.DUSK]: [ SpeciesId.EKANS, SpeciesId.ODDISH, SpeciesId.MEOWTH, SpeciesId.SPINARAK, SpeciesId.SEEDOT, SpeciesId.SHROOMISH, SpeciesId.KRICKETOT, SpeciesId.VENIPEDE ], - [TimeOfDay.NIGHT]: [ SpeciesId.EKANS, SpeciesId.ODDISH, SpeciesId.PARAS, SpeciesId.VENONAT, SpeciesId.MEOWTH, SpeciesId.SEEDOT, SpeciesId.SHROOMISH, SpeciesId.KRICKETOT, SpeciesId.VENIPEDE ], - [TimeOfDay.ALL]: [ SpeciesId.NINCADA, SpeciesId.WHISMUR, SpeciesId.FIDOUGH ] + [TimeOfDay.DAWN]: [ SpeciesId.NIDORAN_F, SpeciesId.NIDORAN_M, SpeciesId.BELLSPROUT, SpeciesId.POOCHYENA, SpeciesId.LOTAD, SpeciesId.SKITTY, SpeciesId.COMBEE, SpeciesId.CHERUBI, SpeciesId.MINCCINO, SpeciesId.PAWMI ], + [TimeOfDay.DAY]: [ SpeciesId.NIDORAN_F, SpeciesId.NIDORAN_M, SpeciesId.BELLSPROUT, SpeciesId.POOCHYENA, SpeciesId.LOTAD, SpeciesId.SKITTY, SpeciesId.COMBEE, SpeciesId.CHERUBI, SpeciesId.MINCCINO, SpeciesId.PAWMI ], + [TimeOfDay.DUSK]: [ SpeciesId.EKANS, SpeciesId.ODDISH, SpeciesId.PARAS, SpeciesId.VENONAT, SpeciesId.MEOWTH, SpeciesId.SHROOMISH, SpeciesId.KRICKETOT ], + [TimeOfDay.NIGHT]: [ SpeciesId.EKANS, SpeciesId.ODDISH, SpeciesId.PARAS, SpeciesId.VENONAT, SpeciesId.MEOWTH, SpeciesId.SHROOMISH, SpeciesId.KRICKETOT ], + [TimeOfDay.ALL]: [ SpeciesId.SEEDOT, SpeciesId.WHISMUR, SpeciesId.VENIPEDE, SpeciesId.FIDOUGH ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.TANDEMAUS ], [TimeOfDay.DAY]: [ SpeciesId.TANDEMAUS ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ABRA, SpeciesId.SURSKIT, SpeciesId.ROOKIDEE ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.EEVEE, SpeciesId.RALTS ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ABRA, SpeciesId.CLEFFA, SpeciesId.IGGLYBUFF, SpeciesId.SURSKIT, SpeciesId.HAPPINY, SpeciesId.ROOKIDEE, SpeciesId.TANDEMAUS ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.EEVEE, SpeciesId.PICHU, SpeciesId.TOGEPI, SpeciesId.RALTS, SpeciesId.NINCADA, SpeciesId.RIOLU ] }, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, SpeciesId.MUNCHLAX, SpeciesId.ZORUA ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, @@ -94,7 +96,7 @@ export const biomePokemonPools: BiomePokemonPools = { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.SENTRET, SpeciesId.YUNGOOS, SpeciesId.SKWOVET ], [TimeOfDay.DAY]: [ SpeciesId.SENTRET, SpeciesId.YUNGOOS, SpeciesId.SKWOVET ], - [TimeOfDay.DUSK]: [ SpeciesId.MEOWTH, SpeciesId.POOCHYENA ], + [TimeOfDay.DUSK]: [ SpeciesId.ZUBAT, SpeciesId.MEOWTH, SpeciesId.POOCHYENA ], [TimeOfDay.NIGHT]: [ SpeciesId.ZUBAT, SpeciesId.MEOWTH, SpeciesId.POOCHYENA ], [TimeOfDay.ALL]: [ SpeciesId.ZIGZAGOON, SpeciesId.BIDOOF, SpeciesId.LECHONK ] }, @@ -104,6 +106,7 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.POOCHYENA, SpeciesId.STARLY, SpeciesId.PIDOVE, + SpeciesId.ROCKRUFF, SpeciesId.PAWMI ], [TimeOfDay.DAY]: [ @@ -114,8 +117,8 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.ROCKRUFF, SpeciesId.PAWMI ], - [TimeOfDay.DUSK]: [ SpeciesId.MANKEY ], - [TimeOfDay.NIGHT]: [ SpeciesId.MANKEY ], + [TimeOfDay.DUSK]: [ SpeciesId.MANKEY, SpeciesId.NICKIT ], + [TimeOfDay.NIGHT]: [ SpeciesId.MANKEY, SpeciesId.NICKIT ], [TimeOfDay.ALL]: [ SpeciesId.PIDGEY, SpeciesId.SPEAROW, @@ -151,79 +154,79 @@ export const biomePokemonPools: BiomePokemonPools = { }, [BiomeId.GRASS]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.HOPPIP, SpeciesId.SUNKERN, SpeciesId.COTTONEE, SpeciesId.PETILIL ], - [TimeOfDay.DAY]: [ SpeciesId.HOPPIP, SpeciesId.SUNKERN, SpeciesId.COTTONEE, SpeciesId.PETILIL ], - [TimeOfDay.DUSK]: [ SpeciesId.SEEDOT, SpeciesId.SHROOMISH ], - [TimeOfDay.NIGHT]: [ SpeciesId.SEEDOT, SpeciesId.SHROOMISH ], - [TimeOfDay.ALL]: [] + [TimeOfDay.DAWN]: [ SpeciesId.HOPPIP, SpeciesId.SILCOON ], + [TimeOfDay.DAY]: [ SpeciesId.HOPPIP, SpeciesId.SILCOON ], + [TimeOfDay.DUSK]: [ SpeciesId.CASCOON ], + [TimeOfDay.NIGHT]: [ SpeciesId.CASCOON ], + [TimeOfDay.ALL]: [ SpeciesId.SHROOMISH, SpeciesId.VENIPEDE, SpeciesId.COTTONEE, SpeciesId.PETILIL ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.COMBEE, SpeciesId.CHERUBI ], - [TimeOfDay.DAY]: [ SpeciesId.COMBEE, SpeciesId.CHERUBI ], - [TimeOfDay.DUSK]: [ SpeciesId.FOONGUS ], - [TimeOfDay.NIGHT]: [ SpeciesId.FOONGUS ], - [TimeOfDay.ALL]: [] + [TimeOfDay.DAWN]: [ SpeciesId.SUNKERN, SpeciesId.COMBEE ], + [TimeOfDay.DAY]: [ SpeciesId.SUNKERN, SpeciesId.COMBEE ], + [TimeOfDay.DUSK]: [ SpeciesId.SEEDOT, SpeciesId.NOIBAT ], + [TimeOfDay.NIGHT]: [ SpeciesId.SEEDOT, SpeciesId.NOIBAT ], + [TimeOfDay.ALL]: [ SpeciesId.MILTANK, SpeciesId.CHERUBI, SpeciesId.FOONGUS, ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.BULBASAUR, SpeciesId.GROWLITHE, SpeciesId.TURTWIG ] + [TimeOfDay.ALL]: [ SpeciesId.BULBASAUR, SpeciesId.GROWLITHE, SpeciesId.TURTWIG, SpeciesId.BONSLY ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SUDOWOODO ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.VIRIZION ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.JUMPLUFF, SpeciesId.SUNFLORA, SpeciesId.WHIMSICOTT ], [TimeOfDay.DAY]: [ SpeciesId.JUMPLUFF, SpeciesId.SUNFLORA, SpeciesId.WHIMSICOTT ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.VENUSAUR, SpeciesId.SUDOWOODO, SpeciesId.TORTERRA ] }, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.JUMPLUFF, SpeciesId.VESPIQUEN ], [TimeOfDay.DAY]: [ SpeciesId.JUMPLUFF, SpeciesId.VESPIQUEN ], [TimeOfDay.DUSK]: [ SpeciesId.NOIVERN ], [TimeOfDay.NIGHT]: [ SpeciesId.NOIVERN ], [TimeOfDay.ALL]: [ SpeciesId.MILTANK, SpeciesId.SCOLIPEDE, SpeciesId.WHIMSICOTT, SpeciesId.LILLIGANT ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.VENUSAUR, SpeciesId.ARCANINE, SpeciesId.SUDOWOODO, SpeciesId.TORTERRA ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.VIRIZION ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, [BiomeId.TALL_GRASS]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.BOUNSWEET ], + [TimeOfDay.DAWN]: [ SpeciesId.NIDORAN_F, SpeciesId.NIDORAN_M, SpeciesId.BOUNSWEET ], [TimeOfDay.DAY]: [ SpeciesId.NIDORAN_F, SpeciesId.NIDORAN_M, SpeciesId.BOUNSWEET ], - [TimeOfDay.DUSK]: [ SpeciesId.ODDISH, SpeciesId.KRICKETOT ], - [TimeOfDay.NIGHT]: [ SpeciesId.ODDISH, SpeciesId.KRICKETOT ], - [TimeOfDay.ALL]: [ SpeciesId.NINCADA, SpeciesId.FOMANTIS, SpeciesId.NYMBLE ] + [TimeOfDay.DUSK]: [ SpeciesId.ODDISH, SpeciesId.SPINARAK, SpeciesId.KRICKETOT ], + [TimeOfDay.NIGHT]: [ SpeciesId.ODDISH, SpeciesId.SPINARAK, SpeciesId.KRICKETOT ], + [TimeOfDay.ALL]: [ SpeciesId.PARAS, SpeciesId.FOMANTIS, SpeciesId.NYMBLE, SpeciesId.SCATTERBUG ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], - [TimeOfDay.NIGHT]: [ SpeciesId.PARAS, SpeciesId.VENONAT, SpeciesId.SPINARAK ], - [TimeOfDay.ALL]: [ SpeciesId.VULPIX ] + [TimeOfDay.NIGHT]: [], + [TimeOfDay.ALL]: [ SpeciesId.VULPIX, SpeciesId.VENONAT, SpeciesId.NINCADA, SpeciesId.ZANGOOSE, SpeciesId.SEVIPER ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.PINSIR, SpeciesId.CHIKORITA, SpeciesId.GIRAFARIG, SpeciesId.ZANGOOSE, SpeciesId.KECLEON, SpeciesId.TROPIUS ] + [TimeOfDay.ALL]: [ SpeciesId.PINSIR, SpeciesId.CHIKORITA, SpeciesId.GIRAFARIG, SpeciesId.KECLEON, SpeciesId.TROPIUS, SpeciesId.AUDINO, SpeciesId.PAWNIARD ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SCYTHER, SpeciesId.SHEDINJA, SpeciesId.ROTOM ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SCYTHER, SpeciesId.SHEDINJA ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS]: { - [TimeOfDay.DAWN]: [ SpeciesId.TSAREENA ], + [TimeOfDay.DAWN]: [ SpeciesId.NIDOQUEEN, SpeciesId.NIDOKING, SpeciesId.TSAREENA ], [TimeOfDay.DAY]: [ SpeciesId.NIDOQUEEN, SpeciesId.NIDOKING, SpeciesId.TSAREENA ], - [TimeOfDay.DUSK]: [ SpeciesId.VILEPLUME, SpeciesId.KRICKETUNE ], - [TimeOfDay.NIGHT]: [ SpeciesId.VILEPLUME, SpeciesId.KRICKETUNE ], - [TimeOfDay.ALL]: [ SpeciesId.NINJASK, SpeciesId.ZANGOOSE, SpeciesId.KECLEON, SpeciesId.LURANTIS, SpeciesId.LOKIX ] + [TimeOfDay.DUSK]: [ SpeciesId.VILEPLUME, SpeciesId.ARIADOS, SpeciesId.KRICKETUNE ], + [TimeOfDay.NIGHT]: [ SpeciesId.VILEPLUME, SpeciesId.ARIADOS, SpeciesId.KRICKETUNE ], + [TimeOfDay.ALL]: [ SpeciesId.NINJASK, SpeciesId.ZANGOOSE, SpeciesId.SEVIPER, SpeciesId.KECLEON, SpeciesId.LURANTIS, SpeciesId.LOKIX ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.BELLOSSOM ], [TimeOfDay.DAY]: [ SpeciesId.BELLOSSOM ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PINSIR, SpeciesId.MEGANIUM, SpeciesId.FARIGIRAF ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.BELLOSSOM ], [TimeOfDay.DAY]: [ SpeciesId.BELLOSSOM ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SCYTHER, SpeciesId.PINSIR, SpeciesId.MEGANIUM, SpeciesId.FARIGIRAF, SpeciesId.KINGAMBIT ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, [BiomeId.METROPOLIS]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.YAMPER ], [TimeOfDay.DAY]: [ SpeciesId.YAMPER ], - [TimeOfDay.DUSK]: [ SpeciesId.PATRAT ], - [TimeOfDay.NIGHT]: [ SpeciesId.HOUNDOUR, SpeciesId.PATRAT ], - [TimeOfDay.ALL]: [ SpeciesId.RATTATA, SpeciesId.ZIGZAGOON, SpeciesId.LILLIPUP ] + [TimeOfDay.DUSK]: [ SpeciesId.HOUNDOUR], + [TimeOfDay.NIGHT]: [ SpeciesId.HOUNDOUR ], + [TimeOfDay.ALL]: [ SpeciesId.RATTATA, SpeciesId.ZIGZAGOON, SpeciesId.PATRAT, SpeciesId.LILLIPUP ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.PATRAT, SpeciesId.INDEEDEE ], - [TimeOfDay.DAY]: [ SpeciesId.PATRAT, SpeciesId.INDEEDEE ], + [TimeOfDay.DAWN]: [ SpeciesId.INDEEDEE ], + [TimeOfDay.DAY]: [ SpeciesId.INDEEDEE ], [TimeOfDay.DUSK]: [ SpeciesId.ESPURR ], [TimeOfDay.NIGHT]: [ SpeciesId.ESPURR ], [TimeOfDay.ALL]: [ SpeciesId.PIKACHU, SpeciesId.GLAMEOW, SpeciesId.FURFROU, SpeciesId.FIDOUGH, SpeciesId.SQUAWKABILLY ] @@ -233,12 +236,12 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ SpeciesId.TANDEMAUS ], [TimeOfDay.DUSK]: [ SpeciesId.MORPEKO ], [TimeOfDay.NIGHT]: [ SpeciesId.MORPEKO ], - [TimeOfDay.ALL]: [ SpeciesId.VAROOM ] + [TimeOfDay.ALL]: [ SpeciesId.SMEARGLE, SpeciesId.CASTFORM, SpeciesId.VAROOM ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, SpeciesId.EEVEE, SpeciesId.SMEARGLE ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.CASTFORM ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.BOLTUND ], [TimeOfDay.DAY]: [ SpeciesId.BOLTUND ], [TimeOfDay.DUSK]: [ SpeciesId.MEOWSTIC ], [TimeOfDay.NIGHT]: [ SpeciesId.MEOWSTIC ], [TimeOfDay.ALL]: [ SpeciesId.STOUTLAND, SpeciesId.FURFROU, SpeciesId.DACHSBUN ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.MAUSHOLD ], [TimeOfDay.DAY]: [ SpeciesId.MAUSHOLD ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.CASTFORM, SpeciesId.REVAVROOM ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, SpeciesId.EEVEE ] }, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.BOLTUND ], [TimeOfDay.DAY]: [ SpeciesId.BOLTUND ], [TimeOfDay.DUSK]: [ SpeciesId.MEOWSTIC ], [TimeOfDay.NIGHT]: [ SpeciesId.MEOWSTIC ], [TimeOfDay.ALL]: [ SpeciesId.CASTFORM, SpeciesId.STOUTLAND, SpeciesId.FURFROU, SpeciesId.DACHSBUN ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.MAUSHOLD ], [TimeOfDay.DAY]: [ SpeciesId.MAUSHOLD ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.REVAVROOM ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, @@ -263,6 +266,7 @@ export const biomePokemonPools: BiomePokemonPools = { ], [TimeOfDay.DUSK]: [ SpeciesId.BEEDRILL, + SpeciesId.SPINARAK, SpeciesId.PINECO, SpeciesId.SEEDOT, SpeciesId.SHROOMISH, @@ -283,7 +287,7 @@ export const biomePokemonPools: BiomePokemonPools = { [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.ROSELIA, SpeciesId.MOTHIM, SpeciesId.SEWADDLE ], [TimeOfDay.DAY]: [ SpeciesId.ROSELIA, SpeciesId.MOTHIM, SpeciesId.SEWADDLE ], - [TimeOfDay.DUSK]: [ SpeciesId.SPINARAK, SpeciesId.DOTTLER ], + [TimeOfDay.DUSK]: [ SpeciesId.DOTTLER ], [TimeOfDay.NIGHT]: [ SpeciesId.HOOTHOOT, SpeciesId.ROCKRUFF, SpeciesId.DOTTLER ], [TimeOfDay.ALL]: [ SpeciesId.EKANS, @@ -332,9 +336,9 @@ export const biomePokemonPools: BiomePokemonPools = { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.SLOWPOKE, SpeciesId.WINGULL, SpeciesId.CRAMORANT, SpeciesId.FINIZEN ], [TimeOfDay.DAY]: [ SpeciesId.SLOWPOKE, SpeciesId.WINGULL, SpeciesId.CRAMORANT, SpeciesId.FINIZEN ], - [TimeOfDay.DUSK]: [ SpeciesId.INKAY ], + [TimeOfDay.DUSK]: [ SpeciesId.FINNEON, SpeciesId.INKAY ], [TimeOfDay.NIGHT]: [ SpeciesId.FINNEON, SpeciesId.INKAY ], - [TimeOfDay.ALL]: [ SpeciesId.TENTACOOL, SpeciesId.MAGIKARP, SpeciesId.BUIZEL ] + [TimeOfDay.ALL]: [ SpeciesId.TENTACOOL, SpeciesId.WAILMER ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.STARYU ], @@ -345,7 +349,8 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.POLIWAG, SpeciesId.HORSEA, SpeciesId.GOLDEEN, - SpeciesId.WAILMER, + SpeciesId.MAGIKARP, + SpeciesId.BUIZEL, SpeciesId.PANPOUR, SpeciesId.WATTREL ] @@ -357,7 +362,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.LAPRAS, SpeciesId.PIPLUP, SpeciesId.POPPLIO ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.KINGDRA, SpeciesId.ROTOM, SpeciesId.TIRTOUGA ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.KINGDRA, SpeciesId.TIRTOUGA ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.PELIPPER, SpeciesId.CRAMORANT, SpeciesId.PALAFIN ], @@ -366,8 +371,8 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ SpeciesId.SHARPEDO, SpeciesId.LUMINEON, SpeciesId.MALAMAR ], [TimeOfDay.ALL]: [ SpeciesId.TENTACRUEL, SpeciesId.FLOATZEL, SpeciesId.SIMIPOUR, SpeciesId.KILOWATTREL ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.KINGDRA, SpeciesId.EMPOLEON, SpeciesId.PRIMARINA ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GYARADOS, SpeciesId.KINGDRA, SpeciesId.EMPOLEON, SpeciesId.PRIMARINA ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.LUGIA ] } }, [BiomeId.SWAMP]: { @@ -473,8 +478,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.ALL]: [ SpeciesId.PSYDUCK, SpeciesId.GOLDEEN, - SpeciesId.MAGIKARP, - SpeciesId.CHEWTLE + SpeciesId.WOOPER, + SpeciesId.SURSKIT, + SpeciesId.CHEWTLE, ] }, [BiomePoolTier.UNCOMMON]: { @@ -482,7 +488,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ SpeciesId.DEWPIDER ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.SLOWPOKE, SpeciesId.WOOPER, SpeciesId.SURSKIT, SpeciesId.WISHIWASHI, SpeciesId.FLAMIGO ] + [TimeOfDay.ALL]: [ SpeciesId.SLOWPOKE, SpeciesId.MAGIKARP, SpeciesId.WISHIWASHI ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], @@ -493,7 +499,8 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.SQUIRTLE, SpeciesId.OSHAWOTT, SpeciesId.FROAKIE, - SpeciesId.SOBBLE + SpeciesId.SOBBLE, + SpeciesId.FLAMIGO ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.VAPOREON, SpeciesId.SLOWKING ] }, @@ -503,9 +510,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ SpeciesId.SWANNA, SpeciesId.ARAQUANID ], [TimeOfDay.DUSK]: [ SpeciesId.AZUMARILL ], [TimeOfDay.NIGHT]: [ SpeciesId.AZUMARILL ], - [TimeOfDay.ALL]: [ SpeciesId.GOLDUCK, SpeciesId.SLOWBRO, SpeciesId.SEAKING, SpeciesId.GYARADOS, SpeciesId.MASQUERAIN, SpeciesId.WISHIWASHI, SpeciesId.DREDNAW ] + [TimeOfDay.ALL]: [ SpeciesId.GOLDUCK, SpeciesId.SLOWBRO, SpeciesId.SEAKING, SpeciesId.MASQUERAIN, SpeciesId.WISHIWASHI, SpeciesId.DREDNAW ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BLASTOISE, SpeciesId.VAPOREON, SpeciesId.SLOWKING, SpeciesId.SAMUROTT, SpeciesId.GRENINJA, SpeciesId.INTELEON ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BLASTOISE, SpeciesId.GYARADOS, SpeciesId.VAPOREON, SpeciesId.SLOWKING, SpeciesId.SAMUROTT, SpeciesId.GRENINJA, SpeciesId.INTELEON ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SUICUNE, SpeciesId.MESPRIT ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, @@ -546,7 +553,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.QWILFISH, SpeciesId.CORSOLA, SpeciesId.OCTILLERY, SpeciesId.MANTYKE, SpeciesId.ALOMOMOLA, SpeciesId.TYNAMO, SpeciesId.DHELMISE ] + [TimeOfDay.ALL]: [ SpeciesId.QWILFISH, SpeciesId.CORSOLA, SpeciesId.OCTILLERY, SpeciesId.FEEBAS, SpeciesId.MANTYKE, SpeciesId.ALOMOMOLA, SpeciesId.TYNAMO, SpeciesId.DHELMISE ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], @@ -563,7 +570,7 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.HISUI_QWILFISH ] }, - [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.FEEBAS, SpeciesId.NIHILEGO ] }, + [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.NIHILEGO ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -576,9 +583,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.OMASTAR, SpeciesId.KABUTOPS, SpeciesId.RELICANTH, SpeciesId.EELEKTROSS, SpeciesId.PYUKUMUKU, SpeciesId.DHELMISE, SpeciesId.CURSOLA, SpeciesId.ARCTOVISH, SpeciesId.BASCULEGION, SpeciesId.OVERQWIL ] + [TimeOfDay.ALL]: [ SpeciesId.OMASTAR, SpeciesId.KABUTOPS, SpeciesId.MILOTIC, SpeciesId.RELICANTH, SpeciesId.EELEKTROSS, SpeciesId.PYUKUMUKU, SpeciesId.DHELMISE, SpeciesId.CURSOLA, SpeciesId.ARCTOVISH, SpeciesId.BASCULEGION, SpeciesId.OVERQWIL ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MILOTIC, SpeciesId.NIHILEGO ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.NIHILEGO ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.KYOGRE ] } }, [BiomeId.MOUNTAIN]: { @@ -626,8 +633,7 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.MACHOP, SpeciesId.GEODUDE, SpeciesId.NATU, - SpeciesId.SLUGMA, - SpeciesId.NACLI + SpeciesId.SLUGMA ] }, [BiomePoolTier.RARE]: { @@ -635,7 +641,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ SpeciesId.MURKROW ], - [TimeOfDay.ALL]: [ SpeciesId.SKARMORY, SpeciesId.TORCHIC, SpeciesId.SPOINK, SpeciesId.HAWLUCHA, SpeciesId.KLAWF ] + [TimeOfDay.ALL]: [ SpeciesId.SKARMORY, SpeciesId.TORCHIC, SpeciesId.SPOINK, SpeciesId.HAWLUCHA, SpeciesId.NACLI ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], @@ -647,7 +653,6 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.CRANIDOS, SpeciesId.SHIELDON, SpeciesId.GIBLE, - SpeciesId.ROTOM, SpeciesId.ARCHEOPS, SpeciesId.AXEW ] @@ -658,10 +663,10 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [ SpeciesId.SWELLOW, SpeciesId.ALTARIA, SpeciesId.STARAPTOR, SpeciesId.UNFEZANT, SpeciesId.BRAVIARY, SpeciesId.TALONFLAME, SpeciesId.CORVIKNIGHT, SpeciesId.ESPATHRA ], [TimeOfDay.DUSK]: [ SpeciesId.MANDIBUZZ ], [TimeOfDay.NIGHT]: [ SpeciesId.MANDIBUZZ ], - [TimeOfDay.ALL]: [ SpeciesId.PIDGEOT, SpeciesId.FEAROW, SpeciesId.SKARMORY, SpeciesId.AGGRON, SpeciesId.GOGOAT, SpeciesId.GARGANACL ] + [TimeOfDay.ALL]: [ SpeciesId.PIDGEOT, SpeciesId.FEAROW, SpeciesId.SKARMORY, SpeciesId.AGGRON, SpeciesId.GOGOAT ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.HISUI_BRAVIARY ], [TimeOfDay.DAY]: [ SpeciesId.HISUI_BRAVIARY ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BLAZIKEN, SpeciesId.RAMPARDOS, SpeciesId.BASTIODON, SpeciesId.HAWLUCHA ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM, SpeciesId.TORNADUS, SpeciesId.TING_LU, SpeciesId.OGERPON ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.HISUI_BRAVIARY ], [TimeOfDay.DAY]: [ SpeciesId.HISUI_BRAVIARY ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BLAZIKEN, SpeciesId.RAMPARDOS, SpeciesId.BASTIODON, SpeciesId.HAWLUCHA, SpeciesId.GARGANACL ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TORNADUS, SpeciesId.TING_LU, SpeciesId.OGERPON ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HO_OH ] } }, [BiomeId.BADLANDS]: { @@ -690,7 +695,7 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.CUFANT ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ONIX, SpeciesId.GLIGAR, SpeciesId.POLTCHAGEIST ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ONIX, SpeciesId.GLIGAR, SpeciesId.KLAWF, SpeciesId.POLTCHAGEIST ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.LANDORUS, SpeciesId.OKIDOGI ] }, [BiomePoolTier.BOSS]: { @@ -717,8 +722,7 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.WHISMUR, SpeciesId.ROGGENROLA, SpeciesId.WOOBAT, - SpeciesId.BUNNELBY, - SpeciesId.NACLI + SpeciesId.BUNNELBY ] }, [BiomePoolTier.UNCOMMON]: { @@ -739,7 +743,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.ONIX, SpeciesId.FERROSEED, SpeciesId.CARBINK, SpeciesId.GLIMMET ] + [TimeOfDay.ALL]: [ SpeciesId.ONIX, SpeciesId.FERROSEED, SpeciesId.CARBINK, SpeciesId.NACLI, SpeciesId.GLIMMET ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SHUCKLE ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.UXIE ] }, @@ -748,44 +752,44 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.PARASECT, SpeciesId.ONIX, SpeciesId.CROBAT, SpeciesId.URSARING, SpeciesId.EXPLOUD, SpeciesId.PROBOPASS, SpeciesId.GIGALITH, SpeciesId.SWOOBAT, SpeciesId.DIGGERSBY, SpeciesId.NOIVERN, SpeciesId.GOLISOPOD, SpeciesId.GARGANACL ] + [TimeOfDay.ALL]: [ SpeciesId.PARASECT, SpeciesId.ONIX, SpeciesId.CROBAT, SpeciesId.URSARING, SpeciesId.EXPLOUD, SpeciesId.PROBOPASS, SpeciesId.GIGALITH, SpeciesId.SWOOBAT, SpeciesId.DIGGERSBY, SpeciesId.NOIVERN, SpeciesId.GOLISOPOD ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ SpeciesId.LYCANROC ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SHUCKLE, SpeciesId.FERROTHORN, SpeciesId.GLIMMORA ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ SpeciesId.LYCANROC ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SHUCKLE, SpeciesId.FERROTHORN, SpeciesId.GARGANACL, SpeciesId.GLIMMORA ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.UXIE ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TERAPAGOS ] } }, [BiomeId.DESERT]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.TRAPINCH, SpeciesId.HIPPOPOTAS, SpeciesId.RELLOR ], - [TimeOfDay.DAY]: [ SpeciesId.TRAPINCH, SpeciesId.HIPPOPOTAS, SpeciesId.RELLOR ], - [TimeOfDay.DUSK]: [ SpeciesId.CACNEA, SpeciesId.SANDILE ], - [TimeOfDay.NIGHT]: [ SpeciesId.CACNEA, SpeciesId.SANDILE ], - [TimeOfDay.ALL]: [ SpeciesId.SANDSHREW, SpeciesId.SKORUPI, SpeciesId.SILICOBRA ] + [TimeOfDay.DAWN]: [ SpeciesId.TRAPINCH, SpeciesId.HELIOPTILE ], + [TimeOfDay.DAY]: [ SpeciesId.TRAPINCH, SpeciesId.HELIOPTILE ], + [TimeOfDay.DUSK]: [ SpeciesId.CACNEA ], + [TimeOfDay.NIGHT]: [ SpeciesId.CACNEA ], + [TimeOfDay.ALL]: [ SpeciesId.SANDSHREW, SpeciesId.SKORUPI, SpeciesId.SILICOBRA, SpeciesId.BRAMBLIN, SpeciesId.RELLOR ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.SANDILE, SpeciesId.HELIOPTILE ], - [TimeOfDay.DAY]: [ SpeciesId.SANDILE, SpeciesId.HELIOPTILE ], - [TimeOfDay.DUSK]: [], - [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.MARACTUS, SpeciesId.BRAMBLIN, SpeciesId.ORTHWORM ] + [TimeOfDay.DAWN]: [ SpeciesId.MARACTUS ], + [TimeOfDay.DAY]: [ SpeciesId.MARACTUS ], + [TimeOfDay.DUSK]: [ SpeciesId.GLIGAR, SpeciesId.YAMASK ], + [TimeOfDay.NIGHT]: [ SpeciesId.GLIGAR, SpeciesId.YAMASK ], + [TimeOfDay.ALL]: [ SpeciesId.NUMEL, SpeciesId.HIPPOPOTAS, SpeciesId.SANDILE, SpeciesId.ORTHWORM ] }, [BiomePoolTier.RARE]: { - [TimeOfDay.DAWN]: [ SpeciesId.VIBRAVA ], - [TimeOfDay.DAY]: [ SpeciesId.VIBRAVA ], + [TimeOfDay.DAWN]: [], + [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.DARUMAKA ] + [TimeOfDay.ALL]: [ SpeciesId.DODUO, SpeciesId.DARUMAKA, SpeciesId.SIGILYPH, SpeciesId.STONJOURNER ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.LILEEP, SpeciesId.ANORITH ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.LILEEP, SpeciesId.ANORITH, SpeciesId.GIBLE ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.REGIROCK, SpeciesId.TAPU_BULU, SpeciesId.PHEROMOSA ] }, [BiomePoolTier.BOSS]: { - [TimeOfDay.DAWN]: [ SpeciesId.HIPPOWDON, SpeciesId.HELIOLISK, SpeciesId.RABSCA ], - [TimeOfDay.DAY]: [ SpeciesId.HIPPOWDON, SpeciesId.HELIOLISK, SpeciesId.RABSCA ], - [TimeOfDay.DUSK]: [ SpeciesId.CACTURNE, SpeciesId.KROOKODILE ], - [TimeOfDay.NIGHT]: [ SpeciesId.CACTURNE, SpeciesId.KROOKODILE ], - [TimeOfDay.ALL]: [ SpeciesId.SANDSLASH, SpeciesId.DRAPION, SpeciesId.DARMANITAN, SpeciesId.MARACTUS, SpeciesId.SANDACONDA, SpeciesId.BRAMBLEGHAST ] + [TimeOfDay.DAWN]: [ SpeciesId.MARACTUS, SpeciesId.HELIOLISK, SpeciesId.FLYGON ], + [TimeOfDay.DAY]: [ SpeciesId.MARACTUS, SpeciesId.HELIOLISK, SpeciesId.FLYGON ], + [TimeOfDay.DUSK]: [ SpeciesId.GLISCOR, SpeciesId.CACTURNE, SpeciesId.COFAGRIGUS ], + [TimeOfDay.NIGHT]: [ SpeciesId.GLISCOR, SpeciesId.CACTURNE, SpeciesId.COFAGRIGUS ], + [TimeOfDay.ALL]: [ SpeciesId.SANDSLASH, SpeciesId.HIPPOWDON, SpeciesId.DRAPION, SpeciesId.KROOKODILE, SpeciesId.DARMANITAN, SpeciesId.SANDACONDA, SpeciesId.BRAMBLEGHAST ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.CRADILY, SpeciesId.ARMALDO ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DODRIO, SpeciesId.CRADILY, SpeciesId.ARMALDO, SpeciesId.GARCHOMP, SpeciesId.SIGILYPH, SpeciesId.STONJOURNER ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.REGIROCK, SpeciesId.TAPU_BULU, SpeciesId.PHEROMOSA ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, @@ -798,7 +802,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.ALL]: [ SpeciesId.SEEL, SpeciesId.SWINUB, - SpeciesId.SNOVER, + SpeciesId.SNORUNT, SpeciesId.VANILLITE, SpeciesId.CUBCHOO, SpeciesId.BERGMITE, @@ -812,15 +816,16 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ + SpeciesId.SLOWKING, SpeciesId.SNEASEL, - SpeciesId.SNORUNT, + SpeciesId.SMOOCHUM, SpeciesId.SPHEAL, SpeciesId.EISCUE, SpeciesId.CETODDLE ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.JYNX, SpeciesId.LAPRAS, SpeciesId.FROSLASS, SpeciesId.CRYOGONAL ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DELIBIRD, SpeciesId.ROTOM, SpeciesId.AMAURA ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.LAPRAS, SpeciesId.DELIBIRD, SpeciesId.CRYOGONAL ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.AMAURA ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ARTICUNO, SpeciesId.REGICE ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], @@ -830,13 +835,13 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.ALL]: [ SpeciesId.DEWGONG, SpeciesId.GLALIE, SpeciesId.WALREIN, SpeciesId.WEAVILE, SpeciesId.MAMOSWINE, SpeciesId.FROSLASS, SpeciesId.VANILLUXE, SpeciesId.BEARTIC, SpeciesId.CRYOGONAL, SpeciesId.AVALUGG, SpeciesId.CRABOMINABLE, SpeciesId.CETITAN ] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.JYNX, SpeciesId.LAPRAS, SpeciesId.GLACEON, SpeciesId.AURORUS ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ARTICUNO, SpeciesId.REGICE, SpeciesId.ROTOM ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ARTICUNO, SpeciesId.REGICE ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.KYUREM ] } }, [BiomeId.MEADOW]: { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.LEDYBA, SpeciesId.ROSELIA, SpeciesId.COTTONEE, SpeciesId.MINCCINO ], - [TimeOfDay.DAY]: [ SpeciesId.ROSELIA, SpeciesId.COTTONEE, SpeciesId.MINCCINO ], + [TimeOfDay.DAY]: [ SpeciesId.LEDYBA, SpeciesId.ROSELIA, SpeciesId.COTTONEE, SpeciesId.MINCCINO ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ @@ -873,9 +878,9 @@ export const biomePokemonPools: BiomePokemonPools = { ] }, [BiomePoolTier.RARE]: { - [TimeOfDay.DAWN]: [], + [TimeOfDay.DAWN]: [ SpeciesId.VOLBEAT, SpeciesId.ILLUMISE ], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [], + [TimeOfDay.DUSK]: [ SpeciesId.VOLBEAT, SpeciesId.ILLUMISE ], [TimeOfDay.NIGHT]: [ SpeciesId.VOLBEAT, SpeciesId.ILLUMISE ], [TimeOfDay.ALL]: [ SpeciesId.TAUROS, SpeciesId.EEVEE, SpeciesId.MILTANK, SpeciesId.SPINDA, SpeciesId.APPLIN, SpeciesId.SPRIGATITO ] }, @@ -883,7 +888,7 @@ export const biomePokemonPools: BiomePokemonPools = { [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MELOETTA ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.LEDIAN, SpeciesId.GRANBULL, SpeciesId.DELCATTY, SpeciesId.ROSERADE, SpeciesId.CINCCINO, SpeciesId.BOUFFALANT, SpeciesId.ARBOLIVA ], - [TimeOfDay.DAY]: [ SpeciesId.GRANBULL, SpeciesId.DELCATTY, SpeciesId.ROSERADE, SpeciesId.CINCCINO, SpeciesId.BOUFFALANT, SpeciesId.ARBOLIVA ], + [TimeOfDay.DAY]: [ SpeciesId.LEDIAN, SpeciesId.GRANBULL, SpeciesId.DELCATTY, SpeciesId.ROSERADE, SpeciesId.CINCCINO, SpeciesId.BOUFFALANT, SpeciesId.ARBOLIVA ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TAUROS, SpeciesId.MILTANK, SpeciesId.GARDEVOIR, SpeciesId.PURUGLY, SpeciesId.ZEBSTRIKA, SpeciesId.FLORGES, SpeciesId.RIBOMBEE, SpeciesId.DUBWOOL ] @@ -900,7 +905,6 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PIKACHU, - SpeciesId.MAGNEMITE, SpeciesId.VOLTORB, SpeciesId.ELECTRIKE, SpeciesId.SHINX, @@ -910,8 +914,8 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.TADBULB ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ELECTABUZZ, SpeciesId.PLUSLE, SpeciesId.MINUN, SpeciesId.PACHIRISU, SpeciesId.EMOLGA, SpeciesId.TOGEDEMARU ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MAREEP ] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MAGNEMITE, SpeciesId.ELECTABUZZ, SpeciesId.PLUSLE, SpeciesId.MINUN, SpeciesId.PACHIRISU, SpeciesId.EMOLGA, SpeciesId.TOGEDEMARU ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MAREEP, SpeciesId.ROTOM ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.JOLTEON, SpeciesId.HISUI_VOLTORB ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.RAIKOU, SpeciesId.THUNDURUS, SpeciesId.XURKITREE, SpeciesId.ZERAORA, SpeciesId.REGIELEKI ] }, [BiomePoolTier.BOSS]: { @@ -936,12 +940,14 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.GROWLITHE, SpeciesId.PONYTA, SpeciesId.SLUGMA, + SpeciesId.POOCHYENA, SpeciesId.NUMEL, - SpeciesId.SALANDIT, + SpeciesId.SPOINK, + SpeciesId.SWABLU, SpeciesId.ROLYCOLY ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MAGMAR, SpeciesId.TORKOAL, SpeciesId.PANSEAR, SpeciesId.HEATMOR, SpeciesId.TURTONATOR ] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MAGMAR, SpeciesId.MEDITITE, SpeciesId.TORKOAL, SpeciesId.PANSEAR, SpeciesId.HEATMOR, SpeciesId.SALANDIT, SpeciesId.TURTONATOR, SpeciesId.ALOLA_DIGLETT ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], @@ -958,14 +964,14 @@ export const biomePokemonPools: BiomePokemonPools = { SpeciesId.CHARCADET ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.FLAREON, SpeciesId.ROTOM, SpeciesId.LARVESTA, SpeciesId.HISUI_GROWLITHE ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.FLAREON, SpeciesId.LARVESTA, SpeciesId.HISUI_GROWLITHE ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ENTEI, SpeciesId.HEATRAN, SpeciesId.VOLCANION, SpeciesId.CHI_YU ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.NINETALES, SpeciesId.ARCANINE, SpeciesId.RAPIDASH, SpeciesId.MAGCARGO, SpeciesId.CAMERUPT, SpeciesId.TORKOAL, SpeciesId.MAGMORTAR, SpeciesId.SIMISEAR, SpeciesId.HEATMOR, SpeciesId.SALAZZLE, SpeciesId.TURTONATOR, SpeciesId.COALOSSAL ] + [TimeOfDay.ALL]: [ SpeciesId.NINETALES, SpeciesId.ARCANINE, SpeciesId.RAPIDASH, SpeciesId.MAGCARGO, SpeciesId.CAMERUPT, SpeciesId.TORKOAL, SpeciesId.MAGMORTAR, SpeciesId.SIMISEAR, SpeciesId.HEATMOR, SpeciesId.SALAZZLE, SpeciesId.TURTONATOR, SpeciesId.COALOSSAL, SpeciesId.ALOLA_DUGTRIO ] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], @@ -974,7 +980,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.CHARIZARD, SpeciesId.FLAREON, SpeciesId.TYPHLOSION, SpeciesId.INFERNAPE, SpeciesId.EMBOAR, SpeciesId.VOLCARONA, SpeciesId.DELPHOX, SpeciesId.INCINEROAR, SpeciesId.CINDERACE, SpeciesId.ARMAROUGE, SpeciesId.HISUI_ARCANINE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MOLTRES, SpeciesId.ENTEI, SpeciesId.ROTOM, SpeciesId.HEATRAN, SpeciesId.VOLCANION, SpeciesId.CHI_YU ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MOLTRES, SpeciesId.ENTEI, SpeciesId.HEATRAN, SpeciesId.VOLCANION, SpeciesId.CHI_YU ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.RESHIRAM ] } }, [BiomeId.GRAVEYARD]: { @@ -1047,8 +1053,8 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.ALL]: [ SpeciesId.HITMONLEE, SpeciesId.HITMONCHAN, SpeciesId.HARIYAMA, SpeciesId.MEDICHAM, SpeciesId.LUCARIO, SpeciesId.TOXICROAK, SpeciesId.THROH, SpeciesId.SAWK, SpeciesId.SCRAFTY, SpeciesId.MIENSHAO, SpeciesId.BEWEAR, SpeciesId.GRAPPLOCT, SpeciesId.ANNIHILAPE ] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.HITMONTOP, SpeciesId.GALLADE, SpeciesId.PANGORO, SpeciesId.SIRFETCHD, SpeciesId.HISUI_DECIDUEYE ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TERRAKION, SpeciesId.KUBFU ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ZAMAZENTA, SpeciesId.GALAR_ZAPDOS ] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TERRAKION, SpeciesId.KUBFU, SpeciesId.GALAR_ZAPDOS ] }, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ZAMAZENTA ] } }, [BiomeId.FACTORY]: { [BiomePoolTier.COMMON]: { @@ -1058,18 +1064,18 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MACHOP, - SpeciesId.MAGNEMITE, SpeciesId.VOLTORB, + SpeciesId.BRONZOR, SpeciesId.TIMBURR, SpeciesId.KLINK ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BRONZOR, SpeciesId.KLEFKI ] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MAGNEMITE, SpeciesId.ELEKID, SpeciesId.MAGBY, SpeciesId.KLEFKI ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PORYGON ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BELDUM ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GENESECT, SpeciesId.MAGEARNA ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.KLINKLANG, SpeciesId.KLEFKI ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BRONZONG, SpeciesId.ELECTIVIRE, SpeciesId.MAGMORTAR, SpeciesId.KLINKLANG, SpeciesId.KLEFKI ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.METAGROSS ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GENESECT, SpeciesId.MAGEARNA ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, @@ -1163,44 +1169,42 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - SpeciesId.MURKROW, - SpeciesId.HOUNDOUR, + SpeciesId.ZUBAT, + SpeciesId.PARAS, + SpeciesId.MISDREAVUS, SpeciesId.SABLEYE, - SpeciesId.PURRLOIN, - SpeciesId.PAWNIARD, - SpeciesId.NICKIT, - SpeciesId.IMPIDIMP, - SpeciesId.MASCHIFF + SpeciesId.WOOBAT, + SpeciesId.IMPIDIMP ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GASTLY, SpeciesId.DUNSPARCE, SpeciesId.HOUNDOUR, SpeciesId.MAWILE, SpeciesId.WHISMUR ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.ABSOL, SpeciesId.SPIRITOMB, SpeciesId.ZORUA, SpeciesId.DEINO ] + [TimeOfDay.ALL]: [ SpeciesId.ABSOL, SpeciesId.SPIRITOMB, SpeciesId.FROSLASS, SpeciesId.ZORUA ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.UMBREON ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.UMBREON, SpeciesId.DEINO, SpeciesId.DREEPY ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DARKRAI, SpeciesId.GALAR_MOLTRES ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.HOUNDOOM, SpeciesId.SABLEYE, SpeciesId.ABSOL, SpeciesId.HONCHKROW, SpeciesId.SPIRITOMB, SpeciesId.LIEPARD, SpeciesId.ZOROARK, SpeciesId.HYDREIGON, SpeciesId.THIEVUL, SpeciesId.GRIMMSNARL, SpeciesId.MABOSSTIFF, SpeciesId.KINGAMBIT ] + [TimeOfDay.ALL]: [ SpeciesId.GENGAR, SpeciesId.CROBAT, SpeciesId.HOUNDOOM, SpeciesId.SABLEYE, SpeciesId.FROSLASS, SpeciesId.ZOROARK, SpeciesId.GRIMMSNARL ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.UMBREON, SpeciesId.HISUI_SAMUROTT ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DARKRAI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PALKIA, SpeciesId.YVELTAL, SpeciesId.GALAR_MOLTRES ] } + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.UMBREON, SpeciesId.SPIRITOMB, SpeciesId.HYDREIGON, SpeciesId.DRAGAPULT ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DARKRAI, SpeciesId.GALAR_MOLTRES ] }, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PALKIA, SpeciesId.YVELTAL ] } }, [BiomeId.SPACE]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [], + [TimeOfDay.DAWN]: [ SpeciesId.SOLROCK ], [TimeOfDay.DAY]: [ SpeciesId.SOLROCK ], - [TimeOfDay.DUSK]: [], + [TimeOfDay.DUSK]: [ SpeciesId.LUNATONE ], [TimeOfDay.NIGHT]: [ SpeciesId.LUNATONE ], - [TimeOfDay.ALL]: [ SpeciesId.CLEFAIRY, SpeciesId.BRONZOR, SpeciesId.MUNNA, SpeciesId.MINIOR ] + [TimeOfDay.ALL]: [ SpeciesId.CLEFFA, SpeciesId.BRONZOR, SpeciesId.MUNNA, SpeciesId.MINIOR ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.BALTOY, SpeciesId.ELGYEM ] }, [BiomePoolTier.RARE]: { @@ -1208,9 +1212,9 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.BELDUM, SpeciesId.SIGILYPH, SpeciesId.SOLOSIS ] + [TimeOfDay.ALL]: [ SpeciesId.STARYU, SpeciesId.SIGILYPH, SpeciesId.SOLOSIS ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PORYGON ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PORYGON, SpeciesId.BELDUM ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.COSMOG, SpeciesId.CELESTEELA ] }, [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [ SpeciesId.SOLROCK ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [ SpeciesId.LUNATONE ], [TimeOfDay.ALL]: [ SpeciesId.CLEFABLE, SpeciesId.BRONZONG, SpeciesId.MUSHARNA, SpeciesId.REUNICLUS, SpeciesId.MINIOR ] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.METAGROSS, SpeciesId.PORYGON_Z ] }, @@ -1224,9 +1228,12 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ + SpeciesId.DIGLETT, SpeciesId.MACHOP, - SpeciesId.MAGNEMITE, - SpeciesId.DRILBUR, + SpeciesId.GRIMER, + SpeciesId.PHANPY, + SpeciesId.MAKUHITA, + SpeciesId.NOSEPASS, SpeciesId.TIMBURR ] }, @@ -1236,17 +1243,19 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - SpeciesId.GRIMER, + SpeciesId.MAGNEMITE, SpeciesId.KOFFING, SpeciesId.RHYHORN, - SpeciesId.SCRAGGY + SpeciesId.DRILBUR, + SpeciesId.SCRAGGY, + SpeciesId.ALOLA_GEODUDE, ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ SpeciesId.GALAR_MEOWTH ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ONIX, SpeciesId.HITMONLEE, SpeciesId.HITMONCHAN, SpeciesId.DURALUDON ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, SpeciesId.HITMONTOP ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ONIX, SpeciesId.TYROGUE, SpeciesId.GALAR_MEOWTH ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, SpeciesId.DURALUDON ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.COBALION, SpeciesId.STAKATAKA ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MACHAMP, SpeciesId.CONKELDURR ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ SpeciesId.PERRSERKER ], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ARCHALUDON ] }, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MACHAMP, SpeciesId.MAGNEZONE, SpeciesId.PROBOPASS, SpeciesId.CONKELDURR, SpeciesId.ALOLA_GOLEM ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PERRSERKER, SpeciesId.ARCHALUDON ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.COBALION, SpeciesId.STAKATAKA ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, @@ -1254,14 +1263,14 @@ export const biomePokemonPools: BiomePokemonPools = { [BiomePoolTier.COMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.VESPIQUEN, SpeciesId.CHERUBI, SpeciesId.SEWADDLE ], [TimeOfDay.DAY]: [ SpeciesId.VESPIQUEN, SpeciesId.CHERUBI, SpeciesId.SEWADDLE ], - [TimeOfDay.DUSK]: [ SpeciesId.SHROOMISH, SpeciesId.PURRLOIN, SpeciesId.FOONGUS ], + [TimeOfDay.DUSK]: [ SpeciesId.SPINARAK, SpeciesId.SHROOMISH, SpeciesId.PURRLOIN, SpeciesId.FOONGUS ], [TimeOfDay.NIGHT]: [ SpeciesId.SPINARAK, SpeciesId.SHROOMISH, SpeciesId.PURRLOIN, SpeciesId.FOONGUS ], [TimeOfDay.ALL]: [ SpeciesId.AIPOM, SpeciesId.BLITZLE, SpeciesId.PIKIPEK ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.EXEGGCUTE, SpeciesId.TROPIUS, SpeciesId.COMBEE, SpeciesId.KOMALA ], [TimeOfDay.DAY]: [ SpeciesId.EXEGGCUTE, SpeciesId.TROPIUS, SpeciesId.COMBEE, SpeciesId.KOMALA ], - [TimeOfDay.DUSK]: [ SpeciesId.TANGELA, SpeciesId.SPINARAK, SpeciesId.PANCHAM ], + [TimeOfDay.DUSK]: [ SpeciesId.TANGELA, SpeciesId.PANCHAM ], [TimeOfDay.NIGHT]: [ SpeciesId.TANGELA, SpeciesId.PANCHAM ], [TimeOfDay.ALL]: [ SpeciesId.PANSAGE, @@ -1275,7 +1284,7 @@ export const biomePokemonPools: BiomePokemonPools = { }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.FOONGUS, SpeciesId.PASSIMIAN, SpeciesId.GALAR_PONYTA ], - [TimeOfDay.DAY]: [ SpeciesId.FOONGUS, SpeciesId.PASSIMIAN ], + [TimeOfDay.DAY]: [ SpeciesId.FOONGUS, SpeciesId.PASSIMIAN, SpeciesId.GALAR_PONYTA ], [TimeOfDay.DUSK]: [ SpeciesId.ORANGURU ], [TimeOfDay.NIGHT]: [ SpeciesId.ORANGURU ], [TimeOfDay.ALL]: [ @@ -1299,13 +1308,13 @@ export const biomePokemonPools: BiomePokemonPools = { }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.AMOONGUSS, SpeciesId.GALAR_RAPIDASH ], - [TimeOfDay.DAY]: [ SpeciesId.AMOONGUSS ], + [TimeOfDay.DAY]: [ SpeciesId.AMOONGUSS, SpeciesId.GALAR_RAPIDASH ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.KANGASKHAN, SpeciesId.SCIZOR, SpeciesId.SLAKING, SpeciesId.LEAFEON, SpeciesId.SERPERIOR, SpeciesId.RILLABOOM ] + [TimeOfDay.ALL]: [ SpeciesId.KANGASKHAN, SpeciesId.SCIZOR, SpeciesId.SLAKING, SpeciesId.LEAFEON, SpeciesId.SERPERIOR, SpeciesId.RILLABOOM, SpeciesId.KLEAVOR ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TAPU_LELE, SpeciesId.BUZZWOLE, SpeciesId.ZARUDE, SpeciesId.MUNKIDORI ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.KLEAVOR ] } + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, [BiomeId.FAIRY_CAVE]: { [BiomePoolTier.COMMON]: { @@ -1390,59 +1399,63 @@ export const biomePokemonPools: BiomePokemonPools = { }, [BiomeId.SLUM]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [], - [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ SpeciesId.PATRAT ], - [TimeOfDay.NIGHT]: [ SpeciesId.PATRAT ], + [TimeOfDay.DAWN]: [ ], + [TimeOfDay.DAY]: [ ], + [TimeOfDay.DUSK]: [ SpeciesId.SHUPPET ], + [TimeOfDay.NIGHT]: [ SpeciesId.SHUPPET ], [TimeOfDay.ALL]: [ SpeciesId.RATTATA, SpeciesId.GRIMER, + SpeciesId.DROWZEE, SpeciesId.KOFFING, + SpeciesId.MURKROW, + SpeciesId.GLAMEOW, + SpeciesId.SCRAGGY, SpeciesId.TRUBBISH, ] }, [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ SpeciesId.STUNKY ], - [TimeOfDay.NIGHT]: [ SpeciesId.STUNKY ], - [TimeOfDay.ALL]: [ SpeciesId.WORMADAM ], + [TimeOfDay.DUSK]: [], + [TimeOfDay.NIGHT]: [], + [TimeOfDay.ALL]: [ SpeciesId.HOUNDOUR, SpeciesId.WORMADAM, SpeciesId.STUNKY, SpeciesId.PANCHAM, SpeciesId.MASCHIFF, SpeciesId.ALOLA_RATTATA, SpeciesId.GALAR_ZIGZAGOON ], }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ SpeciesId.TOXTRICITY, SpeciesId.GALAR_ZIGZAGOON ], - [TimeOfDay.NIGHT]: [ SpeciesId.TOXTRICITY, SpeciesId.GALAR_ZIGZAGOON ], - [TimeOfDay.ALL]: [ SpeciesId.VAROOM ] + [TimeOfDay.DUSK]: [], + [TimeOfDay.NIGHT]: [], + [TimeOfDay.ALL]: [ SpeciesId.SNEASEL, SpeciesId.GOTHITA, SpeciesId.PAWNIARD, SpeciesId.TOXEL, SpeciesId.SQUAWKABILLY, SpeciesId.VAROOM ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GUZZLORD ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ SpeciesId.SKUNTANK, SpeciesId.WATCHOG ], [TimeOfDay.NIGHT]: [ SpeciesId.SKUNTANK, SpeciesId.WATCHOG ], [TimeOfDay.ALL]: [ SpeciesId.MUK, SpeciesId.WEEZING, SpeciesId.WORMADAM, SpeciesId.GARBODOR ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [ SpeciesId.TOXTRICITY, SpeciesId.OBSTAGOON ], [TimeOfDay.NIGHT]: [ SpeciesId.TOXTRICITY, SpeciesId.OBSTAGOON ], [TimeOfDay.ALL]: [ SpeciesId.REVAVROOM, SpeciesId.GALAR_WEEZING ] }, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MUK, SpeciesId.WEEZING, SpeciesId.SKUNTANK, SpeciesId.SCRAFTY, SpeciesId.GARBODOR, SpeciesId.PANGORO, SpeciesId.ALOLA_RATICATE, SpeciesId.OBSTAGOON ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.WEAVILE, SpeciesId.TOXTRICITY, SpeciesId.REVAVROOM, SpeciesId.GALAR_WEEZING ] }, [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GUZZLORD ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] } }, [BiomeId.SNOWY_FOREST]: { [BiomePoolTier.COMMON]: { - [TimeOfDay.DAWN]: [], - [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [ SpeciesId.SNEASEL, SpeciesId.TEDDIURSA, SpeciesId.SNOM ], - [TimeOfDay.NIGHT]: [ SpeciesId.SNEASEL, SpeciesId.TEDDIURSA, SpeciesId.SNOM ], - [TimeOfDay.ALL]: [SpeciesId.PILOSWINE, SpeciesId.SNOVER, SpeciesId.EISCUE ] + [TimeOfDay.DAWN]: [ SpeciesId.GLALIE, SpeciesId.CUBCHOO ], + [TimeOfDay.DAY]: [ SpeciesId.GLALIE, SpeciesId.CUBCHOO ], + [TimeOfDay.DUSK]: [ SpeciesId.SNEASEL, SpeciesId.FROSLASS ], + [TimeOfDay.NIGHT]: [ SpeciesId.SNEASEL, SpeciesId.FROSLASS ], + [TimeOfDay.ALL]: [SpeciesId.SENTRET, SpeciesId.SWINUB, SpeciesId.SNOVER, SpeciesId.SNOM ] }, [BiomePoolTier.UNCOMMON]: { - [TimeOfDay.DAWN]: [ SpeciesId.SNEASEL, SpeciesId.TEDDIURSA, SpeciesId.STANTLER ], - [TimeOfDay.DAY]: [ SpeciesId.SNEASEL, SpeciesId.TEDDIURSA, SpeciesId.STANTLER ], + [TimeOfDay.DAWN]: [], + [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [] + [TimeOfDay.ALL]: [ SpeciesId.TEDDIURSA, SpeciesId.STANTLER, SpeciesId.SKIDDO, SpeciesId.EISCUE ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.GALAR_DARUMAKA ], [TimeOfDay.DAY]: [ SpeciesId.GALAR_DARUMAKA ], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], - [TimeOfDay.ALL]: [ SpeciesId.DELIBIRD, SpeciesId.ALOLA_SANDSHREW, SpeciesId.ALOLA_VULPIX ] + [TimeOfDay.ALL]: [ SpeciesId.DELIBIRD, SpeciesId.CRYOGONAL, SpeciesId.AVALUGG, SpeciesId.ALOLA_SANDSHREW, SpeciesId.ALOLA_VULPIX ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.HISUI_SNEASEL ], @@ -1452,7 +1465,7 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.ALL]: [ SpeciesId.GALAR_MR_MIME, SpeciesId.ARCTOZOLT, SpeciesId.HISUI_AVALUGG ] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GLASTRIER, SpeciesId.CHIEN_PAO, SpeciesId.GALAR_ARTICUNO ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.WYRDEER ], [TimeOfDay.DAY]: [ SpeciesId.WYRDEER ], [TimeOfDay.DUSK]: [ SpeciesId.FROSMOTH ], [TimeOfDay.NIGHT]: [ SpeciesId.FROSMOTH ], [TimeOfDay.ALL]: [ SpeciesId.ABOMASNOW, SpeciesId.URSALUNA ] }, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [ SpeciesId.GLALIE, SpeciesId.BEARTIC ], [TimeOfDay.DAY]: [ SpeciesId.GLALIE, SpeciesId.BEARTIC ], [TimeOfDay.DUSK]: [ SpeciesId.WEAVILE, SpeciesId.FROSLASS ], [TimeOfDay.NIGHT]: [ SpeciesId.WEAVILE, SpeciesId.FROSLASS ], [TimeOfDay.ALL]: [ SpeciesId.ABOMASNOW, SpeciesId.MAMOSWINE, SpeciesId.WYRDEER, SpeciesId.URSALUNA ] }, [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [ SpeciesId.SNEASLER, SpeciesId.GALAR_DARMANITAN ], [TimeOfDay.DAY]: [ SpeciesId.SNEASLER, SpeciesId.GALAR_DARMANITAN ], @@ -1460,8 +1473,8 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.NIGHT]: [ SpeciesId.HISUI_ZOROARK ], [TimeOfDay.ALL]: [ SpeciesId.MR_RIME, SpeciesId.ARCTOZOLT, SpeciesId.ALOLA_SANDSLASH, SpeciesId.ALOLA_NINETALES ] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GLASTRIER, SpeciesId.CHIEN_PAO ] }, - [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ZACIAN, SpeciesId.GALAR_ARTICUNO ] } + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.GLASTRIER, SpeciesId.CHIEN_PAO, SpeciesId.GALAR_ARTICUNO ] }, + [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ZACIAN ] } }, [BiomeId.ISLAND]: { [BiomePoolTier.COMMON]: { @@ -1506,20 +1519,20 @@ export const biomePokemonPools: BiomePokemonPools = { [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ - SpeciesId.MAGNEMITE, SpeciesId.GRIMER, SpeciesId.VOLTORB, SpeciesId.BRONZOR, + SpeciesId.MUNNA, SpeciesId.KLINK, ] }, - [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.SOLOSIS ] }, - [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, SpeciesId.PORYGON ] }, - [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM ] }, + [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MAGNEMITE, SpeciesId.SOLOSIS, SpeciesId.KLEFKI ] }, + [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.DITTO, SpeciesId.PORYGON, SpeciesId.ROTOM ] }, + [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, [BiomePoolTier.ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.TYPE_NULL ] }, - [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MUK, SpeciesId.ELECTRODE, SpeciesId.BRONZONG, SpeciesId.MAGNEZONE, SpeciesId.PORYGON_Z, SpeciesId.REUNICLUS, SpeciesId.KLINKLANG ] }, - [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, - [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ROTOM, SpeciesId.ZYGARDE, SpeciesId.TYPE_NULL ] }, + [BiomePoolTier.BOSS]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MUK, SpeciesId.ELECTRODE, SpeciesId.BRONZONG, SpeciesId.MAGNEZONE, SpeciesId.REUNICLUS, SpeciesId.KLINKLANG ] }, + [BiomePoolTier.BOSS_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.PORYGON_Z, SpeciesId.ROTOM ] }, + [BiomePoolTier.BOSS_SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.ZYGARDE, SpeciesId.TYPE_NULL ] }, [BiomePoolTier.BOSS_ULTRA_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [ SpeciesId.MEWTWO, SpeciesId.MIRAIDON ] } }, [BiomeId.END]: { diff --git a/src/data/balance/init-biomes.ts b/src/data/balance/init-biomes.ts index a50c1036af6..1b410e637e8 100644 --- a/src/data/balance/init-biomes.ts +++ b/src/data/balance/init-biomes.ts @@ -159,29 +159,29 @@ export function initBiomes() { ] ], [SpeciesId.NIDORAN_F, PokemonType.POISON, -1, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON, TimeOfDay.DAY], - [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, TimeOfDay.DAY] + [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.NIDORINA, PokemonType.POISON, -1, [ - [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, TimeOfDay.DAY] + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.NIDOQUEEN, PokemonType.POISON, PokemonType.GROUND, [ - [BiomeId.TALL_GRASS, BiomePoolTier.BOSS, TimeOfDay.DAY] + [BiomeId.TALL_GRASS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.NIDORAN_M, PokemonType.POISON, -1, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON, TimeOfDay.DAY], - [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, TimeOfDay.DAY] + [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.NIDORINO, PokemonType.POISON, -1, [ - [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, TimeOfDay.DAY] + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.NIDOKING, PokemonType.POISON, PokemonType.GROUND, [ - [BiomeId.TALL_GRASS, BiomePoolTier.BOSS, TimeOfDay.DAY] + [BiomeId.TALL_GRASS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.CLEFAIRY, PokemonType.FAIRY, -1, [ @@ -214,13 +214,15 @@ export function initBiomes() { ] ], [SpeciesId.ZUBAT, PokemonType.POISON, PokemonType.FLYING, [ - [BiomeId.PLAINS, BiomePoolTier.COMMON, TimeOfDay.NIGHT], - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.PLAINS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.CAVE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.COMMON] ] ], [SpeciesId.GOLBAT, PokemonType.POISON, PokemonType.FLYING, [ - [BiomeId.PLAINS, BiomePoolTier.COMMON, TimeOfDay.NIGHT], - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.PLAINS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.CAVE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.COMMON] ] ], [SpeciesId.ODDISH, PokemonType.GRASS, PokemonType.POISON, [ @@ -237,36 +239,40 @@ export function initBiomes() { ] ], [SpeciesId.PARAS, PokemonType.BUG, PokemonType.GRASS, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], - [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON], + [BiomeId.CAVE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.COMMON] ] ], [SpeciesId.PARASECT, PokemonType.BUG, PokemonType.GRASS, [ [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], [BiomeId.CAVE, BiomePoolTier.COMMON], - [BiomeId.CAVE, BiomePoolTier.BOSS] + [BiomeId.CAVE, BiomePoolTier.BOSS], + [BiomeId.ABYSS, BiomePoolTier.COMMON] ] ], [SpeciesId.VENONAT, PokemonType.BUG, PokemonType.POISON, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], - [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], + [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON], [BiomeId.FOREST, BiomePoolTier.COMMON, TimeOfDay.NIGHT] ] ], [SpeciesId.VENOMOTH, PokemonType.BUG, PokemonType.POISON, [ - [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], + [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON], [BiomeId.FOREST, BiomePoolTier.COMMON, TimeOfDay.NIGHT], [BiomeId.FOREST, BiomePoolTier.BOSS, TimeOfDay.NIGHT] ] ], [SpeciesId.DIGLETT, PokemonType.GROUND, -1, [ - [BiomeId.BADLANDS, BiomePoolTier.COMMON] + [BiomeId.BADLANDS, BiomePoolTier.COMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] ] ], [SpeciesId.DUGTRIO, PokemonType.GROUND, -1, [ [BiomeId.BADLANDS, BiomePoolTier.COMMON], - [BiomeId.BADLANDS, BiomePoolTier.BOSS] + [BiomeId.BADLANDS, BiomePoolTier.BOSS], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] ] ], [SpeciesId.MEOWTH, PokemonType.NORMAL, -1, [ @@ -306,6 +312,7 @@ export function initBiomes() { ] ], [SpeciesId.ARCANINE, PokemonType.FIRE, -1, [ + [BiomeId.GRASS, BiomePoolTier.BOSS_RARE], [BiomeId.VOLCANO, BiomePoolTier.BOSS] ] ], @@ -419,17 +426,17 @@ export function initBiomes() { ] ], [SpeciesId.MAGNEMITE, PokemonType.ELECTRIC, PokemonType.STEEL, [ - [BiomeId.POWER_PLANT, BiomePoolTier.COMMON], - [BiomeId.FACTORY, BiomePoolTier.COMMON], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON], - [BiomeId.LABORATORY, BiomePoolTier.COMMON] + [BiomeId.POWER_PLANT, BiomePoolTier.UNCOMMON], + [BiomeId.FACTORY, BiomePoolTier.UNCOMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON], + [BiomeId.LABORATORY, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.MAGNETON, PokemonType.ELECTRIC, PokemonType.STEEL, [ - [BiomeId.POWER_PLANT, BiomePoolTier.COMMON], - [BiomeId.FACTORY, BiomePoolTier.COMMON], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON], - [BiomeId.LABORATORY, BiomePoolTier.COMMON] + [BiomeId.POWER_PLANT, BiomePoolTier.UNCOMMON], + [BiomeId.FACTORY, BiomePoolTier.UNCOMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON], + [BiomeId.LABORATORY, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.FARFETCHD, PokemonType.NORMAL, PokemonType.FLYING, [ @@ -438,12 +445,15 @@ export function initBiomes() { ] ], [SpeciesId.DODUO, PokemonType.NORMAL, PokemonType.FLYING, [ - [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.DESERT, BiomePoolTier.RARE] ] ], [SpeciesId.DODRIO, PokemonType.NORMAL, PokemonType.FLYING, [ [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.PLAINS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.PLAINS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.DESERT, BiomePoolTier.RARE], + [BiomeId.DESERT, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.SEEL, PokemonType.WATER, -1, [ @@ -457,12 +467,12 @@ export function initBiomes() { ], [SpeciesId.GRIMER, PokemonType.POISON, -1, [ [BiomeId.SLUM, BiomePoolTier.COMMON], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON], [BiomeId.LABORATORY, BiomePoolTier.COMMON] ] ], [SpeciesId.MUK, PokemonType.POISON, -1, [ - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON], [BiomeId.SLUM, BiomePoolTier.COMMON], [BiomeId.SLUM, BiomePoolTier.BOSS], [BiomeId.LABORATORY, BiomePoolTier.COMMON], @@ -481,16 +491,19 @@ export function initBiomes() { ], [SpeciesId.GASTLY, PokemonType.GHOST, PokemonType.POISON, [ [BiomeId.GRAVEYARD, BiomePoolTier.COMMON], - [BiomeId.TEMPLE, BiomePoolTier.COMMON] + [BiomeId.TEMPLE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.HAUNTER, PokemonType.GHOST, PokemonType.POISON, [ [BiomeId.GRAVEYARD, BiomePoolTier.COMMON], - [BiomeId.TEMPLE, BiomePoolTier.COMMON] + [BiomeId.TEMPLE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.GENGAR, PokemonType.GHOST, PokemonType.POISON, [ - [BiomeId.GRAVEYARD, BiomePoolTier.BOSS] + [BiomeId.GRAVEYARD, BiomePoolTier.BOSS], + [BiomeId.ABYSS, BiomePoolTier.BOSS] ] ], [SpeciesId.ONIX, PokemonType.ROCK, PokemonType.GROUND, [ @@ -501,7 +514,8 @@ export function initBiomes() { ] ], [SpeciesId.DROWZEE, PokemonType.PSYCHIC, -1, [ - [BiomeId.RUINS, BiomePoolTier.COMMON] + [BiomeId.RUINS, BiomePoolTier.COMMON], + [BiomeId.SLUM, BiomePoolTier.COMMON], ] ], [SpeciesId.HYPNO, PokemonType.PSYCHIC, -1, [ @@ -556,14 +570,12 @@ export function initBiomes() { ], [SpeciesId.HITMONLEE, PokemonType.FIGHTING, -1, [ [BiomeId.DOJO, BiomePoolTier.RARE], - [BiomeId.DOJO, BiomePoolTier.BOSS], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE] + [BiomeId.DOJO, BiomePoolTier.BOSS] ] ], [SpeciesId.HITMONCHAN, PokemonType.FIGHTING, -1, [ [BiomeId.DOJO, BiomePoolTier.RARE], - [BiomeId.DOJO, BiomePoolTier.BOSS], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE] + [BiomeId.DOJO, BiomePoolTier.BOSS] ] ], [SpeciesId.LICKITUNG, PokemonType.NORMAL, -1, [ @@ -630,7 +642,8 @@ export function initBiomes() { ], [SpeciesId.STARYU, PokemonType.WATER, -1, [ [BiomeId.BEACH, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.SEA, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.SEA, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.SPACE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.STARMIE, PokemonType.WATER, PokemonType.PSYCHIC, [ @@ -646,12 +659,13 @@ export function initBiomes() { ], [SpeciesId.SCYTHER, PokemonType.BUG, PokemonType.FLYING, [ [BiomeId.TALL_GRASS, BiomePoolTier.SUPER_RARE], + [BiomeId.TALL_GRASS, BiomePoolTier.BOSS_RARE], [BiomeId.FOREST, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.JUNGLE, BiomePoolTier.RARE] ] ], [SpeciesId.JYNX, PokemonType.ICE, PokemonType.PSYCHIC, [ - [BiomeId.ICE_CAVE, BiomePoolTier.RARE], + [BiomeId.ICE_CAVE, BiomePoolTier.UNCOMMON], [BiomeId.ICE_CAVE, BiomePoolTier.BOSS_RARE] ] ], @@ -674,14 +688,15 @@ export function initBiomes() { ] ], [SpeciesId.MAGIKARP, PokemonType.WATER, -1, [ - [BiomeId.SEA, BiomePoolTier.COMMON], - [BiomeId.LAKE, BiomePoolTier.COMMON] + [BiomeId.SEA, BiomePoolTier.UNCOMMON], + [BiomeId.LAKE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.GYARADOS, PokemonType.WATER, PokemonType.FLYING, [ - [BiomeId.SEA, BiomePoolTier.COMMON], - [BiomeId.LAKE, BiomePoolTier.COMMON], - [BiomeId.LAKE, BiomePoolTier.BOSS] + [BiomeId.SEA, BiomePoolTier.UNCOMMON], + [BiomeId.SEA, BiomePoolTier.BOSS_RARE], + [BiomeId.LAKE, BiomePoolTier.UNCOMMON], + [BiomeId.LAKE, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.LAPRAS, PokemonType.WATER, PokemonType.ICE, [ @@ -827,7 +842,8 @@ export function initBiomes() { ], [SpeciesId.SENTRET, PokemonType.NORMAL, -1, [ [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.PLAINS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.PLAINS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON] ] ], [SpeciesId.FURRET, PokemonType.NORMAL, -1, [ @@ -836,7 +852,7 @@ export function initBiomes() { ] ], [SpeciesId.HOOTHOOT, PokemonType.NORMAL, PokemonType.FLYING, [ - [BiomeId.TOWN, BiomePoolTier.COMMON, TimeOfDay.NIGHT], + [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.FOREST, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT] ] ], @@ -846,36 +862,34 @@ export function initBiomes() { ] ], [SpeciesId.LEDYBA, PokemonType.BUG, PokemonType.FLYING, [ - [BiomeId.TOWN, BiomePoolTier.COMMON, TimeOfDay.DAWN], - [BiomeId.MEADOW, BiomePoolTier.COMMON, TimeOfDay.DAWN] + [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.MEADOW, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.LEDIAN, PokemonType.BUG, PokemonType.FLYING, [ - [BiomeId.MEADOW, BiomePoolTier.COMMON, TimeOfDay.DAWN], - [BiomeId.MEADOW, BiomePoolTier.BOSS, TimeOfDay.DAWN] + [BiomeId.MEADOW, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.MEADOW, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.SPINARAK, PokemonType.BUG, PokemonType.POISON, [ [BiomeId.TOWN, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK], [BiomeId.TOWN, BiomePoolTier.COMMON, TimeOfDay.NIGHT], - [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], - [BiomeId.FOREST, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK], - [BiomeId.FOREST, BiomePoolTier.COMMON, TimeOfDay.NIGHT], - [BiomeId.JUNGLE, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK], - [BiomeId.JUNGLE, BiomePoolTier.COMMON, TimeOfDay.NIGHT] + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.ARIADOS, PokemonType.BUG, PokemonType.POISON, [ - [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], - [BiomeId.FOREST, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK], - [BiomeId.FOREST, BiomePoolTier.COMMON, TimeOfDay.NIGHT], + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.TALL_GRASS, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.FOREST, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.JUNGLE, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK], - [BiomeId.JUNGLE, BiomePoolTier.COMMON, TimeOfDay.NIGHT] + [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.CROBAT, PokemonType.POISON, PokemonType.FLYING, [ - [BiomeId.CAVE, BiomePoolTier.BOSS] + [BiomeId.CAVE, BiomePoolTier.BOSS], + [BiomeId.ABYSS, BiomePoolTier.BOSS] ] ], [SpeciesId.CHINCHOU, PokemonType.WATER, PokemonType.ELECTRIC, [ @@ -889,13 +903,22 @@ export function initBiomes() { [BiomeId.SEABED, BiomePoolTier.BOSS] ] ], - [SpeciesId.PICHU, PokemonType.ELECTRIC, -1, [] + [SpeciesId.PICHU, PokemonType.ELECTRIC, -1, [ + [BiomeId.TOWN, BiomePoolTier.SUPER_RARE] + ] ], - [SpeciesId.CLEFFA, PokemonType.FAIRY, -1, [] + [SpeciesId.CLEFFA, PokemonType.FAIRY, -1, [ + [BiomeId.TOWN, BiomePoolTier.RARE], + [BiomeId.SPACE, BiomePoolTier.COMMON] + ] ], - [SpeciesId.IGGLYBUFF, PokemonType.NORMAL, PokemonType.FAIRY, [] + [SpeciesId.IGGLYBUFF, PokemonType.NORMAL, PokemonType.FAIRY, [ + [BiomeId.TOWN, BiomePoolTier.RARE] + ] ], - [SpeciesId.TOGEPI, PokemonType.FAIRY, -1, [] + [SpeciesId.TOGEPI, PokemonType.FAIRY, -1, [ + [BiomeId.TOWN, BiomePoolTier.SUPER_RARE] + ] ], [SpeciesId.TOGETIC, PokemonType.FAIRY, PokemonType.FLYING, [ [BiomeId.FAIRY_CAVE, BiomePoolTier.UNCOMMON] @@ -945,7 +968,6 @@ export function initBiomes() { ] ], [SpeciesId.SUDOWOODO, PokemonType.ROCK, -1, [ - [BiomeId.GRASS, BiomePoolTier.SUPER_RARE], [BiomeId.GRASS, BiomePoolTier.BOSS_RARE] ] ], @@ -973,24 +995,22 @@ export function initBiomes() { ], [SpeciesId.SUNKERN, PokemonType.GRASS, -1, [ [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.GRASS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], - [SpeciesId.SUNFLORA, PokemonType.GRASS, -1, [ - [BiomeId.GRASS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] - ] + [SpeciesId.SUNFLORA, PokemonType.GRASS, -1, [] ], [SpeciesId.YANMA, PokemonType.BUG, PokemonType.FLYING, [ [BiomeId.JUNGLE, BiomePoolTier.RARE] ] ], [SpeciesId.WOOPER, PokemonType.WATER, PokemonType.GROUND, [ - [BiomeId.LAKE, BiomePoolTier.UNCOMMON], + [BiomeId.LAKE, BiomePoolTier.COMMON], [BiomeId.SWAMP, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.QUAGSIRE, PokemonType.WATER, PokemonType.GROUND, [ - [BiomeId.LAKE, BiomePoolTier.UNCOMMON], + [BiomeId.LAKE, BiomePoolTier.COMMON], [BiomeId.SWAMP, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.SWAMP, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] @@ -1007,16 +1027,18 @@ export function initBiomes() { ], [SpeciesId.MURKROW, PokemonType.DARK, PokemonType.FLYING, [ [BiomeId.MOUNTAIN, BiomePoolTier.RARE, TimeOfDay.NIGHT], - [BiomeId.ABYSS, BiomePoolTier.COMMON] + [BiomeId.SLUM, BiomePoolTier.COMMON] ] ], [SpeciesId.SLOWKING, PokemonType.WATER, PokemonType.PSYCHIC, [ [BiomeId.LAKE, BiomePoolTier.SUPER_RARE], - [BiomeId.LAKE, BiomePoolTier.BOSS_RARE] + [BiomeId.LAKE, BiomePoolTier.BOSS_RARE], + [BiomeId.ICE_CAVE, BiomePoolTier.RARE] ] ], [SpeciesId.MISDREAVUS, PokemonType.GHOST, -1, [ - [BiomeId.GRAVEYARD, BiomePoolTier.RARE] + [BiomeId.GRAVEYARD, BiomePoolTier.RARE], + [BiomeId.ABYSS, BiomePoolTier.COMMON] ] ], [SpeciesId.UNOWN, PokemonType.PSYCHIC, -1, [ @@ -1042,11 +1064,12 @@ export function initBiomes() { ] ], [SpeciesId.DUNSPARCE, PokemonType.NORMAL, -1, [ - [BiomeId.PLAINS, BiomePoolTier.SUPER_RARE] + [BiomeId.PLAINS, BiomePoolTier.SUPER_RARE], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.GLIGAR, PokemonType.GROUND, PokemonType.FLYING, [ - [BiomeId.BADLANDS, BiomePoolTier.RARE] + [BiomeId.BADLANDS, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.STEELIX, PokemonType.STEEL, PokemonType.GROUND, [ @@ -1082,24 +1105,22 @@ export function initBiomes() { ] ], [SpeciesId.SNEASEL, PokemonType.DARK, PokemonType.ICE, [ + [BiomeId.SLUM, BiomePoolTier.RARE], [BiomeId.ICE_CAVE, BiomePoolTier.UNCOMMON], - [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.TEDDIURSA, PokemonType.NORMAL, -1, [ [BiomeId.FOREST, BiomePoolTier.UNCOMMON], [BiomeId.CAVE, BiomePoolTier.COMMON], - [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.URSARING, PokemonType.NORMAL, -1, [ [BiomeId.FOREST, BiomePoolTier.UNCOMMON], [BiomeId.CAVE, BiomePoolTier.COMMON], [BiomeId.CAVE, BiomePoolTier.BOSS], - [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.SLUGMA, PokemonType.FIRE, -1, [ @@ -1138,7 +1159,7 @@ export function initBiomes() { ] ], [SpeciesId.DELIBIRD, PokemonType.ICE, PokemonType.FLYING, [ - [BiomeId.ICE_CAVE, BiomePoolTier.SUPER_RARE], + [BiomeId.ICE_CAVE, BiomePoolTier.RARE], [BiomeId.SNOWY_FOREST, BiomePoolTier.RARE] ] ], @@ -1153,13 +1174,14 @@ export function initBiomes() { ] ], [SpeciesId.HOUNDOUR, PokemonType.DARK, PokemonType.FIRE, [ - [BiomeId.METROPOLIS, BiomePoolTier.COMMON, TimeOfDay.NIGHT], - [BiomeId.ABYSS, BiomePoolTier.COMMON] + [BiomeId.METROPOLIS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON], + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.HOUNDOOM, PokemonType.DARK, PokemonType.FIRE, [ - [BiomeId.METROPOLIS, BiomePoolTier.COMMON, TimeOfDay.NIGHT], - [BiomeId.ABYSS, BiomePoolTier.COMMON], + [BiomeId.METROPOLIS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON], [BiomeId.ABYSS, BiomePoolTier.BOSS] ] ], @@ -1169,12 +1191,14 @@ export function initBiomes() { ] ], [SpeciesId.PHANPY, PokemonType.GROUND, -1, [ - [BiomeId.BADLANDS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.BADLANDS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] ] ], [SpeciesId.DONPHAN, PokemonType.GROUND, -1, [ [BiomeId.BADLANDS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.BADLANDS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.BADLANDS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] ] ], [SpeciesId.PORYGON2, PokemonType.NORMAL, -1, [ @@ -1186,28 +1210,36 @@ export function initBiomes() { [SpeciesId.STANTLER, PokemonType.NORMAL, -1, [ [BiomeId.FOREST, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.FOREST, BiomePoolTier.BOSS_RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.SMEARGLE, PokemonType.NORMAL, -1, [ - [BiomeId.METROPOLIS, BiomePoolTier.SUPER_RARE] + [BiomeId.METROPOLIS, BiomePoolTier.RARE] ] ], - [SpeciesId.TYROGUE, PokemonType.FIGHTING, -1, [] + [SpeciesId.TYROGUE, PokemonType.FIGHTING, -1, [ + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE] + ] ], [SpeciesId.HITMONTOP, PokemonType.FIGHTING, -1, [ [BiomeId.DOJO, BiomePoolTier.SUPER_RARE], - [BiomeId.DOJO, BiomePoolTier.BOSS_RARE], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.SUPER_RARE] + [BiomeId.DOJO, BiomePoolTier.BOSS_RARE] ] ], - [SpeciesId.SMOOCHUM, PokemonType.ICE, PokemonType.PSYCHIC, [] + [SpeciesId.SMOOCHUM, PokemonType.ICE, PokemonType.PSYCHIC, [ + [BiomeId.ICE_CAVE, BiomePoolTier.UNCOMMON], + ] ], - [SpeciesId.ELEKID, PokemonType.ELECTRIC, -1, [] + [SpeciesId.ELEKID, PokemonType.ELECTRIC, -1, [ + [BiomeId.FACTORY, BiomePoolTier.UNCOMMON] + ] ], - [SpeciesId.MAGBY, PokemonType.FIRE, -1, [] + [SpeciesId.MAGBY, PokemonType.FIRE, -1, [ + [BiomeId.FACTORY, BiomePoolTier.UNCOMMON] + ] ], [SpeciesId.MILTANK, PokemonType.NORMAL, -1, [ + [BiomeId.GRASS, BiomePoolTier.BOSS], [BiomeId.MEADOW, BiomePoolTier.RARE], [BiomeId.MEADOW, BiomePoolTier.BOSS] ] @@ -1299,13 +1331,15 @@ export function initBiomes() { [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.PLAINS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.PLAINS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.VOLCANO, BiomePoolTier.COMMON] ] ], [SpeciesId.MIGHTYENA, PokemonType.DARK, -1, [ [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.PLAINS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.PLAINS, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.PLAINS, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.VOLCANO, BiomePoolTier.COMMON] ] ], [SpeciesId.ZIGZAGOON, PokemonType.NORMAL, -1, [ @@ -1325,19 +1359,23 @@ export function initBiomes() { ] ], [SpeciesId.SILCOON, PokemonType.BUG, -1, [ - [BiomeId.TOWN, BiomePoolTier.COMMON, TimeOfDay.DAY] + [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.BEAUTIFLY, PokemonType.BUG, PokemonType.FLYING, [ + [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.FOREST, BiomePoolTier.COMMON, TimeOfDay.DAY], [BiomeId.FOREST, BiomePoolTier.BOSS, TimeOfDay.DAY] ] ], [SpeciesId.CASCOON, PokemonType.BUG, -1, [ - [BiomeId.TOWN, BiomePoolTier.COMMON, TimeOfDay.NIGHT] + [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.DUSTOX, PokemonType.BUG, PokemonType.POISON, [ + [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.FOREST, BiomePoolTier.COMMON, TimeOfDay.NIGHT], [BiomeId.FOREST, BiomePoolTier.BOSS, TimeOfDay.NIGHT] ] @@ -1358,8 +1396,8 @@ export function initBiomes() { ] ], [SpeciesId.SEEDOT, PokemonType.GRASS, -1, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.TOWN, BiomePoolTier.UNCOMMON], + [BiomeId.GRASS, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], @@ -1410,23 +1448,23 @@ export function initBiomes() { ], [SpeciesId.SURSKIT, PokemonType.BUG, PokemonType.WATER, [ [BiomeId.TOWN, BiomePoolTier.RARE], - [BiomeId.LAKE, BiomePoolTier.UNCOMMON] + [BiomeId.LAKE, BiomePoolTier.COMMON] ] ], [SpeciesId.MASQUERAIN, PokemonType.BUG, PokemonType.FLYING, [ - [BiomeId.LAKE, BiomePoolTier.UNCOMMON], + [BiomeId.LAKE, BiomePoolTier.COMMON], [BiomeId.LAKE, BiomePoolTier.BOSS] ] ], [SpeciesId.SHROOMISH, PokemonType.GRASS, -1, [ [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.GRASS, BiomePoolTier.COMMON], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.BRELOOM, PokemonType.GRASS, PokemonType.FIGHTING, [ - [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.GRASS, BiomePoolTier.COMMON], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.FOREST, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.JUNGLE, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] @@ -1446,12 +1484,12 @@ export function initBiomes() { ] ], [SpeciesId.NINCADA, PokemonType.BUG, PokemonType.GROUND, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON], - [BiomeId.TALL_GRASS, BiomePoolTier.COMMON] + [BiomeId.TOWN, BiomePoolTier.SUPER_RARE], + [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.NINJASK, PokemonType.BUG, PokemonType.FLYING, [ - [BiomeId.TALL_GRASS, BiomePoolTier.COMMON], + [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON], [BiomeId.TALL_GRASS, BiomePoolTier.BOSS] ] ], @@ -1461,33 +1499,39 @@ export function initBiomes() { ], [SpeciesId.WHISMUR, PokemonType.NORMAL, -1, [ [BiomeId.TOWN, BiomePoolTier.UNCOMMON], - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.CAVE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.LOUDRED, PokemonType.NORMAL, -1, [ - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.CAVE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.EXPLOUD, PokemonType.NORMAL, -1, [ [BiomeId.CAVE, BiomePoolTier.COMMON], - [BiomeId.CAVE, BiomePoolTier.BOSS] + [BiomeId.CAVE, BiomePoolTier.BOSS], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.MAKUHITA, PokemonType.FIGHTING, -1, [ [BiomeId.CAVE, BiomePoolTier.UNCOMMON], - [BiomeId.DOJO, BiomePoolTier.COMMON] + [BiomeId.DOJO, BiomePoolTier.COMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] ] ], [SpeciesId.HARIYAMA, PokemonType.FIGHTING, -1, [ [BiomeId.CAVE, BiomePoolTier.UNCOMMON], [BiomeId.DOJO, BiomePoolTier.COMMON], - [BiomeId.DOJO, BiomePoolTier.BOSS] + [BiomeId.DOJO, BiomePoolTier.BOSS], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] ] ], [SpeciesId.AZURILL, PokemonType.NORMAL, PokemonType.FAIRY, [] ], [SpeciesId.NOSEPASS, PokemonType.ROCK, -1, [ - [BiomeId.CAVE, BiomePoolTier.UNCOMMON] + [BiomeId.CAVE, BiomePoolTier.UNCOMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] ] ], [SpeciesId.SKITTY, PokemonType.NORMAL, -1, [ @@ -1507,7 +1551,8 @@ export function initBiomes() { ], [SpeciesId.MAWILE, PokemonType.STEEL, PokemonType.FAIRY, [ [BiomeId.FAIRY_CAVE, BiomePoolTier.COMMON], - [BiomeId.FAIRY_CAVE, BiomePoolTier.BOSS] + [BiomeId.FAIRY_CAVE, BiomePoolTier.BOSS], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.ARON, PokemonType.STEEL, PokemonType.ROCK, [ @@ -1527,10 +1572,12 @@ export function initBiomes() { ] ], [SpeciesId.MEDITITE, PokemonType.FIGHTING, PokemonType.PSYCHIC, [ + [BiomeId.VOLCANO, BiomePoolTier.UNCOMMON], [BiomeId.DOJO, BiomePoolTier.COMMON] ] ], [SpeciesId.MEDICHAM, PokemonType.FIGHTING, PokemonType.PSYCHIC, [ + [BiomeId.VOLCANO, BiomePoolTier.UNCOMMON], [BiomeId.DOJO, BiomePoolTier.COMMON], [BiomeId.DOJO, BiomePoolTier.BOSS] ] @@ -1553,11 +1600,11 @@ export function initBiomes() { ] ], [SpeciesId.VOLBEAT, PokemonType.BUG, -1, [ - [BiomeId.MEADOW, BiomePoolTier.RARE, TimeOfDay.NIGHT] + [BiomeId.MEADOW, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.ILLUMISE, PokemonType.BUG, -1, [ - [BiomeId.MEADOW, BiomePoolTier.RARE, TimeOfDay.NIGHT] + [BiomeId.MEADOW, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.ROSELIA, PokemonType.GRASS, PokemonType.POISON, [ @@ -1584,23 +1631,25 @@ export function initBiomes() { ] ], [SpeciesId.WAILMER, PokemonType.WATER, -1, [ - [BiomeId.SEA, BiomePoolTier.UNCOMMON], + [BiomeId.SEA, BiomePoolTier.COMMON], [BiomeId.SEABED, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.WAILORD, PokemonType.WATER, -1, [ - [BiomeId.SEA, BiomePoolTier.UNCOMMON], + [BiomeId.SEA, BiomePoolTier.COMMON], [BiomeId.SEABED, BiomePoolTier.UNCOMMON], [BiomeId.SEABED, BiomePoolTier.BOSS] ] ], [SpeciesId.NUMEL, PokemonType.FIRE, PokemonType.GROUND, [ [BiomeId.BADLANDS, BiomePoolTier.UNCOMMON], + [BiomeId.DESERT, BiomePoolTier.UNCOMMON], [BiomeId.VOLCANO, BiomePoolTier.COMMON] ] ], [SpeciesId.CAMERUPT, PokemonType.FIRE, PokemonType.GROUND, [ [BiomeId.BADLANDS, BiomePoolTier.UNCOMMON], + [BiomeId.DESERT, BiomePoolTier.UNCOMMON], [BiomeId.VOLCANO, BiomePoolTier.COMMON], [BiomeId.VOLCANO, BiomePoolTier.BOSS] ] @@ -1612,13 +1661,15 @@ export function initBiomes() { ], [SpeciesId.SPOINK, PokemonType.PSYCHIC, -1, [ [BiomeId.MOUNTAIN, BiomePoolTier.RARE], - [BiomeId.RUINS, BiomePoolTier.COMMON] + [BiomeId.RUINS, BiomePoolTier.COMMON], + [BiomeId.VOLCANO, BiomePoolTier.COMMON] ] ], [SpeciesId.GRUMPIG, PokemonType.PSYCHIC, -1, [ [BiomeId.MOUNTAIN, BiomePoolTier.RARE], [BiomeId.RUINS, BiomePoolTier.COMMON], - [BiomeId.RUINS, BiomePoolTier.BOSS] + [BiomeId.RUINS, BiomePoolTier.BOSS], + [BiomeId.VOLCANO, BiomePoolTier.COMMON] ] ], [SpeciesId.SPINDA, PokemonType.NORMAL, -1, [ @@ -1626,17 +1677,14 @@ export function initBiomes() { ] ], [SpeciesId.TRAPINCH, PokemonType.GROUND, -1, [ - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] - ] - ], - [SpeciesId.VIBRAVA, PokemonType.GROUND, PokemonType.DRAGON, [ - [BiomeId.DESERT, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.WASTELAND, BiomePoolTier.COMMON] ] ], + [SpeciesId.VIBRAVA, PokemonType.GROUND, PokemonType.DRAGON, [] + ], [SpeciesId.FLYGON, PokemonType.GROUND, PokemonType.DRAGON, [ - [BiomeId.DESERT, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.WASTELAND, BiomePoolTier.COMMON], + [BiomeId.DESERT, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.WASTELAND, BiomePoolTier.BOSS] ] ], @@ -1651,33 +1699,37 @@ export function initBiomes() { ], [SpeciesId.SWABLU, PokemonType.NORMAL, PokemonType.FLYING, [ [BiomeId.MOUNTAIN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.VOLCANO, BiomePoolTier.COMMON], [BiomeId.WASTELAND, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.ALTARIA, PokemonType.DRAGON, PokemonType.FLYING, [ [BiomeId.MOUNTAIN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.MOUNTAIN, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.VOLCANO, BiomePoolTier.COMMON], [BiomeId.WASTELAND, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.ZANGOOSE, PokemonType.NORMAL, -1, [ - [BiomeId.TALL_GRASS, BiomePoolTier.RARE], + [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON], [BiomeId.TALL_GRASS, BiomePoolTier.BOSS] ] ], [SpeciesId.SEVIPER, PokemonType.POISON, -1, [ + [BiomeId.TALL_GRASS, BiomePoolTier.UNCOMMON], + [BiomeId.TALL_GRASS, BiomePoolTier.BOSS], [BiomeId.JUNGLE, BiomePoolTier.RARE], [BiomeId.JUNGLE, BiomePoolTier.BOSS] ] ], [SpeciesId.LUNATONE, PokemonType.ROCK, PokemonType.PSYCHIC, [ - [BiomeId.SPACE, BiomePoolTier.COMMON, TimeOfDay.NIGHT], - [BiomeId.SPACE, BiomePoolTier.BOSS, TimeOfDay.NIGHT] + [BiomeId.SPACE, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.SPACE, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.SOLROCK, PokemonType.ROCK, PokemonType.PSYCHIC, [ - [BiomeId.SPACE, BiomePoolTier.COMMON, TimeOfDay.DAY], - [BiomeId.SPACE, BiomePoolTier.BOSS, TimeOfDay.DAY] + [BiomeId.SPACE, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.SPACE, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.BARBOACH, PokemonType.WATER, PokemonType.GROUND, [ @@ -1730,16 +1782,16 @@ export function initBiomes() { ] ], [SpeciesId.FEEBAS, PokemonType.WATER, -1, [ - [BiomeId.SEABED, BiomePoolTier.ULTRA_RARE] + [BiomeId.SEABED, BiomePoolTier.RARE] ] ], [SpeciesId.MILOTIC, PokemonType.WATER, -1, [ - [BiomeId.SEABED, BiomePoolTier.BOSS_SUPER_RARE] + [BiomeId.SEABED, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.CASTFORM, PokemonType.NORMAL, -1, [ - [BiomeId.METROPOLIS, BiomePoolTier.ULTRA_RARE], - [BiomeId.METROPOLIS, BiomePoolTier.BOSS_RARE] + [BiomeId.METROPOLIS, BiomePoolTier.RARE], + [BiomeId.METROPOLIS, BiomePoolTier.BOSS] ] ], [SpeciesId.KECLEON, PokemonType.NORMAL, -1, [ @@ -1748,7 +1800,8 @@ export function initBiomes() { ] ], [SpeciesId.SHUPPET, PokemonType.GHOST, -1, [ - [BiomeId.GRAVEYARD, BiomePoolTier.COMMON] + [BiomeId.GRAVEYARD, BiomePoolTier.COMMON], + [BiomeId.SLUM, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], ] ], [SpeciesId.BANETTE, PokemonType.GHOST, -1, [ @@ -1786,12 +1839,14 @@ export function initBiomes() { [SpeciesId.WYNAUT, PokemonType.PSYCHIC, -1, [] ], [SpeciesId.SNORUNT, PokemonType.ICE, -1, [ - [BiomeId.ICE_CAVE, BiomePoolTier.UNCOMMON] + [BiomeId.ICE_CAVE, BiomePoolTier.COMMON] ] ], [SpeciesId.GLALIE, PokemonType.ICE, -1, [ - [BiomeId.ICE_CAVE, BiomePoolTier.UNCOMMON], - [BiomeId.ICE_CAVE, BiomePoolTier.BOSS] + [BiomeId.ICE_CAVE, BiomePoolTier.COMMON], + [BiomeId.ICE_CAVE, BiomePoolTier.BOSS], + [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.SPHEAL, PokemonType.ICE, PokemonType.WATER, [ @@ -1844,17 +1899,18 @@ export function initBiomes() { ], [SpeciesId.BELDUM, PokemonType.STEEL, PokemonType.PSYCHIC, [ [BiomeId.FACTORY, BiomePoolTier.SUPER_RARE], - [BiomeId.SPACE, BiomePoolTier.RARE] + [BiomeId.SPACE, BiomePoolTier.SUPER_RARE] ] ], [SpeciesId.METANG, PokemonType.STEEL, PokemonType.PSYCHIC, [ [BiomeId.FACTORY, BiomePoolTier.SUPER_RARE], - [BiomeId.SPACE, BiomePoolTier.RARE] + [BiomeId.SPACE, BiomePoolTier.SUPER_RARE] ] ], [SpeciesId.METAGROSS, PokemonType.STEEL, PokemonType.PSYCHIC, [ [BiomeId.FACTORY, BiomePoolTier.SUPER_RARE], - [BiomeId.SPACE, BiomePoolTier.RARE], + [BiomeId.FACTORY, BiomePoolTier.BOSS_RARE], + [BiomeId.SPACE, BiomePoolTier.SUPER_RARE], [BiomeId.SPACE, BiomePoolTier.BOSS_RARE] ] ], @@ -2026,8 +2082,7 @@ export function initBiomes() { [BiomeId.FOREST, BiomePoolTier.BOSS], [BiomeId.BEACH, BiomePoolTier.UNCOMMON], [BiomeId.BEACH, BiomePoolTier.BOSS], - [BiomeId.SLUM, BiomePoolTier.UNCOMMON], - [BiomeId.SLUM, BiomePoolTier.BOSS] + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.MOTHIM, PokemonType.BUG, PokemonType.FLYING, [ @@ -2043,7 +2098,7 @@ export function initBiomes() { ] ], [SpeciesId.VESPIQUEN, PokemonType.BUG, PokemonType.FLYING, [ - [BiomeId.GRASS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.GRASS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.FOREST, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] @@ -2054,17 +2109,17 @@ export function initBiomes() { ] ], [SpeciesId.BUIZEL, PokemonType.WATER, -1, [ - [BiomeId.SEA, BiomePoolTier.COMMON] + [BiomeId.SEA, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.FLOATZEL, PokemonType.WATER, -1, [ - [BiomeId.SEA, BiomePoolTier.COMMON], + [BiomeId.SEA, BiomePoolTier.UNCOMMON], [BiomeId.SEA, BiomePoolTier.BOSS] ] ], [SpeciesId.CHERUBI, PokemonType.GRASS, -1, [ [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.GRASS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.GRASS, BiomePoolTier.UNCOMMON], [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], @@ -2111,13 +2166,12 @@ export function initBiomes() { [BiomeId.GRAVEYARD, BiomePoolTier.BOSS] ] ], - [SpeciesId.HONCHKROW, PokemonType.DARK, PokemonType.FLYING, [ - [BiomeId.ABYSS, BiomePoolTier.BOSS] - ] + [SpeciesId.HONCHKROW, PokemonType.DARK, PokemonType.FLYING, [] ], [SpeciesId.GLAMEOW, PokemonType.NORMAL, -1, [ [BiomeId.METROPOLIS, BiomePoolTier.UNCOMMON], - [BiomeId.MEADOW, BiomePoolTier.UNCOMMON] + [BiomeId.MEADOW, BiomePoolTier.UNCOMMON], + [BiomeId.SLUM, BiomePoolTier.COMMON] ] ], [SpeciesId.PURUGLY, PokemonType.NORMAL, -1, [ @@ -2131,33 +2185,38 @@ export function initBiomes() { ] ], [SpeciesId.STUNKY, PokemonType.POISON, PokemonType.DARK, [ - [BiomeId.SLUM, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.SKUNTANK, PokemonType.POISON, PokemonType.DARK, [ - [BiomeId.SLUM, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SLUM, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SLUM, BiomePoolTier.UNCOMMON], + [BiomeId.SLUM, BiomePoolTier.BOSS] ] ], [SpeciesId.BRONZOR, PokemonType.STEEL, PokemonType.PSYCHIC, [ - [BiomeId.FACTORY, BiomePoolTier.UNCOMMON], + [BiomeId.FACTORY, BiomePoolTier.COMMON], [BiomeId.SPACE, BiomePoolTier.COMMON], [BiomeId.LABORATORY, BiomePoolTier.COMMON] ] ], [SpeciesId.BRONZONG, PokemonType.STEEL, PokemonType.PSYCHIC, [ - [BiomeId.FACTORY, BiomePoolTier.UNCOMMON], + [BiomeId.FACTORY, BiomePoolTier.COMMON], + [BiomeId.FACTORY, BiomePoolTier.BOSS], [BiomeId.SPACE, BiomePoolTier.COMMON], [BiomeId.SPACE, BiomePoolTier.BOSS], [BiomeId.LABORATORY, BiomePoolTier.COMMON], [BiomeId.LABORATORY, BiomePoolTier.BOSS] ] ], - [SpeciesId.BONSLY, PokemonType.ROCK, -1, [] + [SpeciesId.BONSLY, PokemonType.ROCK, -1, [ + [BiomeId.GRASS, BiomePoolTier.RARE] + ] ], [SpeciesId.MIME_JR, PokemonType.PSYCHIC, PokemonType.FAIRY, [] ], - [SpeciesId.HAPPINY, PokemonType.NORMAL, -1, [] + [SpeciesId.HAPPINY, PokemonType.NORMAL, -1, [ + [BiomeId.TOWN, BiomePoolTier.RARE] + ] ], [SpeciesId.CHATOT, PokemonType.NORMAL, PokemonType.FLYING, [ [BiomeId.JUNGLE, BiomePoolTier.SUPER_RARE] @@ -2166,28 +2225,36 @@ export function initBiomes() { [SpeciesId.SPIRITOMB, PokemonType.GHOST, PokemonType.DARK, [ [BiomeId.GRAVEYARD, BiomePoolTier.SUPER_RARE], [BiomeId.ABYSS, BiomePoolTier.RARE], - [BiomeId.ABYSS, BiomePoolTier.BOSS] + [BiomeId.ABYSS, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.GIBLE, PokemonType.DRAGON, PokemonType.GROUND, [ [BiomeId.MOUNTAIN, BiomePoolTier.SUPER_RARE], + [BiomeId.DESERT, BiomePoolTier.SUPER_RARE], [BiomeId.WASTELAND, BiomePoolTier.COMMON] ] ], [SpeciesId.GABITE, PokemonType.DRAGON, PokemonType.GROUND, [ [BiomeId.MOUNTAIN, BiomePoolTier.SUPER_RARE], + [BiomeId.DESERT, BiomePoolTier.SUPER_RARE], [BiomeId.WASTELAND, BiomePoolTier.COMMON] ] ], [SpeciesId.GARCHOMP, PokemonType.DRAGON, PokemonType.GROUND, [ [BiomeId.MOUNTAIN, BiomePoolTier.SUPER_RARE], + [BiomeId.DESERT, BiomePoolTier.SUPER_RARE], + [BiomeId.DESERT, BiomePoolTier.BOSS_RARE], [BiomeId.WASTELAND, BiomePoolTier.COMMON], [BiomeId.WASTELAND, BiomePoolTier.BOSS] ] ], - [SpeciesId.MUNCHLAX, PokemonType.NORMAL, -1, [] + [SpeciesId.MUNCHLAX, PokemonType.NORMAL, -1, [ + [BiomeId.TOWN, BiomePoolTier.ULTRA_RARE] + ] ], - [SpeciesId.RIOLU, PokemonType.FIGHTING, -1, [] + [SpeciesId.RIOLU, PokemonType.FIGHTING, -1, [ + [BiomeId.TOWN, BiomePoolTier.SUPER_RARE] + ] ], [SpeciesId.LUCARIO, PokemonType.FIGHTING, PokemonType.STEEL, [ [BiomeId.DOJO, BiomePoolTier.RARE], @@ -2195,12 +2262,12 @@ export function initBiomes() { ] ], [SpeciesId.HIPPOPOTAS, PokemonType.GROUND, -1, [ - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.DESERT, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.HIPPOWDON, PokemonType.GROUND, -1, [ - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.DESERT, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.DESERT, BiomePoolTier.UNCOMMON], + [BiomeId.DESERT, BiomePoolTier.BOSS] ] ], [SpeciesId.SKORUPI, PokemonType.POISON, PokemonType.BUG, [ @@ -2233,11 +2300,11 @@ export function initBiomes() { ] ], [SpeciesId.FINNEON, PokemonType.WATER, -1, [ - [BiomeId.SEA, BiomePoolTier.COMMON, TimeOfDay.NIGHT] + [BiomeId.SEA, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.LUMINEON, PokemonType.WATER, -1, [ - [BiomeId.SEA, BiomePoolTier.COMMON, TimeOfDay.NIGHT], + [BiomeId.SEA, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.SEA, BiomePoolTier.BOSS, TimeOfDay.NIGHT] ] ], @@ -2257,11 +2324,14 @@ export function initBiomes() { ] ], [SpeciesId.WEAVILE, PokemonType.DARK, PokemonType.ICE, [ - [BiomeId.ICE_CAVE, BiomePoolTier.BOSS] + [BiomeId.SLUM, BiomePoolTier.BOSS_RARE], + [BiomeId.ICE_CAVE, BiomePoolTier.BOSS], + [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.MAGNEZONE, PokemonType.ELECTRIC, PokemonType.STEEL, [ [BiomeId.POWER_PLANT, BiomePoolTier.BOSS], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.BOSS], [BiomeId.LABORATORY, BiomePoolTier.BOSS] ] ], @@ -2278,11 +2348,13 @@ export function initBiomes() { ] ], [SpeciesId.ELECTIVIRE, PokemonType.ELECTRIC, -1, [ - [BiomeId.POWER_PLANT, BiomePoolTier.BOSS] + [BiomeId.POWER_PLANT, BiomePoolTier.BOSS], + [BiomeId.FACTORY, BiomePoolTier.BOSS] ] ], [SpeciesId.MAGMORTAR, PokemonType.FIRE, -1, [ - [BiomeId.VOLCANO, BiomePoolTier.BOSS] + [BiomeId.VOLCANO, BiomePoolTier.BOSS], + [BiomeId.FACTORY, BiomePoolTier.BOSS] ] ], [SpeciesId.TOGEKISS, PokemonType.FAIRY, PokemonType.FLYING, [ @@ -2302,7 +2374,7 @@ export function initBiomes() { ] ], [SpeciesId.GLISCOR, PokemonType.GROUND, PokemonType.FLYING, [ - [BiomeId.BADLANDS, BiomePoolTier.BOSS] + [BiomeId.BADLANDS, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.MAMOSWINE, PokemonType.ICE, PokemonType.GROUND, [ @@ -2311,7 +2383,7 @@ export function initBiomes() { ], [SpeciesId.PORYGON_Z, PokemonType.NORMAL, -1, [ [BiomeId.SPACE, BiomePoolTier.BOSS_RARE], - [BiomeId.LABORATORY, BiomePoolTier.BOSS] + [BiomeId.LABORATORY, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.GALLADE, PokemonType.PSYCHIC, PokemonType.FIGHTING, [ @@ -2320,7 +2392,8 @@ export function initBiomes() { ] ], [SpeciesId.PROBOPASS, PokemonType.ROCK, PokemonType.STEEL, [ - [BiomeId.CAVE, BiomePoolTier.BOSS] + [BiomeId.CAVE, BiomePoolTier.BOSS], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.BOSS] ] ], [SpeciesId.DUSKNOIR, PokemonType.GHOST, -1, [ @@ -2328,23 +2401,18 @@ export function initBiomes() { ] ], [SpeciesId.FROSLASS, PokemonType.ICE, PokemonType.GHOST, [ - [BiomeId.ICE_CAVE, BiomePoolTier.RARE], - [BiomeId.ICE_CAVE, BiomePoolTier.BOSS] + [BiomeId.ABYSS, BiomePoolTier.RARE], + [BiomeId.ABYSS, BiomePoolTier.BOSS], + [BiomeId.ICE_CAVE, BiomePoolTier.COMMON], + [BiomeId.ICE_CAVE, BiomePoolTier.BOSS], + [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.ROTOM, PokemonType.ELECTRIC, PokemonType.GHOST, [ - [BiomeId.LABORATORY, BiomePoolTier.SUPER_RARE], - [BiomeId.LABORATORY, BiomePoolTier.BOSS_SUPER_RARE], - [BiomeId.VOLCANO, BiomePoolTier.SUPER_RARE], - [BiomeId.VOLCANO, BiomePoolTier.BOSS_SUPER_RARE], - [BiomeId.SEA, BiomePoolTier.SUPER_RARE], - [BiomeId.SEA, BiomePoolTier.BOSS_SUPER_RARE], - [BiomeId.ICE_CAVE, BiomePoolTier.SUPER_RARE], - [BiomeId.ICE_CAVE, BiomePoolTier.BOSS_SUPER_RARE], - [BiomeId.MOUNTAIN, BiomePoolTier.SUPER_RARE], - [BiomeId.MOUNTAIN, BiomePoolTier.BOSS_SUPER_RARE], - [BiomeId.TALL_GRASS, BiomePoolTier.SUPER_RARE], - [BiomeId.TALL_GRASS, BiomePoolTier.BOSS_SUPER_RARE] + [BiomeId.POWER_PLANT, BiomePoolTier.RARE], + [BiomeId.LABORATORY, BiomePoolTier.RARE], + [BiomeId.LABORATORY, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.UXIE, PokemonType.PSYCHIC, -1, [ @@ -2445,18 +2513,13 @@ export function initBiomes() { ] ], [SpeciesId.PATRAT, PokemonType.NORMAL, -1, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.METROPOLIS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.METROPOLIS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SLUM, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.TOWN, BiomePoolTier.COMMON], + [BiomeId.METROPOLIS, BiomePoolTier.COMMON] ] ], [SpeciesId.WATCHOG, PokemonType.NORMAL, -1, [ [BiomeId.METROPOLIS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.METROPOLIS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SLUM, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SLUM, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.METROPOLIS, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.LILLIPUP, PokemonType.NORMAL, -1, [ @@ -2475,13 +2538,10 @@ export function initBiomes() { ], [SpeciesId.PURRLOIN, PokemonType.DARK, -1, [ [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.ABYSS, BiomePoolTier.COMMON], [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.LIEPARD, PokemonType.DARK, -1, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON], - [BiomeId.ABYSS, BiomePoolTier.BOSS], [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], @@ -2519,11 +2579,13 @@ export function initBiomes() { ] ], [SpeciesId.MUNNA, PokemonType.PSYCHIC, -1, [ - [BiomeId.SPACE, BiomePoolTier.COMMON] + [BiomeId.SPACE, BiomePoolTier.COMMON], + [BiomeId.LABORATORY, BiomePoolTier.COMMON] ] ], [SpeciesId.MUSHARNA, PokemonType.PSYCHIC, -1, [ [BiomeId.SPACE, BiomePoolTier.COMMON], + [BiomeId.LABORATORY, BiomePoolTier.COMMON], [BiomeId.SPACE, BiomePoolTier.BOSS] ] ], @@ -2574,26 +2636,29 @@ export function initBiomes() { ] ], [SpeciesId.WOOBAT, PokemonType.PSYCHIC, PokemonType.FLYING, [ - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.CAVE, BiomePoolTier.COMMON], + [BiomeId.ABYSS, BiomePoolTier.COMMON] ] ], [SpeciesId.SWOOBAT, PokemonType.PSYCHIC, PokemonType.FLYING, [ [BiomeId.CAVE, BiomePoolTier.COMMON], - [BiomeId.CAVE, BiomePoolTier.BOSS] + [BiomeId.CAVE, BiomePoolTier.BOSS], + [BiomeId.ABYSS, BiomePoolTier.COMMON] ] ], [SpeciesId.DRILBUR, PokemonType.GROUND, -1, [ [BiomeId.BADLANDS, BiomePoolTier.COMMON], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.EXCADRILL, PokemonType.GROUND, PokemonType.STEEL, [ [BiomeId.BADLANDS, BiomePoolTier.COMMON], [BiomeId.BADLANDS, BiomePoolTier.BOSS], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.COMMON] + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.AUDINO, PokemonType.NORMAL, -1, [ + [BiomeId.TALL_GRASS, BiomePoolTier.RARE], [BiomeId.FAIRY_CAVE, BiomePoolTier.RARE], [BiomeId.FAIRY_CAVE, BiomePoolTier.BOSS] ] @@ -2652,35 +2717,41 @@ export function initBiomes() { ] ], [SpeciesId.VENIPEDE, PokemonType.BUG, PokemonType.POISON, [ - [BiomeId.TOWN, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.TOWN, BiomePoolTier.UNCOMMON], + [BiomeId.GRASS, BiomePoolTier.COMMON], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.WHIRLIPEDE, PokemonType.BUG, PokemonType.POISON, [ + [BiomeId.GRASS, BiomePoolTier.COMMON], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.SCOLIPEDE, PokemonType.BUG, PokemonType.POISON, [ + [BiomeId.GRASS, BiomePoolTier.COMMON], + [BiomeId.GRASS, BiomePoolTier.BOSS], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.FOREST, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.COTTONEE, PokemonType.GRASS, PokemonType.FAIRY, [ [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.GRASS, BiomePoolTier.COMMON], [BiomeId.MEADOW, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.WHIMSICOTT, PokemonType.GRASS, PokemonType.FAIRY, [ - [BiomeId.GRASS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.GRASS, BiomePoolTier.BOSS] ] ], [SpeciesId.PETILIL, PokemonType.GRASS, -1, [ - [BiomeId.GRASS, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.GRASS, BiomePoolTier.COMMON], [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.LILLIGANT, PokemonType.GRASS, -1, [ + [BiomeId.GRASS, BiomePoolTier.COMMON], + [BiomeId.GRASS, BiomePoolTier.BOSS], [BiomeId.FOREST, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], @@ -2689,19 +2760,16 @@ export function initBiomes() { ] ], [SpeciesId.SANDILE, PokemonType.GROUND, PokemonType.DARK, [ - [BiomeId.DESERT, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.DESERT, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.KROKOROK, PokemonType.GROUND, PokemonType.DARK, [ - [BiomeId.DESERT, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.DESERT, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.KROOKODILE, PokemonType.GROUND, PokemonType.DARK, [ - [BiomeId.DESERT, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.DESERT, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.DESERT, BiomePoolTier.UNCOMMON], + [BiomeId.DESERT, BiomePoolTier.BOSS] ] ], [SpeciesId.DARUMAKA, PokemonType.FIRE, -1, [ @@ -2714,8 +2782,8 @@ export function initBiomes() { ] ], [SpeciesId.MARACTUS, PokemonType.GRASS, -1, [ - [BiomeId.DESERT, BiomePoolTier.UNCOMMON], - [BiomeId.DESERT, BiomePoolTier.BOSS] + [BiomeId.DESERT, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.DESERT, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.DWEBBLE, PokemonType.BUG, PokemonType.ROCK, [ @@ -2729,27 +2797,34 @@ export function initBiomes() { ], [SpeciesId.SCRAGGY, PokemonType.DARK, PokemonType.FIGHTING, [ [BiomeId.DOJO, BiomePoolTier.UNCOMMON], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON] + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON], + [BiomeId.SLUM, BiomePoolTier.COMMON] ] ], [SpeciesId.SCRAFTY, PokemonType.DARK, PokemonType.FIGHTING, [ [BiomeId.DOJO, BiomePoolTier.UNCOMMON], [BiomeId.DOJO, BiomePoolTier.BOSS], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON] + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON], + [BiomeId.SLUM, BiomePoolTier.BOSS] ] ], [SpeciesId.SIGILYPH, PokemonType.PSYCHIC, PokemonType.FLYING, [ + [BiomeId.DESERT, BiomePoolTier.RARE], + [BiomeId.DESERT, BiomePoolTier.BOSS_RARE], [BiomeId.RUINS, BiomePoolTier.UNCOMMON], [BiomeId.RUINS, BiomePoolTier.BOSS], [BiomeId.SPACE, BiomePoolTier.RARE] ] ], [SpeciesId.YAMASK, PokemonType.GHOST, -1, [ + [BiomeId.DESERT, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.GRAVEYARD, BiomePoolTier.UNCOMMON], [BiomeId.TEMPLE, BiomePoolTier.COMMON] ] ], [SpeciesId.COFAGRIGUS, PokemonType.GHOST, -1, [ + [BiomeId.DESERT, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.DESERT, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], [BiomeId.GRAVEYARD, BiomePoolTier.UNCOMMON], [BiomeId.TEMPLE, BiomePoolTier.COMMON], [BiomeId.TEMPLE, BiomePoolTier.BOSS] @@ -2786,6 +2861,7 @@ export function initBiomes() { ] ], [SpeciesId.ZORUA, PokemonType.DARK, -1, [ + [BiomeId.TOWN, BiomePoolTier.ULTRA_RARE], [BiomeId.ABYSS, BiomePoolTier.RARE] ] ], @@ -2804,16 +2880,19 @@ export function initBiomes() { ] ], [SpeciesId.GOTHITA, PokemonType.PSYCHIC, -1, [ - [BiomeId.RUINS, BiomePoolTier.RARE] + [BiomeId.RUINS, BiomePoolTier.RARE], + [BiomeId.SLUM, BiomePoolTier.RARE] ] ], [SpeciesId.GOTHORITA, PokemonType.PSYCHIC, -1, [ - [BiomeId.RUINS, BiomePoolTier.RARE] + [BiomeId.RUINS, BiomePoolTier.RARE], + [BiomeId.SLUM, BiomePoolTier.RARE] ] ], [SpeciesId.GOTHITELLE, PokemonType.PSYCHIC, -1, [ [BiomeId.RUINS, BiomePoolTier.RARE], - [BiomeId.RUINS, BiomePoolTier.BOSS] + [BiomeId.RUINS, BiomePoolTier.BOSS], + [BiomeId.SLUM, BiomePoolTier.RARE] ] ], [SpeciesId.SOLOSIS, PokemonType.PSYCHIC, -1, [ @@ -2877,7 +2956,7 @@ export function initBiomes() { ] ], [SpeciesId.FOONGUS, PokemonType.GRASS, PokemonType.POISON, [ - [BiomeId.GRASS, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.GRASS, BiomePoolTier.UNCOMMON], [BiomeId.JUNGLE, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.JUNGLE, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] @@ -2992,17 +3071,20 @@ export function initBiomes() { ] ], [SpeciesId.CUBCHOO, PokemonType.ICE, -1, [ - [BiomeId.ICE_CAVE, BiomePoolTier.COMMON] + [BiomeId.ICE_CAVE, BiomePoolTier.COMMON], + [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.BEARTIC, PokemonType.ICE, -1, [ [BiomeId.ICE_CAVE, BiomePoolTier.COMMON], - [BiomeId.ICE_CAVE, BiomePoolTier.BOSS] + [BiomeId.ICE_CAVE, BiomePoolTier.BOSS], + [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.CRYOGONAL, PokemonType.ICE, -1, [ [BiomeId.ICE_CAVE, BiomePoolTier.RARE], - [BiomeId.ICE_CAVE, BiomePoolTier.BOSS] + [BiomeId.ICE_CAVE, BiomePoolTier.BOSS], + [BiomeId.SNOWY_FOREST, BiomePoolTier.RARE] ] ], [SpeciesId.SHELMET, PokemonType.BUG, -1, [ @@ -3042,11 +3124,13 @@ export function initBiomes() { ] ], [SpeciesId.PAWNIARD, PokemonType.DARK, PokemonType.STEEL, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON] + [BiomeId.TALL_GRASS, BiomePoolTier.RARE], + [BiomeId.SLUM, BiomePoolTier.RARE] ] ], [SpeciesId.BISHARP, PokemonType.DARK, PokemonType.STEEL, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON] + [BiomeId.TALL_GRASS, BiomePoolTier.RARE], + [BiomeId.SLUM, BiomePoolTier.RARE] ] ], [SpeciesId.BOUFFALANT, PokemonType.NORMAL, -1, [ @@ -3084,18 +3168,18 @@ export function initBiomes() { ], [SpeciesId.DEINO, PokemonType.DARK, PokemonType.DRAGON, [ [BiomeId.WASTELAND, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.ABYSS, BiomePoolTier.RARE] + [BiomeId.ABYSS, BiomePoolTier.SUPER_RARE] ] ], [SpeciesId.ZWEILOUS, PokemonType.DARK, PokemonType.DRAGON, [ [BiomeId.WASTELAND, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.ABYSS, BiomePoolTier.RARE] + [BiomeId.ABYSS, BiomePoolTier.SUPER_RARE] ] ], [SpeciesId.HYDREIGON, PokemonType.DARK, PokemonType.DRAGON, [ [BiomeId.WASTELAND, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.ABYSS, BiomePoolTier.RARE], - [BiomeId.ABYSS, BiomePoolTier.BOSS] + [BiomeId.ABYSS, BiomePoolTier.SUPER_RARE], + [BiomeId.ABYSS, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.LARVESTA, PokemonType.BUG, PokemonType.FIRE, [ @@ -3230,15 +3314,18 @@ export function initBiomes() { ] ], [SpeciesId.SCATTERBUG, PokemonType.BUG, -1, [ - [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON] ] ], [SpeciesId.SPEWPA, PokemonType.BUG, -1, [ - [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.TOWN, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON] ] ], [SpeciesId.VIVILLON, PokemonType.BUG, PokemonType.FLYING, [ - [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.FOREST, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.TALL_GRASS, BiomePoolTier.COMMON] ] ], [SpeciesId.LITLEO, PokemonType.FIRE, PokemonType.NORMAL, [ @@ -3263,7 +3350,8 @@ export function initBiomes() { ] ], [SpeciesId.SKIDDO, PokemonType.GRASS, -1, [ - [BiomeId.MOUNTAIN, BiomePoolTier.COMMON] + [BiomeId.MOUNTAIN, BiomePoolTier.COMMON], + [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.GOGOAT, PokemonType.GRASS, -1, [ @@ -3273,14 +3361,16 @@ export function initBiomes() { ], [SpeciesId.PANCHAM, PokemonType.FIGHTING, -1, [ [BiomeId.DOJO, BiomePoolTier.RARE], - [BiomeId.JUNGLE, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.JUNGLE, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.PANGORO, PokemonType.FIGHTING, PokemonType.DARK, [ [BiomeId.DOJO, BiomePoolTier.RARE], [BiomeId.DOJO, BiomePoolTier.BOSS_RARE], [BiomeId.JUNGLE, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.JUNGLE, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.JUNGLE, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.SLUM, BiomePoolTier.BOSS] ] ], [SpeciesId.FURFROU, PokemonType.NORMAL, -1, [ @@ -3364,7 +3454,7 @@ export function initBiomes() { ] ], [SpeciesId.HELIOPTILE, PokemonType.ELECTRIC, PokemonType.NORMAL, [ - [BiomeId.DESERT, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.HELIOLISK, PokemonType.ELECTRIC, PokemonType.NORMAL, [ @@ -3425,6 +3515,7 @@ export function initBiomes() { ], [SpeciesId.KLEFKI, PokemonType.STEEL, PokemonType.FAIRY, [ [BiomeId.FACTORY, BiomePoolTier.UNCOMMON], + [BiomeId.LABORATORY, BiomePoolTier.UNCOMMON], [BiomeId.FACTORY, BiomePoolTier.BOSS] ] ], @@ -3450,14 +3541,17 @@ export function initBiomes() { ], [SpeciesId.AVALUGG, PokemonType.ICE, -1, [ [BiomeId.ICE_CAVE, BiomePoolTier.COMMON], - [BiomeId.ICE_CAVE, BiomePoolTier.BOSS] + [BiomeId.ICE_CAVE, BiomePoolTier.BOSS], + [BiomeId.SNOWY_FOREST, BiomePoolTier.RARE] ] ], [SpeciesId.NOIBAT, PokemonType.FLYING, PokemonType.DRAGON, [ - [BiomeId.CAVE, BiomePoolTier.UNCOMMON] + [BiomeId.CAVE, BiomePoolTier.UNCOMMON], + [BiomeId.GRASS, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.NOIVERN, PokemonType.FLYING, PokemonType.DRAGON, [ + [BiomeId.GRASS, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.CAVE, BiomePoolTier.UNCOMMON], [BiomeId.CAVE, BiomePoolTier.BOSS] ] @@ -3590,7 +3684,7 @@ export function initBiomes() { ] ], [SpeciesId.ROCKRUFF, PokemonType.ROCK, -1, [ - [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, TimeOfDay.DAY], + [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], [BiomeId.FOREST, BiomePoolTier.UNCOMMON, TimeOfDay.NIGHT], [BiomeId.CAVE, BiomePoolTier.UNCOMMON, TimeOfDay.DUSK] ] @@ -3661,11 +3755,11 @@ export function initBiomes() { ] ], [SpeciesId.SALANDIT, PokemonType.POISON, PokemonType.FIRE, [ - [BiomeId.VOLCANO, BiomePoolTier.COMMON] + [BiomeId.VOLCANO, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.SALAZZLE, PokemonType.POISON, PokemonType.FIRE, [ - [BiomeId.VOLCANO, BiomePoolTier.COMMON], + [BiomeId.VOLCANO, BiomePoolTier.UNCOMMON], [BiomeId.VOLCANO, BiomePoolTier.BOSS] ] ], @@ -3984,13 +4078,10 @@ export function initBiomes() { ] ], [SpeciesId.NICKIT, PokemonType.DARK, -1, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON] + [BiomeId.PLAINS, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], - [SpeciesId.THIEVUL, PokemonType.DARK, -1, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON], - [BiomeId.ABYSS, BiomePoolTier.BOSS] - ] + [SpeciesId.THIEVUL, PokemonType.DARK, -1, [] ], [SpeciesId.GOSSIFLEUR, PokemonType.GRASS, -1, [ [BiomeId.MEADOW, BiomePoolTier.COMMON] @@ -4076,11 +4167,13 @@ export function initBiomes() { [BiomeId.SEABED, BiomePoolTier.BOSS] ] ], - [SpeciesId.TOXEL, PokemonType.ELECTRIC, PokemonType.POISON, [] + [SpeciesId.TOXEL, PokemonType.ELECTRIC, PokemonType.POISON, [ + [BiomeId.SLUM, BiomePoolTier.RARE] + ] ], [SpeciesId.TOXTRICITY, PokemonType.ELECTRIC, PokemonType.POISON, [ - [BiomeId.SLUM, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SLUM, BiomePoolTier.BOSS_RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SLUM, BiomePoolTier.RARE], + [BiomeId.SLUM, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.SIZZLIPEDE, PokemonType.FIRE, PokemonType.BUG, [ @@ -4137,13 +4230,13 @@ export function initBiomes() { ] ], [SpeciesId.OBSTAGOON, PokemonType.DARK, PokemonType.NORMAL, [ - [BiomeId.SLUM, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SLUM, BiomePoolTier.BOSS_RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SLUM, BiomePoolTier.UNCOMMON], + [BiomeId.SLUM, BiomePoolTier.BOSS] ] ], [SpeciesId.PERRSERKER, PokemonType.STEEL, -1, [ - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE, TimeOfDay.DUSK], - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.BOSS_RARE, TimeOfDay.DUSK] + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.CURSOLA, PokemonType.GHOST, -1, [ @@ -4185,22 +4278,24 @@ export function initBiomes() { ], [SpeciesId.SNOM, PokemonType.ICE, PokemonType.BUG, [ [BiomeId.ICE_CAVE, BiomePoolTier.COMMON], - [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON] ] ], [SpeciesId.FROSMOTH, PokemonType.ICE, PokemonType.BUG, [ [BiomeId.ICE_CAVE, BiomePoolTier.COMMON], - [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON], + [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS] ] ], [SpeciesId.STONJOURNER, PokemonType.ROCK, -1, [ + [BiomeId.DESERT, BiomePoolTier.RARE], + [BiomeId.DESERT, BiomePoolTier.BOSS_RARE], [BiomeId.RUINS, BiomePoolTier.RARE] ] ], [SpeciesId.EISCUE, PokemonType.ICE, -1, [ [BiomeId.ICE_CAVE, BiomePoolTier.UNCOMMON], - [BiomeId.SNOWY_FOREST, BiomePoolTier.COMMON] + [BiomeId.SNOWY_FOREST, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.INDEEDEE, PokemonType.PSYCHIC, PokemonType.NORMAL, [ @@ -4241,20 +4336,24 @@ export function initBiomes() { ] ], [SpeciesId.DURALUDON, PokemonType.STEEL, PokemonType.DRAGON, [ - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE] + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.SUPER_RARE] ] ], [SpeciesId.DREEPY, PokemonType.DRAGON, PokemonType.GHOST, [ - [BiomeId.WASTELAND, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.WASTELAND, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.ABYSS, BiomePoolTier.SUPER_RARE] ] ], [SpeciesId.DRAKLOAK, PokemonType.DRAGON, PokemonType.GHOST, [ - [BiomeId.WASTELAND, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.WASTELAND, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.ABYSS, BiomePoolTier.SUPER_RARE] ] ], [SpeciesId.DRAGAPULT, PokemonType.DRAGON, PokemonType.GHOST, [ [BiomeId.WASTELAND, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.WASTELAND, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.WASTELAND, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.ABYSS, BiomePoolTier.SUPER_RARE], + [BiomeId.ABYSS, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.ZACIAN, PokemonType.FAIRY, -1, [ @@ -4309,12 +4408,12 @@ export function initBiomes() { ] ], [SpeciesId.WYRDEER, PokemonType.NORMAL, PokemonType.PSYCHIC, [ - [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS] ] ], [SpeciesId.KLEAVOR, PokemonType.BUG, PokemonType.ROCK, [ [BiomeId.JUNGLE, BiomePoolTier.SUPER_RARE], - [BiomeId.JUNGLE, BiomePoolTier.BOSS_ULTRA_RARE] + [BiomeId.JUNGLE, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.URSALUNA, PokemonType.GROUND, PokemonType.NORMAL, [ @@ -4427,7 +4526,7 @@ export function initBiomes() { ] ], [SpeciesId.TANDEMAUS, PokemonType.NORMAL, -1, [ - [BiomeId.TOWN, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.TOWN, BiomePoolTier.RARE], [BiomeId.METROPOLIS, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], @@ -4461,24 +4560,25 @@ export function initBiomes() { ], [SpeciesId.SQUAWKABILLY, PokemonType.NORMAL, PokemonType.FLYING, [ [BiomeId.METROPOLIS, BiomePoolTier.UNCOMMON], - [BiomeId.FOREST, BiomePoolTier.RARE] + [BiomeId.FOREST, BiomePoolTier.RARE], + [BiomeId.SLUM, BiomePoolTier.RARE] ] ], [SpeciesId.NACLI, PokemonType.ROCK, -1, [ - [BiomeId.MOUNTAIN, BiomePoolTier.UNCOMMON], - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.MOUNTAIN, BiomePoolTier.RARE], + [BiomeId.CAVE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.NACLSTACK, PokemonType.ROCK, -1, [ - [BiomeId.MOUNTAIN, BiomePoolTier.UNCOMMON], - [BiomeId.CAVE, BiomePoolTier.COMMON] + [BiomeId.MOUNTAIN, BiomePoolTier.RARE], + [BiomeId.CAVE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.GARGANACL, PokemonType.ROCK, -1, [ - [BiomeId.MOUNTAIN, BiomePoolTier.UNCOMMON], - [BiomeId.MOUNTAIN, BiomePoolTier.BOSS], - [BiomeId.CAVE, BiomePoolTier.COMMON], - [BiomeId.CAVE, BiomePoolTier.BOSS] + [BiomeId.MOUNTAIN, BiomePoolTier.RARE], + [BiomeId.MOUNTAIN, BiomePoolTier.BOSS_RARE], + [BiomeId.CAVE, BiomePoolTier.UNCOMMON], + [BiomeId.CAVE, BiomePoolTier.BOSS_RARE] ] ], [SpeciesId.CHARCADET, PokemonType.FIRE, -1, [ @@ -4514,13 +4614,10 @@ export function initBiomes() { ] ], [SpeciesId.MASCHIFF, PokemonType.DARK, -1, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON] + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], - [SpeciesId.MABOSSTIFF, PokemonType.DARK, -1, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON], - [BiomeId.ABYSS, BiomePoolTier.BOSS] - ] + [SpeciesId.MABOSSTIFF, PokemonType.DARK, -1, [] ], [SpeciesId.SHROODLE, PokemonType.POISON, PokemonType.NORMAL, [ [BiomeId.FOREST, BiomePoolTier.COMMON] @@ -4532,11 +4629,11 @@ export function initBiomes() { ] ], [SpeciesId.BRAMBLIN, PokemonType.GRASS, PokemonType.GHOST, [ - [BiomeId.DESERT, BiomePoolTier.UNCOMMON] + [BiomeId.DESERT, BiomePoolTier.COMMON] ] ], [SpeciesId.BRAMBLEGHAST, PokemonType.GRASS, PokemonType.GHOST, [ - [BiomeId.DESERT, BiomePoolTier.UNCOMMON], + [BiomeId.DESERT, BiomePoolTier.COMMON], [BiomeId.DESERT, BiomePoolTier.BOSS] ] ], @@ -4550,7 +4647,7 @@ export function initBiomes() { ] ], [SpeciesId.KLAWF, PokemonType.ROCK, -1, [ - [BiomeId.MOUNTAIN, BiomePoolTier.RARE] + [BiomeId.BADLANDS, BiomePoolTier.RARE] ] ], [SpeciesId.CAPSAKID, PokemonType.GRASS, -1, [ @@ -4563,12 +4660,11 @@ export function initBiomes() { ] ], [SpeciesId.RELLOR, PokemonType.BUG, -1, [ - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.DESERT, BiomePoolTier.COMMON] ] ], [SpeciesId.RABSCA, PokemonType.BUG, PokemonType.PSYCHIC, [ - [BiomeId.DESERT, BiomePoolTier.COMMON, [TimeOfDay.DAWN, TimeOfDay.DAY]], - [BiomeId.DESERT, BiomePoolTier.BOSS, [TimeOfDay.DAWN, TimeOfDay.DAY]] + [BiomeId.DESERT, BiomePoolTier.COMMON] ] ], [SpeciesId.FLITTLE, PokemonType.PSYCHIC, -1, [ @@ -4653,7 +4749,7 @@ export function initBiomes() { ] ], [SpeciesId.FLAMIGO, PokemonType.FLYING, PokemonType.FIGHTING, [ - [BiomeId.LAKE, BiomePoolTier.UNCOMMON] + [BiomeId.LAKE, BiomePoolTier.RARE] ] ], [SpeciesId.CETODDLE, PokemonType.ICE, -1, [ @@ -4696,12 +4792,13 @@ export function initBiomes() { ], [SpeciesId.DUDUNSPARCE, PokemonType.NORMAL, -1, [ [BiomeId.PLAINS, BiomePoolTier.SUPER_RARE], - [BiomeId.PLAINS, BiomePoolTier.BOSS_RARE] + [BiomeId.PLAINS, BiomePoolTier.BOSS_RARE], + [BiomeId.ABYSS, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.KINGAMBIT, PokemonType.DARK, PokemonType.STEEL, [ - [BiomeId.ABYSS, BiomePoolTier.COMMON], - [BiomeId.ABYSS, BiomePoolTier.BOSS] + [BiomeId.TALL_GRASS, BiomePoolTier.BOSS_RARE], + [BiomeId.SLUM, BiomePoolTier.RARE] ] ], [SpeciesId.GREAT_TUSK, PokemonType.GROUND, PokemonType.FIGHTING, [ @@ -4882,12 +4979,14 @@ export function initBiomes() { [SpeciesId.PECHARUNT, PokemonType.POISON, PokemonType.GHOST, [] ], [SpeciesId.ALOLA_RATTATA, PokemonType.DARK, PokemonType.NORMAL, [ - [BiomeId.ISLAND, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.ISLAND, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.ALOLA_RATICATE, PokemonType.DARK, PokemonType.NORMAL, [ [BiomeId.ISLAND, BiomePoolTier.COMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], - [BiomeId.ISLAND, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.ISLAND, BiomePoolTier.BOSS, [TimeOfDay.DUSK, TimeOfDay.NIGHT]], + [BiomeId.SLUM, BiomePoolTier.BOSS] ] ], [SpeciesId.ALOLA_RAICHU, PokemonType.ELECTRIC, PokemonType.PSYCHIC, [ @@ -4920,12 +5019,14 @@ export function initBiomes() { ] ], [SpeciesId.ALOLA_DIGLETT, PokemonType.GROUND, PokemonType.STEEL, [ - [BiomeId.ISLAND, BiomePoolTier.COMMON] + [BiomeId.ISLAND, BiomePoolTier.COMMON], + [BiomeId.VOLCANO, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.ALOLA_DUGTRIO, PokemonType.GROUND, PokemonType.STEEL, [ [BiomeId.ISLAND, BiomePoolTier.COMMON], - [BiomeId.ISLAND, BiomePoolTier.BOSS] + [BiomeId.ISLAND, BiomePoolTier.BOSS], + [BiomeId.VOLCANO, BiomePoolTier.BOSS] ] ], [SpeciesId.ALOLA_MEOWTH, PokemonType.DARK, -1, [ @@ -4938,16 +5039,20 @@ export function initBiomes() { ] ], [SpeciesId.ALOLA_GEODUDE, PokemonType.ROCK, PokemonType.ELECTRIC, [ - [BiomeId.ISLAND, BiomePoolTier.COMMON] + [BiomeId.ISLAND, BiomePoolTier.COMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.ALOLA_GRAVELER, PokemonType.ROCK, PokemonType.ELECTRIC, [ - [BiomeId.ISLAND, BiomePoolTier.COMMON] + [BiomeId.ISLAND, BiomePoolTier.COMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.ALOLA_GOLEM, PokemonType.ROCK, PokemonType.ELECTRIC, [ [BiomeId.ISLAND, BiomePoolTier.COMMON], - [BiomeId.ISLAND, BiomePoolTier.BOSS] + [BiomeId.ISLAND, BiomePoolTier.BOSS], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.UNCOMMON], + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.BOSS] ] ], [SpeciesId.ALOLA_GRIMER, PokemonType.POISON, PokemonType.DARK, [ @@ -4975,16 +5080,16 @@ export function initBiomes() { ] ], [SpeciesId.GALAR_MEOWTH, PokemonType.STEEL, -1, [ - [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE, TimeOfDay.DUSK] + [BiomeId.CONSTRUCTION_SITE, BiomePoolTier.RARE] ] ], [SpeciesId.GALAR_PONYTA, PokemonType.PSYCHIC, -1, [ - [BiomeId.JUNGLE, BiomePoolTier.RARE, TimeOfDay.DAWN] + [BiomeId.JUNGLE, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.GALAR_RAPIDASH, PokemonType.PSYCHIC, PokemonType.FAIRY, [ - [BiomeId.JUNGLE, BiomePoolTier.RARE, TimeOfDay.DAWN], - [BiomeId.JUNGLE, BiomePoolTier.BOSS_RARE, TimeOfDay.DAWN] + [BiomeId.JUNGLE, BiomePoolTier.RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]], + [BiomeId.JUNGLE, BiomePoolTier.BOSS_RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], [SpeciesId.GALAR_SLOWPOKE, PokemonType.PSYCHIC, -1, [ @@ -5010,17 +5115,17 @@ export function initBiomes() { ], [SpeciesId.GALAR_ARTICUNO, PokemonType.PSYCHIC, PokemonType.FLYING, [ [BiomeId.SNOWY_FOREST, BiomePoolTier.ULTRA_RARE], - [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS_ULTRA_RARE] + [BiomeId.SNOWY_FOREST, BiomePoolTier.BOSS_SUPER_RARE] ] ], [SpeciesId.GALAR_ZAPDOS, PokemonType.FIGHTING, PokemonType.FLYING, [ [BiomeId.DOJO, BiomePoolTier.ULTRA_RARE], - [BiomeId.DOJO, BiomePoolTier.BOSS_ULTRA_RARE] + [BiomeId.DOJO, BiomePoolTier.BOSS_SUPER_RARE] ] ], [SpeciesId.GALAR_MOLTRES, PokemonType.DARK, PokemonType.FLYING, [ [BiomeId.ABYSS, BiomePoolTier.ULTRA_RARE], - [BiomeId.ABYSS, BiomePoolTier.BOSS_ULTRA_RARE] + [BiomeId.ABYSS, BiomePoolTier.BOSS_SUPER_RARE] ] ], [SpeciesId.GALAR_SLOWKING, PokemonType.POISON, PokemonType.PSYCHIC, [ @@ -5032,11 +5137,11 @@ export function initBiomes() { ] ], [SpeciesId.GALAR_ZIGZAGOON, PokemonType.DARK, PokemonType.NORMAL, [ - [BiomeId.SLUM, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.GALAR_LINOONE, PokemonType.DARK, PokemonType.NORMAL, [ - [BiomeId.SLUM, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.SLUM, BiomePoolTier.UNCOMMON] ] ], [SpeciesId.GALAR_DARUMAKA, PokemonType.ICE, -1, [ @@ -5085,9 +5190,7 @@ export function initBiomes() { [BiomeId.SNOWY_FOREST, BiomePoolTier.SUPER_RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]] ] ], - [SpeciesId.HISUI_SAMUROTT, PokemonType.WATER, PokemonType.DARK, [ - [BiomeId.ABYSS, BiomePoolTier.BOSS_RARE] - ] + [SpeciesId.HISUI_SAMUROTT, PokemonType.WATER, PokemonType.DARK, [] ], [SpeciesId.HISUI_LILLIGANT, PokemonType.GRASS, PokemonType.FIGHTING, [ [BiomeId.MEADOW, BiomePoolTier.BOSS_RARE, [TimeOfDay.DAWN, TimeOfDay.DAY]] diff --git a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts index 6ab029a7ff9..a05da4893c6 100644 --- a/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts +++ b/src/data/mystery-encounters/encounters/bug-type-superfan-encounter.ts @@ -175,6 +175,8 @@ export const BugTypeSuperfanEncounter: MysteryEncounter = MysteryEncounterBuilde ) .withMaxAllowedEncounters(1) .withSceneWaveRangeRequirement(...CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES) + .withScenePartySizeRequirement(3, 6) + .withMaxAllowedEncounters(1) .withIntroSpriteConfigs([]) // These are set in onInit() .withAutoHideIntroVisuals(false) .withIntroDialogue([ diff --git a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts index fbdc1c8f714..c30aee94a56 100644 --- a/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-winstrate-challenge-encounter.ts @@ -45,6 +45,8 @@ export const TheWinstrateChallengeEncounter: MysteryEncounter = MysteryEncounter ) .withEncounterTier(MysteryEncounterTier.ROGUE) .withSceneWaveRangeRequirement(100, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) + .withScenePartySizeRequirement(3, 6) + .withMaxAllowedEncounters(1) .withIntroSpriteConfigs([ { spriteKey: "vito", diff --git a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts index ed588ea2884..80eeeec6162 100644 --- a/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts +++ b/src/data/mystery-encounters/encounters/trash-to-treasure-encounter.ts @@ -47,7 +47,8 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde MysteryEncounterType.TRASH_TO_TREASURE, ) .withEncounterTier(MysteryEncounterTier.ULTRA) - .withSceneWaveRangeRequirement(60, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) + .withSceneWaveRangeRequirement(100, CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES[1]) + .withScenePartySizeRequirement(3, 6) .withMaxAllowedEncounters(1) .withFleeAllowed(false) .withIntroSpriteConfigs([ @@ -148,6 +149,48 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde }, ], }) + .withOptionPhase(async () => { + // Investigate garbage, battle Gmax Garbodor + globalScene.setFieldScale(0.75); + await showEncounterText(`${namespace}:option.1.selected2`); + await transitionMysteryEncounterIntroVisuals(); + + const encounter = globalScene.currentBattle.mysteryEncounter!; + + setEncounterRewards({ + guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], + guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], + fillRemaining: true, + }); + encounter.startOfBattleEffects.push( + { + sourceBattlerIndex: BattlerIndex.ENEMY, + targets: [BattlerIndex.PLAYER], + move: new PokemonMove(MoveId.TOXIC), + useMode: MoveUseMode.IGNORE_PP, + }, + { + sourceBattlerIndex: BattlerIndex.ENEMY, + targets: [BattlerIndex.ENEMY], + move: new PokemonMove(MoveId.STOCKPILE), + useMode: MoveUseMode.IGNORE_PP, + }, + ); + await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]); + }) + .build(), + ) + .withOption( + MysteryEncounterOptionBuilder.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT) + .withDialogue({ + buttonLabel: `${namespace}:option.2.label`, + buttonTooltip: `${namespace}:option.2.tooltip`, + selected: [ + { + text: `${namespace}:option.2.selected`, + }, + ], + }) .withPreOptionPhase(async () => { // Play Dig2 and then Venom Drench sfx doGarbageDig(); @@ -180,48 +223,6 @@ export const TrashToTreasureEncounter: MysteryEncounter = MysteryEncounterBuilde }) .build(), ) - .withOption( - MysteryEncounterOptionBuilder.newOptionWithMode(MysteryEncounterOptionMode.DEFAULT) - .withDialogue({ - buttonLabel: `${namespace}:option.2.label`, - buttonTooltip: `${namespace}:option.2.tooltip`, - selected: [ - { - text: `${namespace}:option.2.selected`, - }, - ], - }) - .withOptionPhase(async () => { - // Investigate garbage, battle Gmax Garbodor - globalScene.setFieldScale(0.75); - await showEncounterText(`${namespace}:option.2.selected2`); - await transitionMysteryEncounterIntroVisuals(); - - const encounter = globalScene.currentBattle.mysteryEncounter!; - - setEncounterRewards({ - guaranteedModifierTypeFuncs: [modifierTypes.LEFTOVERS], - guaranteedModifierTiers: [ModifierTier.ROGUE, ModifierTier.ULTRA, ModifierTier.GREAT], - fillRemaining: true, - }); - encounter.startOfBattleEffects.push( - { - sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.PLAYER], - move: new PokemonMove(MoveId.TOXIC), - useMode: MoveUseMode.IGNORE_PP, - }, - { - sourceBattlerIndex: BattlerIndex.ENEMY, - targets: [BattlerIndex.ENEMY], - move: new PokemonMove(MoveId.STOCKPILE), - useMode: MoveUseMode.IGNORE_PP, - }, - ); - await initBattleWithEnemyConfig(encounter.enemyPartyConfigs[0]); - }) - .build(), - ) .build(); async function tryApplyDigRewardItems() { diff --git a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts index abd81fb92ea..56d3dda817f 100644 --- a/src/data/mystery-encounters/encounters/weird-dream-encounter.ts +++ b/src/data/mystery-encounters/encounters/weird-dream-encounter.ts @@ -127,8 +127,9 @@ export const WeirdDreamEncounter: MysteryEncounter = MysteryEncounterBuilder.wit ) .withEncounterTier(MysteryEncounterTier.ROGUE) .withDisallowedChallenges(Challenges.SINGLE_TYPE, Challenges.SINGLE_GENERATION) - // TODO: should reset minimum wave to 10 when there are more Rogue tiers in pool. Matching Dark Deal minimum for now. .withSceneWaveRangeRequirement(30, 140) + .withScenePartySizeRequirement(3, 6) + .withMaxAllowedEncounters(1) .withIntroSpriteConfigs([ { spriteKey: "weird_dream_woman", diff --git a/src/data/weather.ts b/src/data/weather.ts index 49af505dc62..c6d00c3d8d9 100644 --- a/src/data/weather.ts +++ b/src/data/weather.ts @@ -251,25 +251,31 @@ export function getRandomWeatherType(arena: Arena): WeatherType { const hasSun = arena.getTimeOfDay() < 2; switch (arena.biomeType) { case BiomeId.GRASS: - weatherPool = [{ weatherType: WeatherType.NONE, weight: 7 }]; - if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 3 }); - } - break; - case BiomeId.TALL_GRASS: weatherPool = [ { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.RAIN, weight: 5 }, + { weatherType: WeatherType.RAIN, weight: 4 }, ]; if (hasSun) { weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 8 }); } break; + case BiomeId.TALL_GRASS: + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 8 }, + { weatherType: WeatherType.RAIN, weight: 4 }, + ]; + if (hasSun) { + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 4 }); + } + break; case BiomeId.FOREST: weatherPool = [ { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.RAIN, weight: 5 }, + { weatherType: WeatherType.RAIN, weight: 4 }, ]; + if (!hasSun) { + weatherPool.push({ weatherType: WeatherType.FOG, weight: 1 }); + } break; case BiomeId.SEA: weatherPool = [ @@ -296,7 +302,7 @@ export function getRandomWeatherType(arena: Arena): WeatherType { case BiomeId.LAKE: weatherPool = [ { weatherType: WeatherType.NONE, weight: 10 }, - { weatherType: WeatherType.RAIN, weight: 5 }, + { weatherType: WeatherType.RAIN, weight: 4 }, { weatherType: WeatherType.FOG, weight: 1 }, ]; break; @@ -313,9 +319,12 @@ export function getRandomWeatherType(arena: Arena): WeatherType { } break; case BiomeId.DESERT: - weatherPool = [{ weatherType: WeatherType.SANDSTORM, weight: 2 }]; + weatherPool = [ + { weatherType: WeatherType.NONE, weight: 2 }, + { weatherType: WeatherType.SANDSTORM, weight: 8 }, + ]; if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); } break; case BiomeId.ICE_CAVE: @@ -326,9 +335,9 @@ export function getRandomWeatherType(arena: Arena): WeatherType { ]; break; case BiomeId.MEADOW: - weatherPool = [{ weatherType: WeatherType.NONE, weight: 2 }]; + weatherPool = [{ weatherType: WeatherType.NONE, weight: 3 }]; if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); } break; case BiomeId.VOLCANO: @@ -348,7 +357,8 @@ export function getRandomWeatherType(arena: Arena): WeatherType { case BiomeId.JUNGLE: weatherPool = [ { weatherType: WeatherType.NONE, weight: 8 }, - { weatherType: WeatherType.RAIN, weight: 2 }, + { weatherType: WeatherType.RAIN, weight: 6 }, + { weatherType: WeatherType.FOG, weight: 1 }, ]; break; case BiomeId.SNOWY_FOREST: @@ -359,11 +369,11 @@ export function getRandomWeatherType(arena: Arena): WeatherType { break; case BiomeId.ISLAND: weatherPool = [ - { weatherType: WeatherType.NONE, weight: 5 }, - { weatherType: WeatherType.RAIN, weight: 1 }, + { weatherType: WeatherType.NONE, weight: 7 }, + { weatherType: WeatherType.RAIN, weight: 3 }, ]; if (hasSun) { - weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 2 }); + weatherPool.push({ weatherType: WeatherType.SUNNY, weight: 5 }); } break; } diff --git a/src/field/arena.ts b/src/field/arena.ts index 468e6846d03..b4d993314c4 100644 --- a/src/field/arena.ts +++ b/src/field/arena.ts @@ -249,20 +249,6 @@ export class Arena { return 2; } break; - case SpeciesId.ROTOM: - switch (this.biomeType) { - case BiomeId.VOLCANO: - return 1; - case BiomeId.SEA: - return 2; - case BiomeId.ICE_CAVE: - return 3; - case BiomeId.MOUNTAIN: - return 4; - case BiomeId.TALL_GRASS: - return 5; - } - break; case SpeciesId.LYCANROC: { const timeOfDay = this.getTimeOfDay(); switch (timeOfDay) { diff --git a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts index 91a88712e9b..15680d5791d 100644 --- a/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts +++ b/test/mystery-encounter/encounters/trash-to-treasure-encounter.test.ts @@ -151,7 +151,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { expect(onInitResult).toBe(true); }); - describe("Option 1 - Dig for Valuables", () => { + describe("Option 1 - Battle Garbodor", () => { it("should have the correct properties", () => { const option1 = TrashToTreasureEncounter.options[0]; expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT); @@ -167,56 +167,11 @@ describe("Trash to Treasure - Mystery Encounter", () => { }); }); - it("should give 1 Leftovers, 1 Shell Bell, and Black Sludge", async () => { - await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); - await runMysteryEncounterToEnd(game, 1); - expect(game).toBeAtPhase("SelectModifierPhase"); - await game.phaseInterceptor.to("SelectModifierPhase"); - - const leftovers = scene.findModifier(m => m instanceof TurnHealModifier) as TurnHealModifier; - expect(leftovers).toBeDefined(); - expect(leftovers?.stackCount).toBe(1); - - const shellBell = scene.findModifier(m => m instanceof HitHealModifier) as HitHealModifier; - expect(shellBell).toBeDefined(); - expect(shellBell?.stackCount).toBe(1); - - const blackSludge = scene.findModifier(m => m instanceof HealShopCostModifier) as HealShopCostModifier; - expect(blackSludge).toBeDefined(); - expect(blackSludge?.stackCount).toBe(1); - }); - - it("should leave encounter without battle", async () => { - const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); - - await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); - await runMysteryEncounterToEnd(game, 1); - - expect(leaveEncounterWithoutBattleSpy).toBeCalled(); - }); - }); - - describe("Option 2 - Battle Garbodor", () => { - it("should have the correct properties", () => { - const option1 = TrashToTreasureEncounter.options[1]; - expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT); - expect(option1.dialogue).toBeDefined(); - expect(option1.dialogue).toStrictEqual({ - buttonLabel: `${namespace}:option.2.label`, - buttonTooltip: `${namespace}:option.2.tooltip`, - selected: [ - { - text: `${namespace}:option.2.selected`, - }, - ], - }); - }); - it("should start battle against Garbodor", async () => { const phaseSpy = vi.spyOn(scene.phaseManager, "pushPhase"); await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); - await runMysteryEncounterToEnd(game, 2, undefined, true); + await runMysteryEncounterToEnd(game, 1, undefined, true); const enemyField = scene.getEnemyField(); expect(game).toBeAtPhase("CommandPhase"); @@ -238,7 +193,7 @@ describe("Trash to Treasure - Mystery Encounter", () => { it("should have 2 Rogue, 1 Ultra, 1 Great in rewards", async () => { await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); - await runMysteryEncounterToEnd(game, 2, undefined, true); + await runMysteryEncounterToEnd(game, 1, undefined, true); await skipBattleRunMysteryEncounterRewardsPhase(game); await game.phaseInterceptor.to("SelectModifierPhase", false); expect(game).toBeAtPhase("SelectModifierPhase"); @@ -267,4 +222,49 @@ describe("Trash to Treasure - Mystery Encounter", () => { ).toEqual(ModifierTier.GREAT); }); }); + + describe("Option 2 - Dig for Valuables", () => { + it("should have the correct properties", () => { + const option1 = TrashToTreasureEncounter.options[1]; + expect(option1.optionMode).toBe(MysteryEncounterOptionMode.DEFAULT); + expect(option1.dialogue).toBeDefined(); + expect(option1.dialogue).toStrictEqual({ + buttonLabel: `${namespace}:option.2.label`, + buttonTooltip: `${namespace}:option.2.tooltip`, + selected: [ + { + text: `${namespace}:option.2.selected`, + }, + ], + }); + }); + + it("should give 1 Leftovers, 1 Shell Bell, and Black Sludge", async () => { + await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); + await runMysteryEncounterToEnd(game, 2); + expect(game).toBeAtPhase("SelectModifierPhase"); + await game.phaseInterceptor.to("SelectModifierPhase"); + + const leftovers = scene.findModifier(m => m instanceof TurnHealModifier) as TurnHealModifier; + expect(leftovers).toBeDefined(); + expect(leftovers?.stackCount).toBe(1); + + const shellBell = scene.findModifier(m => m instanceof HitHealModifier) as HitHealModifier; + expect(shellBell).toBeDefined(); + expect(shellBell?.stackCount).toBe(1); + + const blackSludge = scene.findModifier(m => m instanceof HealShopCostModifier) as HealShopCostModifier; + expect(blackSludge).toBeDefined(); + expect(blackSludge?.stackCount).toBe(1); + }); + + it("should leave encounter without battle", async () => { + const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle"); + + await game.runToMysteryEncounter(MysteryEncounterType.TRASH_TO_TREASURE, defaultParty); + await runMysteryEncounterToEnd(game, 2); + + expect(leaveEncounterWithoutBattleSpy).toBeCalled(); + }); + }); }); From ea7a1c9a7421e81d06bd53440762bc24dcc40b08 Mon Sep 17 00:00:00 2001 From: damocleas Date: Wed, 29 Oct 2025 12:53:44 -0400 Subject: [PATCH 10/58] Update locales, update version --- locales | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/locales b/locales index 5ef010497b8..67a0c026068 160000 --- a/locales +++ b/locales @@ -1 +1 @@ -Subproject commit 5ef010497b8cc688bd8ee79d40c967bd85ee8192 +Subproject commit 67a0c02606848cc6ca3f8998a7cbacb0d7dd5a9e diff --git a/package.json b/package.json index f018717ed21..b23b9b9b75d 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.10.7", + "version": "1.11.0", "type": "module", "scripts": { "start:prod": "vite --mode production", From bc79a2490b5a1b1746ac8795eaf2778f802a2918 Mon Sep 17 00:00:00 2001 From: Fabi <192151969+fabske0@users.noreply.github.com> Date: Wed, 29 Oct 2025 22:19:27 +0100 Subject: [PATCH 11/58] [Beta] [Bug] Show correct username in title ui (#6710) fix title username --- src/ui/handlers/title-ui-handler.ts | 6 ++++++ src/ui/settings/abstract-settings-ui-handler.ts | 2 ++ 2 files changed, 8 insertions(+) diff --git a/src/ui/handlers/title-ui-handler.ts b/src/ui/handlers/title-ui-handler.ts index 86fd27a6a1b..80c7180f6c5 100644 --- a/src/ui/handlers/title-ui-handler.ts +++ b/src/ui/handlers/title-ui-handler.ts @@ -47,6 +47,10 @@ export class TitleUiHandler extends OptionSelectUiHandler { return i18next.t("menu:loggedInAs", { username: displayName }); } + updateUsername() { + this.usernameLabel.setText(this.getUsername()); + } + constructor(mode: UiMode = UiMode.TITLE) { super(mode); } @@ -167,6 +171,8 @@ export class TitleUiHandler extends OptionSelectUiHandler { const scaledHeight = globalScene.scaledCanvas.height; const windowHeight = this.getWindowHeight(); + this.updateUsername(); + // Moving username and player count to top of the menu // and sorting it, to display the shorter one on top const UPPER_LABEL = scaledHeight - 23 - windowHeight; diff --git a/src/ui/settings/abstract-settings-ui-handler.ts b/src/ui/settings/abstract-settings-ui-handler.ts index e22c28116f5..78c34a47c06 100644 --- a/src/ui/settings/abstract-settings-ui-handler.ts +++ b/src/ui/settings/abstract-settings-ui-handler.ts @@ -10,6 +10,7 @@ import { MessageUiHandler } from "#ui/message-ui-handler"; import { NavigationManager, NavigationMenu } from "#ui/navigation-menu"; import { ScrollBar } from "#ui/scroll-bar"; import { addTextObject, getTextColor } from "#ui/text"; +import type { TitleUiHandler } from "#ui/title-ui-handler"; import { addWindow } from "#ui/ui-theme"; import i18next from "i18next"; @@ -497,6 +498,7 @@ export class AbstractSettingsUiHandler extends MessageUiHandler { this.setScrollCursor(0); this.eraseCursor(); this.getUi().bgmBar.toggleBgmBar(globalScene.showBgmBar); + (this.getUi().handlers[UiMode.TITLE] as TitleUiHandler)?.updateUsername(); if (this.reloadRequired) { this.reloadRequired = false; globalScene.reset(true, false, true); From 12b57836b2b3f05ebc5e36419cbb82bcf33a3f47 Mon Sep 17 00:00:00 2001 From: Blitzy <118096277+Blitz425@users.noreply.github.com> Date: Wed, 29 Oct 2025 17:03:58 -0500 Subject: [PATCH 12/58] literally just an egg move change Update egg-moves.ts --- src/data/balance/egg-moves.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/balance/egg-moves.ts b/src/data/balance/egg-moves.ts index 4374305c183..f43ee573207 100644 --- a/src/data/balance/egg-moves.ts +++ b/src/data/balance/egg-moves.ts @@ -479,7 +479,7 @@ export const speciesEggMoves = { [SpeciesId.ARCTOZOLT]: [ MoveId.MOUNTAIN_GALE, MoveId.AQUA_STEP, MoveId.HIGH_HORSEPOWER, MoveId.SHIFT_GEAR ], [SpeciesId.DRACOVISH]: [ MoveId.TRIPLE_AXEL, MoveId.DRAGON_HAMMER, MoveId.THUNDER_FANG, MoveId.DRAGON_DANCE ], [SpeciesId.ARCTOVISH]: [ MoveId.ICE_FANG, MoveId.THUNDER_FANG, MoveId.HIGH_HORSEPOWER, MoveId.SHIFT_GEAR ], - [SpeciesId.DURALUDON]: [ MoveId.DAZZLING_GLEAM, MoveId.BODY_PRESS, MoveId.THUNDERCLAP, MoveId.CORE_ENFORCER ], + [SpeciesId.DURALUDON]: [ MoveId.HEAT_WAVE, MoveId.BODY_PRESS, MoveId.THUNDERCLAP, MoveId.CORE_ENFORCER ], [SpeciesId.DREEPY]: [ MoveId.SHADOW_BONE, MoveId.POWER_UP_PUNCH, MoveId.FIRE_LASH, MoveId.DIRE_CLAW ], [SpeciesId.ZACIAN]: [ MoveId.MAGICAL_TORQUE, MoveId.MIGHTY_CLEAVE, MoveId.EARTHQUAKE, MoveId.BITTER_BLADE ], [SpeciesId.ZAMAZENTA]: [ MoveId.BULK_UP, MoveId.BODY_PRESS, MoveId.POWER_TRIP, MoveId.SLACK_OFF ], From a55b2b18e80a49a56a4d3c585da7117e3ed171f1 Mon Sep 17 00:00:00 2001 From: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Date: Wed, 29 Oct 2025 23:27:03 +0100 Subject: [PATCH 13/58] [UI/UX][Beta] Adjustments to display of ribbons (#6709) * Introduce custom ordering of ribbons * Displaying classic ribbon for mons that have at least one classic win --------- Co-authored-by: damocleas --- src/ui/containers/ribbon-tray-container.ts | 15 ++++++-- src/utils/ribbon-utils.ts | 44 ++++++++++++++++++++++ 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/src/ui/containers/ribbon-tray-container.ts b/src/ui/containers/ribbon-tray-container.ts index 0f2e5137c06..038e03f5ef4 100644 --- a/src/ui/containers/ribbon-tray-container.ts +++ b/src/ui/containers/ribbon-tray-container.ts @@ -1,11 +1,11 @@ import { globalScene } from "#app/global-scene"; import type { PokemonSpecies } from "#data/pokemon-species"; import { Button } from "#enums/buttons"; -import type { RibbonData, RibbonFlag } from "#system/ribbons/ribbon-data"; +import { RibbonData, type RibbonFlag } from "#system/ribbons/ribbon-data"; import { ribbonFlagToAssetKey } from "#system/ribbons/ribbon-methods"; import type { MessageUiHandler } from "#ui/message-ui-handler"; import { addWindow } from "#ui/ui-theme"; -import { getAvailableRibbons, getRibbonKey } from "#utils/ribbon-utils"; +import { getAvailableRibbons, getRibbonKey, orderedRibbons } from "#utils/ribbon-utils"; import i18next from "i18next"; export class RibbonTray extends Phaser.GameObjects.Container { @@ -111,8 +111,15 @@ export class RibbonTray extends Phaser.GameObjects.Container { this.trayIcons = []; let index = 0; - for (const ribbon of getAvailableRibbons(species)) { - const hasRibbon = this.ribbonData.has(ribbon); + + const availableRibbons = getAvailableRibbons(species); + const availableOrderedRibbons = orderedRibbons.filter(r => availableRibbons.includes(r)); + + const hasWonClassic = globalScene.gameData.starterData[species.speciesId]?.classicWinCount > 0; + + for (const ribbon of availableOrderedRibbons) { + const hasRibbon = this.ribbonData.has(ribbon) || (ribbon === RibbonData.CLASSIC && hasWonClassic); + if (!hasRibbon && !globalScene.dexForDevs && !globalScene.showMissingRibbons) { continue; } diff --git a/src/utils/ribbon-utils.ts b/src/utils/ribbon-utils.ts index f45cfef80d8..20c0e755be7 100644 --- a/src/utils/ribbon-utils.ts +++ b/src/utils/ribbon-utils.ts @@ -170,3 +170,47 @@ export function getRibbonKey(flag: RibbonFlag): string { return ""; } } + +/** + * This list is used to determined the display order of ribbons in the Pokédex. + */ +export const orderedRibbons: RibbonFlag[] = [ + RibbonData.CLASSIC, + RibbonData.FRIENDSHIP, + RibbonData.FRESH_START, + RibbonData.HARDCORE, + RibbonData.LIMITED_CATCH, + RibbonData.NUZLOCKE, + RibbonData.NO_HEAL, + RibbonData.NO_SHOP, + RibbonData.NO_SUPPORT, + RibbonData.MONO_GEN_1, + RibbonData.MONO_GEN_2, + RibbonData.MONO_GEN_3, + RibbonData.MONO_GEN_4, + RibbonData.MONO_GEN_5, + RibbonData.MONO_GEN_6, + RibbonData.MONO_GEN_7, + RibbonData.MONO_GEN_8, + RibbonData.MONO_GEN_9, + RibbonData.MONO_NORMAL, + RibbonData.MONO_FIGHTING, + RibbonData.MONO_FLYING, + RibbonData.MONO_POISON, + RibbonData.MONO_GROUND, + RibbonData.MONO_ROCK, + RibbonData.MONO_BUG, + RibbonData.MONO_GHOST, + RibbonData.MONO_STEEL, + RibbonData.MONO_FIRE, + RibbonData.MONO_WATER, + RibbonData.MONO_GRASS, + RibbonData.MONO_ELECTRIC, + RibbonData.MONO_PSYCHIC, + RibbonData.MONO_ICE, + RibbonData.MONO_DRAGON, + RibbonData.MONO_DARK, + RibbonData.MONO_FAIRY, + RibbonData.INVERSE, + RibbonData.FLIP_STATS, +]; From f9a21a0ea4ed4994db1f8e8c19ba05776ab4fd6f Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Wed, 29 Oct 2025 21:49:50 -0700 Subject: [PATCH 14/58] [Dev] Update `@ts-expect-error` in `battle-scene.ts` This allows devs to use the Go port of TypeScript (aka "tsgo"/"TS7") without an error due to different handling of `@ts-expect-error` --- src/battle-scene.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 6c60a0caa20..a7679f4479f 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -452,9 +452,17 @@ export class BattleScene extends SceneBase { true, ); - //@ts-expect-error (the defined types in the package are incromplete...) + // TODO: fix the typing in a `.d.ts` file so the `ts-ignore` is no longer necessary + /* biome-ignore lint/suspicious/noTsIgnore: ts-ignore is necessary because `tsc` and `tsgo` require the directive to be on different lines, + * meaning `@ts-expect-error` is guaranteed to emit a diagnostic on one of the lines depending on which one is used + */ + // @ts-ignore transition.transit({ mode: "blinds", + /* biome-ignore lint/suspicious/noTsIgnore: ts-ignore is necessary because `tsc` and `tsgo` require the directive to be on different lines, + * meaning `@ts-expect-error` is guaranteed to emit a diagnostic on one of the lines depending on which one is used + */ + // @ts-ignore ease: "Cubic.easeInOut", duration: 1250, }); From 20615bcd21629f0e24c5a9964f5eb0a8bbd092c5 Mon Sep 17 00:00:00 2001 From: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Date: Thu, 30 Oct 2025 14:24:04 +0100 Subject: [PATCH 15/58] [Bug] Fix awarded ribbon in limited support (#6713) Fixed awarded ribbon in limited support --- src/data/challenge.ts | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/data/challenge.ts b/src/data/challenge.ts index 0cd2773f2e1..67d0bf60a7f 100644 --- a/src/data/challenge.ts +++ b/src/data/challenge.ts @@ -1109,7 +1109,16 @@ export class LowerStarterPointsChallenge extends Challenge { */ export class LimitedSupportChallenge extends Challenge { public override get ribbonAwarded(): RibbonFlag { - return this.value ? ((RibbonData.NO_HEAL << (BigInt(this.value) - 1n)) as RibbonFlag) : 0n; + switch (this.value) { + case 1: + return RibbonData.NO_HEAL as RibbonFlag; + case 2: + return RibbonData.NO_SHOP as RibbonFlag; + case 3: + return (RibbonData.NO_HEAL | RibbonData.NO_SHOP | RibbonData.NO_SUPPORT) as RibbonFlag; + default: + return 0n as RibbonFlag; + } } constructor() { super(Challenges.LIMITED_SUPPORT, 3); From 24e9dcdadcfb64485c874cd06eae80a7fe923ddd Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Thu, 30 Oct 2025 12:15:20 -0400 Subject: [PATCH 16/58] [Feature] Allow setting movesets via custom daily seed (#6712) * Clean up Daily Run custom seed gen; add moveset post-processing * Remove redundant `fetchDailyRunSeed` function --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/data/daily-run.ts | 98 ++++++++++++++++++++++-------- src/field/pokemon.ts | 20 ++++-- src/phases/select-starter-phase.ts | 4 +- src/phases/title-phase.ts | 12 +++- src/utils/common.ts | 2 +- src/utils/strings.ts | 27 +++++++- test/daily-mode.test.ts | 55 ++++++++++++++++- 7 files changed, 179 insertions(+), 39 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index 776dff1bf46..b86442fac0f 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -1,42 +1,36 @@ -import { pokerogueApi } from "#api/pokerogue-api"; import { globalScene } from "#app/global-scene"; import { speciesStarterCosts } from "#balance/starters"; import type { PokemonSpeciesForm } from "#data/pokemon-species"; import { PokemonSpecies } from "#data/pokemon-species"; import { BiomeId } from "#enums/biome-id"; +import { MoveId } from "#enums/move-id"; import { PartyMemberStrength } from "#enums/party-member-strength"; import { SpeciesId } from "#enums/species-id"; -import type { Starter } from "#types/save-data"; -import { randSeedGauss, randSeedInt, randSeedItem } from "#utils/common"; +import type { Starter, StarterMoveset } from "#types/save-data"; +import { isBetween, randSeedGauss, randSeedInt, randSeedItem } from "#utils/common"; import { getEnumValues } from "#utils/enums"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils"; +import { chunkString } from "#utils/strings"; export interface DailyRunConfig { seed: number; starters: Starter; } +type StarterTuple = [Starter, Starter, Starter]; -export function fetchDailyRunSeed(): Promise { - return new Promise((resolve, _reject) => { - pokerogueApi.daily.getSeed().then(dailySeed => { - resolve(dailySeed); - }); - }); -} - -export function getDailyRunStarters(seed: string): Starter[] { +export function getDailyRunStarters(seed: string): StarterTuple { const starters: Starter[] = []; globalScene.executeWithSeedOffset( () => { - const startingLevel = globalScene.gameMode.getStartingLevel(); - const eventStarters = getDailyEventSeedStarters(seed); if (eventStarters != null) { starters.push(...eventStarters); return; } + // TODO: explain this math + const startingLevel = globalScene.gameMode.getStartingLevel(); const starterCosts: number[] = []; starterCosts.push(Math.min(Math.round(3.5 + Math.abs(randSeedGauss(1))), 8)); starterCosts.push(randSeedInt(9 - starterCosts[0], 1)); @@ -57,9 +51,12 @@ export function getDailyRunStarters(seed: string): Starter[] { seed, ); - return starters; + setDailyRunEventStarterMovesets(seed, starters as StarterTuple); + + return starters as StarterTuple; } +// TODO: Refactor this unmaintainable mess function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: number): Starter { const starterSpecies = starterSpeciesForm instanceof PokemonSpecies ? starterSpeciesForm : getPokemonSpecies(starterSpeciesForm.speciesId); @@ -169,30 +166,83 @@ export function isDailyEventSeed(seed: string): boolean { return globalScene.gameMode.isDaily && seed.length > 24; } +/** + * The length of a single numeric Move ID string. + * Must be updated whenever the `MoveId` enum gets a new digit! + */ +const MOVE_ID_STRING_LENGTH = 4; + +const MOVE_ID_SEED_REGEX = /(?<=\/moves)((?:\d{4}){0,4})(?:,((?:\d{4}){0,4}))?(?:,((?:\d{4}){0,4}))?/; + +/** + * Perform moveset post-processing on Daily run starters. \ + * If the seed matches {@linkcode MOVE_ID_SEED_REGEX}, + * the extracted Move IDs will be used to populate the starters' moveset instead. + * @param seed - The daily run seed + * @param starters - The previously generated starters; will have movesets mutated in place + */ +function setDailyRunEventStarterMovesets(seed: string, starters: StarterTuple): void { + const moveMatch: readonly string[] = MOVE_ID_SEED_REGEX.exec(seed)?.slice(1) ?? []; + if (moveMatch.length === 0) { + return; + } + + if (!isBetween(moveMatch.length, 1, 3)) { + console.error( + "Invalid custom seeded moveset used for daily run seed!\nSeed: %s\nMatch contents: %s", + seed, + moveMatch, + ); + return; + } + + const moveIds = getEnumValues(MoveId); + for (const [i, moveStr] of moveMatch.entries()) { + if (!moveStr) { + // Fallback for empty capture groups from omitted entries + continue; + } + const starter = starters[i]; + const parsedMoveIds = chunkString(moveStr, MOVE_ID_STRING_LENGTH).map(m => Number.parseInt(m) as MoveId); + + if (parsedMoveIds.some(f => !moveIds.includes(f))) { + console.error("Invalid move IDs used for custom daily run seed moveset on starter %d:", i, parsedMoveIds); + continue; + } + + starter.moveset = parsedMoveIds as StarterMoveset; + } +} + /** * Expects the seed to contain `/starters\d{18}/` * where the digits alternate between 4 digits for the species ID and 2 digits for the form index * (left padded with `0`s as necessary). * @returns An array of {@linkcode Starter}s, or `null` if no valid match. */ -export function getDailyEventSeedStarters(seed: string): Starter[] | null { +// TODO: Rework this setup into JSON or similar - this is quite hard to maintain +export function getDailyEventSeedStarters(seed: string): StarterTuple | null { if (!isDailyEventSeed(seed)) { return null; } const starters: Starter[] = []; - const match = /starters(\d{4})(\d{2})(\d{4})(\d{2})(\d{4})(\d{2})/g.exec(seed); + const speciesMatch = /starters(\d{4})(\d{2})(\d{4})(\d{2})(\d{4})(\d{2})/g.exec(seed)?.slice(1); - if (!match || match.length !== 7) { + if (!speciesMatch || speciesMatch.length !== 6) { return null; } - for (let i = 1; i < match.length; i += 2) { - const speciesId = Number.parseInt(match[i]) as SpeciesId; - const formIndex = Number.parseInt(match[i + 1]); + // TODO: Move these to server-side validation + const speciesIds = getEnumValues(SpeciesId); - if (!getEnumValues(SpeciesId).includes(speciesId)) { - console.warn("Invalid species ID used for custom daily run seed starter:", speciesId); + // generate each starter in turn + for (let i = 0; i < 3; i++) { + const speciesId = Number.parseInt(speciesMatch[2 * i]) as SpeciesId; + const formIndex = Number.parseInt(speciesMatch[2 * i + 1]); + + if (!speciesIds.includes(speciesId)) { + console.error("Invalid species ID used for custom daily run seed starter:", speciesId); return null; } @@ -202,7 +252,7 @@ export function getDailyEventSeedStarters(seed: string): Starter[] | null { starters.push(starter); } - return starters; + return starters as StarterTuple; } /** diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 5d50865798e..6f9d8b53249 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -5849,19 +5849,27 @@ export class PlayerPokemon extends Pokemon { } } - tryPopulateMoveset(moveset: StarterMoveset): boolean { + /** + * Attempt to populate this Pokemon's moveset based on those from a Starter + * @param moveset - The {@linkcode StarterMoveset} to use; will override corresponding slots + * of this Pokemon's moveset + * @param ignoreValidate - Whether to ignore validating the passed-in moveset; default `false` + */ + tryPopulateMoveset(moveset: StarterMoveset, ignoreValidate = false): void { + // TODO: Why do we need to re-validate starter movesets after picking them? if ( - !this.getSpeciesForm().validateStarterMoveset( + !ignoreValidate + && !this.getSpeciesForm().validateStarterMoveset( moveset, globalScene.gameData.starterData[this.species.getRootSpeciesId()].eggMoves, ) ) { - return false; + return; } - this.moveset = moveset.map(m => new PokemonMove(m)); - - return true; + moveset.forEach((m, i) => { + this.moveset[i] = new PokemonMove(m); + }); } /** diff --git a/src/phases/select-starter-phase.ts b/src/phases/select-starter-phase.ts index e923efaa678..70cfcb95ae5 100644 --- a/src/phases/select-starter-phase.ts +++ b/src/phases/select-starter-phase.ts @@ -71,7 +71,9 @@ export class SelectStarterPhase extends Phase { starter.ivs, starter.nature, ); - starter.moveset && starterPokemon.tryPopulateMoveset(starter.moveset); + if (starter.moveset) { + starterPokemon.tryPopulateMoveset(starter.moveset); + } if (starter.passive) { starterPokemon.passive = true; } diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index bc530d6f0b0..a18be85374f 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -1,3 +1,4 @@ +import { pokerogueApi } from "#api/pokerogue-api"; import { loggedInUser } from "#app/account"; import { GameMode, getGameMode } from "#app/game-mode"; import { timedEventManager } from "#app/global-event-manager"; @@ -5,7 +6,7 @@ import { globalScene } from "#app/global-scene"; import Overrides from "#app/overrides"; import { Phase } from "#app/phase"; import { bypassLogin } from "#constants/app-constants"; -import { fetchDailyRunSeed, getDailyRunStarters } from "#data/daily-run"; +import { getDailyRunStarters } from "#data/daily-run"; import { modifierTypes } from "#data/data-lists"; import { Gender } from "#data/gender"; import { BattleType } from "#enums/battle-type"; @@ -218,6 +219,7 @@ export class TitlePhase extends Phase { const starters = getDailyRunStarters(seed); const startingLevel = globalScene.gameMode.getStartingLevel(); + // TODO: Dedupe this const party = globalScene.getPlayerParty(); const loadPokemonAssets: Promise[] = []; for (const starter of starters) { @@ -237,6 +239,11 @@ export class TitlePhase extends Phase { starter.nature, ); starterPokemon.setVisible(false); + if (starter.moveset) { + // avoid validating daily run starter movesets which are pre-populated already + starterPokemon.tryPopulateMoveset(starter.moveset, true); + } + party.push(starterPokemon); loadPokemonAssets.push(starterPokemon.loadAssets()); } @@ -279,7 +286,8 @@ export class TitlePhase extends Phase { // If Online, calls seed fetch from db to generate daily run. If Offline, generates a daily run based on current date. if (!bypassLogin || isLocalServerConnected) { - fetchDailyRunSeed() + pokerogueApi.daily + .getSeed() .then(seed => { if (seed) { generateDaily(seed); diff --git a/src/utils/common.ts b/src/utils/common.ts index 58deccb4d80..056358dd87c 100644 --- a/src/utils/common.ts +++ b/src/utils/common.ts @@ -473,7 +473,7 @@ export function getLocalizedSpriteKey(baseKey: string) { } /** - * Check if a number is **inclusively** between two numbers + * Check if a number is **inclusively** between two numbers. * @param num - the number to check * @param min - the minimum value (inclusive) * @param max - the maximum value (inclusive) diff --git a/src/utils/strings.ts b/src/utils/strings.ts index b4b2498fe9d..7c13bbff0dd 100644 --- a/src/utils/strings.ts +++ b/src/utils/strings.ts @@ -11,7 +11,7 @@ const SPLIT_LOWER_UPPER_RE = /([\p{Ll}\d])(\p{Lu})/gu; const SPLIT_UPPER_UPPER_RE = /(\p{Lu})([\p{Lu}][\p{Ll}])/gu; /** Regexp involved with stripping non-word delimiters from the result. */ const DELIM_STRIP_REGEXP = /[-_ ]+/giu; -// The replacement value for splits. +/** The replacement value for splits. */ const SPLIT_REPLACE_VALUE = "$1\0$2"; /** @@ -57,8 +57,6 @@ function trimFromStartAndEnd(str: string, charToTrim: string): string { return str.slice(start, end); } -// #endregion Split String code - /** * Capitalize the first letter of a string. * @param str - The string whose first letter is to be capitalized @@ -179,3 +177,26 @@ export function toPascalSnakeCase(str: string) { .map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()) .join("_"); } +// #endregion Split String code + +/** + * Chunk a string into an array, creating a new element every `length` characters. + * @param str - The string to chunk + * @param length - The length of each chunk; should be a non-negative integer + * @returns The result of splitting `str` after every instance of `length` characters. + * @example + * ```ts + * console.log(chunkString("123456789abc", 4)); // Output: ["1234", "5678", "9abc"] + * console.log(chunkString("1234567890", 4)); // Output: ["1234", "5678", "90"] + * ``` + */ +export function chunkString(str: string, length: number): string[] { + const numChunks = Math.ceil(str.length / length); + const chunks = new Array(numChunks); + + for (let i = 0; i < numChunks; i++) { + chunks[i] = str.substring(i * length, (i + 1) * length); + } + + return chunks; +} diff --git a/test/daily-mode.test.ts b/test/daily-mode.test.ts index 34a8da80478..e5284906318 100644 --- a/test/daily-mode.test.ts +++ b/test/daily-mode.test.ts @@ -5,6 +5,7 @@ import { SpeciesId } from "#enums/species-id"; import { UiMode } from "#enums/ui-mode"; import { MapModifier } from "#modifiers/modifier"; import { GameManager } from "#test/test-utils/game-manager"; +import { stringifyEnumArray } from "#test/test-utils/string-utils"; import { ModifierSelectUiHandler } from "#ui/modifier-select-ui-handler"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; @@ -20,7 +21,6 @@ describe("Daily Mode", () => { beforeEach(() => { game = new GameManager(phaserGame); - vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("test-seed"); }); afterEach(() => { @@ -28,6 +28,7 @@ describe("Daily Mode", () => { }); it("should initialize properly", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("test-seed"); await game.dailyMode.startBattle(); const party = game.scene.getPlayerParty(); @@ -36,7 +37,57 @@ describe("Daily Mode", () => { expect(pkm.level).toBe(20); expect(pkm.moveset.length).toBeGreaterThan(0); }); - expect(game.scene.getModifiers(MapModifier).length).toBeGreaterThan(0); + expect(game.scene.getModifiers(MapModifier).length).toBe(1); + }); + + describe("Custom Seeds", () => { + it("should support custom moves", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004,03320006,01300919"); + await game.dailyMode.startBattle(); + + const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId)); + expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([ + MoveId.POUND, + MoveId.KARATE_CHOP, + MoveId.DOUBLE_SLAP, + MoveId.COMET_PUNCH, + ]); + expect(moves2, stringifyEnumArray(MoveId, moves2)).toEqual([ + MoveId.AERIAL_ACE, + MoveId.PAY_DAY, + expect.anything(), // make sure it doesn't replace normal moveset gen + expect.anything(), + ]); + expect(moves3, stringifyEnumArray(MoveId, moves3)).toEqual([ + MoveId.SKULL_BASH, + MoveId.MALIGNANT_CHAIN, + expect.anything(), + expect.anything(), + ]); + }); + + it("should allow omitting movesets for some starters", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004"); + await game.dailyMode.startBattle(); + + const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId)); + expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([ + MoveId.POUND, + MoveId.KARATE_CHOP, + MoveId.DOUBLE_SLAP, + MoveId.COMET_PUNCH, + ]); + expect(moves2, "was not a random moveset").toHaveLength(4); + expect(moves3, "was not a random moveset").toHaveLength(4); + }); + + it("should skip invalid move IDs", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves9999,,0919"); + await game.dailyMode.startBattle(); + + const moves = game.field.getPlayerPokemon().moveset.map(pm => pm.moveId); + expect(moves, "invalid move was in moveset").not.toContain(MoveId[9999]); + }); }); }); From e5154850c6252968e863b6ce8f62bf1e31bef9aa Mon Sep 17 00:00:00 2001 From: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:04:25 +0100 Subject: [PATCH 17/58] [Bug][UI/UX] Display no heal and no shop ribbon if no support is unlocked (#6715) * New condition to display ribbons * Added TODO comment --- src/ui/containers/ribbon-tray-container.ts | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/ui/containers/ribbon-tray-container.ts b/src/ui/containers/ribbon-tray-container.ts index 038e03f5ef4..3737df4bf8a 100644 --- a/src/ui/containers/ribbon-tray-container.ts +++ b/src/ui/containers/ribbon-tray-container.ts @@ -115,10 +115,17 @@ export class RibbonTray extends Phaser.GameObjects.Container { const availableRibbons = getAvailableRibbons(species); const availableOrderedRibbons = orderedRibbons.filter(r => availableRibbons.includes(r)); - const hasWonClassic = globalScene.gameData.starterData[species.speciesId]?.classicWinCount > 0; + // Classic win count (always 0 for evolutions) + const classicWinCount = globalScene.gameData.starterData[species.speciesId]?.classicWinCount ?? 0; for (const ribbon of availableOrderedRibbons) { - const hasRibbon = this.ribbonData.has(ribbon) || (ribbon === RibbonData.CLASSIC && hasWonClassic); + // TODO: eventually, write a save migrator to fix the ribbon save data and get rid of these two conditions + // Display classic ribbons for starters with at least one classic win + const overrideClassicRibbon = ribbon === RibbonData.CLASSIC && classicWinCount > 0; + // Display no heal and no shop ribbons for mons that have the no support ribbon + const overrideNoSupportRibbons = + (ribbon === RibbonData.NO_HEAL || ribbon === RibbonData.NO_SHOP) && this.ribbonData.has(RibbonData.NO_SUPPORT); + const hasRibbon = this.ribbonData.has(ribbon) || overrideClassicRibbon || overrideNoSupportRibbons; if (!hasRibbon && !globalScene.dexForDevs && !globalScene.showMissingRibbons) { continue; From 79148452e9251a3bb9394c14376b599265cf7eb9 Mon Sep 17 00:00:00 2001 From: Austin Fontaine <36677462+Fontbane@users.noreply.github.com> Date: Thu, 30 Oct 2025 15:46:35 -0400 Subject: [PATCH 18/58] [Refactor] Refactor ME mon generation and event encounters, add to Safari Zone & GTS (#6695) * Refactor event encounters * Fix safari test * Apply biome fixes * Cleanup, 100% event chance for WT * Fix Safari Zone * Fix shiny chance * Run biome * Apply suggestions from code review Co-authored-by: Fabi <192151969+fabske0@users.noreply.github.com> Co-authored-by: Bertie690 <136088738+Bertie690@users.noreply.github.com> * Documentation for randomEncParams * other * Updated doc comments on interface to be less jank * >'less janky'>look inside>linting error * Update encounter-phase-utils.ts doc comment * Update encounter-phase-utils.ts * Update src/data/mystery-encounters/encounters/global-trade-system-encounter.ts Co-authored-by: Bertie690 <136088738+Bertie690@users.noreply.github.com> * thing --------- Co-authored-by: Fabi <192151969+fabske0@users.noreply.github.com> Co-authored-by: Bertie690 <136088738+Bertie690@users.noreply.github.com> Co-authored-by: damocleas --- src/@types/pokemon-common.ts | 98 +++++++++++++++++++ .../encounters/berries-abound-encounter.ts | 9 +- .../encounters/fight-or-flight-encounter.ts | 9 +- .../global-trade-system-encounter.ts | 58 ++++------- .../encounters/safari-zone-encounter.ts | 63 ++++++------ .../the-pokemon-salesman-encounter.ts | 26 ++--- .../encounters/uncommon-breed-encounter.ts | 9 +- .../utils/encounter-phase-utils.ts | 66 +++++++++---- src/data/pokemon/pokemon-data.ts | 9 +- src/field/pokemon.ts | 24 +++-- src/timed-event-manager.ts | 64 +++++++++++- 11 files changed, 318 insertions(+), 117 deletions(-) create mode 100644 src/@types/pokemon-common.ts diff --git a/src/@types/pokemon-common.ts b/src/@types/pokemon-common.ts new file mode 100644 index 00000000000..b56647c32a0 --- /dev/null +++ b/src/@types/pokemon-common.ts @@ -0,0 +1,98 @@ +import type { PokemonSpecies, PokemonSpeciesFilter } from "#data/pokemon-species"; +import type { SpeciesId } from "#enums/species-id"; +import type { BooleanHolder } from "#utils/common"; + +/** + * The type that {@linkcode PokemonSpeciesForm} is converted to when an object containing it serializes it. + */ +export type SerializedSpeciesForm = { + id: SpeciesId; + formIdx: number; +}; + +export interface RandomEncounterParams { + /** The level of the mon */ + level: number; + + /** A custom function used to return the {@linkcode PokemonSpecies} to generate */ + speciesFunction?: () => PokemonSpecies; + + /** + * Whether the Pokemon should be a Boss. + * @defaultValue `false` + */ + isBoss?: boolean; + + /** + * Whether Sub-legendaries can be encountered, mainly for event encounters + * @defaultValue `true` + */ + includeSubLegendary?: boolean; + + /** + * Whether Legendaries can be encountered + * @defaultValue `true` + */ + includeLegendary?: boolean; + + /** + * Whether Mythicals can be encountered + * @defaultValue `true` + */ + includeMythical?: boolean; + + /** + * The chance out of 100 to pick an event encounter + * @defaultValue `50` + */ + eventChance?: number; + + /** + * Number of rerolls for Hidden Ability (HA) that should be attempted + * @defaultValue `0` + */ + hiddenRerolls?: number; + + /** + * Number of rerolls for shininess/variants that should be attempted + * @defaultValue `0` + */ + shinyRerolls?: number; + + /** + * Number of extra HA rerolls for event mons + * @defaultValue `0` + */ + eventHiddenRerolls?: number; + + /** + * Number of extra shiny rerolls for event mons + * @defaultValue `0` + */ + eventShinyRerolls?: number; + + /** + * The overridden HA chance, defaults to base + */ + hiddenAbilityChance?: number; + + /** + * The overridden shiny chance, defaults to base + */ + shinyChance?: number; + + /** + * The max shiny threshold after modifiers are applied. Values below 1 mean no maximum + * @defaultValue `0` (no maximum) + */ + maxShinyChance?: number; + + /** + * An optional filter for eligible mons, applied to the event encounter pool. + * If omitted, no filter will be applied. + */ + speciesFilter?: PokemonSpeciesFilter; + + /** An optional {@linkcode BooleanHolder} used to let the caller know if it pulled from an event. */ + isEventEncounter?: BooleanHolder; +} diff --git a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts index a4f2b00b04b..41a3f7dd55a 100644 --- a/src/data/mystery-encounters/encounters/berries-abound-encounter.ts +++ b/src/data/mystery-encounters/encounters/berries-abound-encounter.ts @@ -18,7 +18,7 @@ import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils import { generateModifierType, generateModifierTypeOption, - getRandomEncounterSpecies, + getRandomEncounterPokemon, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, @@ -66,7 +66,12 @@ export const BerriesAboundEncounter: MysteryEncounter = MysteryEncounterBuilder. // Calculate boss mon const level = getEncounterPokemonLevelForWave(STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER); - const bossPokemon = getRandomEncounterSpecies(level, true); + const bossPokemon = getRandomEncounterPokemon({ + level, + isBoss: true, + eventShinyRerolls: 2, + eventHiddenRerolls: 1, + }); encounter.setDialogueToken("enemyPokemon", getPokemonNameWithAffix(bossPokemon)); const config: EnemyPartyConfig = { pokemonConfigs: [ diff --git a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts index a46bac013cc..1a5d74852c1 100644 --- a/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts +++ b/src/data/mystery-encounters/encounters/fight-or-flight-encounter.ts @@ -12,7 +12,7 @@ import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from " import { queueEncounterMessage } from "#mystery-encounters/encounter-dialogue-utils"; import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils"; import { - getRandomEncounterSpecies, + getRandomEncounterPokemon, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, @@ -58,7 +58,12 @@ export const FightOrFlightEncounter: MysteryEncounter = MysteryEncounterBuilder. // Calculate boss mon const level = getEncounterPokemonLevelForWave(STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER); - const bossPokemon = getRandomEncounterSpecies(level, true); + const bossPokemon = getRandomEncounterPokemon({ + level, + isBoss: true, + eventShinyRerolls: 2, + eventHiddenRerolls: 1, + }); encounter.setDialogueToken("enemyPokemon", bossPokemon.getNameToRender()); const config: EnemyPartyConfig = { pokemonConfigs: [ diff --git a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts index fd323edd236..0941283147a 100644 --- a/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts +++ b/src/data/mystery-encounters/encounters/global-trade-system-encounter.ts @@ -1,5 +1,4 @@ import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/constants"; -import { timedEventManager } from "#app/global-event-manager"; import { globalScene } from "#app/global-scene"; import { allSpecies } from "#data/data-lists"; import { Gender, getGenderSymbol } from "#data/gender"; @@ -20,17 +19,13 @@ import { doShinySparkleAnim } from "#field/anims"; import type { PlayerPokemon, Pokemon } from "#field/pokemon"; import { EnemyPokemon } from "#field/pokemon"; import type { PokemonHeldItemModifier } from "#modifiers/modifier"; -import { - HiddenAbilityRateBoosterModifier, - PokemonFormChangeItemModifier, - ShinyRateBoosterModifier, - SpeciesStatBoosterModifier, -} from "#modifiers/modifier"; +import { PokemonFormChangeItemModifier, SpeciesStatBoosterModifier } from "#modifiers/modifier"; import type { ModifierTypeOption } from "#modifiers/modifier-type"; import { getPlayerModifierTypeOptions, regenerateModifierPoolThresholds } from "#modifiers/modifier-type"; import { PokemonMove } from "#moves/pokemon-move"; import { getEncounterText, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils"; import { + getRandomEncounterPokemon, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, @@ -43,7 +38,7 @@ import { PartySizeRequirement } from "#mystery-encounters/mystery-encounter-requ import { PokemonData } from "#system/pokemon-data"; import { MusicPreference } from "#system/settings"; import type { OptionSelectItem } from "#ui/abstract-option-select-ui-handler"; -import { NumberHolder, randInt, randSeedInt, randSeedItem, randSeedShuffle } from "#utils/common"; +import { randInt, randSeedInt, randSeedItem, randSeedShuffle } from "#utils/common"; import { getEnumKeys } from "#utils/enums"; import { getRandomLocaleEntry } from "#utils/i18n"; import { getPokemonSpecies } from "#utils/pokemon-utils"; @@ -58,6 +53,8 @@ const WONDER_TRADE_SHINY_CHANCE = 512; /** Max shiny chance of 4096/65536 -> 1/16 odds. */ const MAX_WONDER_TRADE_SHINY_CHANCE = 4096; +const WONDER_TRADE_HIDDEN_ABILITY_CHANCE = 64; + const LEGENDARY_TRADE_POOLS = { 1: [SpeciesId.RATTATA, SpeciesId.PIDGEY, SpeciesId.WEEDLE], 2: [SpeciesId.SENTRET, SpeciesId.HOOTHOOT, SpeciesId.LEDYBA], @@ -273,38 +270,23 @@ export const GlobalTradeSystemEncounter: MysteryEncounter = MysteryEncounterBuil const encounter = globalScene.currentBattle.mysteryEncounter!; const onPokemonSelected = (pokemon: PlayerPokemon) => { // Randomly generate a Wonder Trade pokemon - const randomTradeOption = generateTradeOption(globalScene.getPlayerParty().map(p => p.species)); - const tradePokemon = new EnemyPokemon(randomTradeOption, pokemon.level, TrainerSlot.NONE, false); - // Extra shiny roll at 1/128 odds (boosted by events and charms) - if (!tradePokemon.shiny) { - const shinyThreshold = new NumberHolder(WONDER_TRADE_SHINY_CHANCE); - if (timedEventManager.isEventActive()) { - shinyThreshold.value *= timedEventManager.getShinyEncounterMultiplier(); - } - globalScene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold); - - // Base shiny chance of 512/65536 -> 1/128, affected by events and Shiny Charms - // Maximum shiny chance of 4096/65536 -> 1/16, cannot improve further after that - const shinyChance = Math.min(shinyThreshold.value, MAX_WONDER_TRADE_SHINY_CHANCE); - - tradePokemon.trySetShinySeed(shinyChance, false); - } - - // Extra HA roll at base 1/64 odds (boosted by events and charms) - const hiddenIndex = tradePokemon.species.ability2 ? 2 : 1; - if (tradePokemon.species.abilityHidden && tradePokemon.abilityIndex < hiddenIndex) { - const hiddenAbilityChance = new NumberHolder(64); - globalScene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); - - const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value); - - if (hasHiddenAbility) { - tradePokemon.abilityIndex = hiddenIndex; - } - } + const tradePokemon = getRandomEncounterPokemon({ + level: pokemon.level, + speciesFunction: () => generateTradeOption(globalScene.getPlayerParty().map(p => p.species)), + isBoss: false, + eventChance: 100, + shinyRerolls: 1, + hiddenRerolls: 1, + eventShinyRerolls: 1, + eventHiddenRerolls: 1, + hiddenAbilityChance: WONDER_TRADE_HIDDEN_ABILITY_CHANCE, + shinyChance: WONDER_TRADE_SHINY_CHANCE, + maxShinyChance: MAX_WONDER_TRADE_SHINY_CHANCE, + speciesFilter: s => !globalScene.getPlayerParty().some(p => p.species === s), + }); // If Pokemon is still not shiny or with HA, give the Pokemon a random Common egg move in its moveset - if (!tradePokemon.shiny && (!tradePokemon.species.abilityHidden || tradePokemon.abilityIndex < hiddenIndex)) { + if (!tradePokemon.shiny && (!tradePokemon.species.abilityHidden || tradePokemon.abilityIndex < 2)) { const eggMoves = tradePokemon.getEggMoves(); if (eggMoves) { // Cannot gen the rare egg move, only 1 of the first 3 common moves diff --git a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts index cfa862b5743..5960989929d 100644 --- a/src/data/mystery-encounters/encounters/safari-zone-encounter.ts +++ b/src/data/mystery-encounters/encounters/safari-zone-encounter.ts @@ -9,11 +9,11 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { PlayerGender } from "#enums/player-gender"; import { PokeballType } from "#enums/pokeball"; -import { TrainerSlot } from "#enums/trainer-slot"; import type { EnemyPokemon } from "#field/pokemon"; -import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#modifiers/modifier"; +import { IvScannerModifier } from "#modifiers/modifier"; import { getEncounterText, showEncounterText } from "#mystery-encounters/encounter-dialogue-utils"; import { + getRandomEncounterPokemon, initSubsequentOptionSelect, leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, @@ -30,7 +30,7 @@ import { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter"; import type { MysteryEncounterOption } from "#mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option"; import { MoneyRequirement } from "#mystery-encounters/mystery-encounter-requirements"; -import { NumberHolder, randSeedInt } from "#utils/common"; +import { BooleanHolder, NumberHolder, randSeedInt } from "#utils/common"; import { getPokemonSpecies } from "#utils/pokemon-utils"; /** the i18n namespace for the encounter */ @@ -42,6 +42,9 @@ const SAFARI_MONEY_MULTIPLIER = 2; const NUM_SAFARI_ENCOUNTERS = 3; +const eventEncs = new NumberHolder(0); +const eventChance = new NumberHolder(50); + /** * Safari Zone encounter. * @see {@link https://github.com/pagefaultgames/pokerogue/issues/3800 | GitHub Issue #3800} @@ -74,6 +77,8 @@ export const SafariZoneEncounter: MysteryEncounter = MysteryEncounterBuilder.wit .withQuery(`${namespace}:query`) .withOnInit(() => { globalScene.currentBattle.mysteryEncounter?.setDialogueToken("numEncounters", NUM_SAFARI_ENCOUNTERS.toString()); + eventEncs.value = 0; + eventChance.value = 50; return true; }) .withOption( @@ -279,37 +284,37 @@ async function summonSafariPokemon() { // Generate pokemon using safariPokemonRemaining so they are always the same pokemon no matter how many turns are taken // Safari pokemon roll twice on shiny and HA chances, but are otherwise normal - let enemySpecies: PokemonSpecies; let pokemon: any; globalScene.executeWithSeedOffset( () => { - enemySpecies = getSafariSpeciesSpawn(); - const level = globalScene.currentBattle.getLevelForWave(); - enemySpecies = getPokemonSpecies(enemySpecies.getWildSpeciesForLevel(level, true, false, globalScene.gameMode)); - pokemon = globalScene.addEnemyPokemon(enemySpecies, level, TrainerSlot.NONE, false); + console.log("Event chance %d", eventChance.value); + const fromEvent = new BooleanHolder(false); + pokemon = getRandomEncounterPokemon({ + level: globalScene.currentBattle.getLevelForWave(), + includeLegendary: false, + includeSubLegendary: false, + includeMythical: false, + speciesFunction: getSafariSpeciesSpawn, + shinyRerolls: 1, + eventShinyRerolls: 1, + hiddenRerolls: 1, + eventHiddenRerolls: 1, + eventChance: eventChance.value, + isEventEncounter: fromEvent, + }); - // Roll shiny twice - if (!pokemon.shiny) { - pokemon.trySetShinySeed(); + pokemon.init(); + + // Increase chance of event encounter by 25% until one spawns + if (fromEvent.value) { + console.log("Safari zone encounter is from event"); + eventEncs.value++; + eventChance.value = 50; + } else if (eventEncs.value === 0) { + console.log("Safari zone encounter is not from event"); + eventChance.value += 25; } - // Roll HA twice - if (pokemon.species.abilityHidden) { - const hiddenIndex = pokemon.species.ability2 ? 2 : 1; - if (pokemon.abilityIndex < hiddenIndex) { - const hiddenAbilityChance = new NumberHolder(256); - globalScene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); - - const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value); - - if (hasHiddenAbility) { - pokemon.abilityIndex = hiddenIndex; - } - } - } - - pokemon.calculateStats(); - globalScene.currentBattle.enemyParty.unshift(pokemon); }, globalScene.currentBattle.waveIndex * 1000 * encounter.misc.safariPokemonRemaining, @@ -569,7 +574,7 @@ async function doEndTurn(cursorIndex: number) { } /** - * @returns A random species that has at most 5 starter cost and is not Mythical, Paradox, etc. + * @returns A function to get a random species that has at most 5 starter cost and is not Mythical, Paradox, etc. */ export function getSafariSpeciesSpawn(): PokemonSpecies { return getPokemonSpecies( diff --git a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts index 51efa0c7586..763b1229ee5 100644 --- a/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts +++ b/src/data/mystery-encounters/encounters/the-pokemon-salesman-encounter.ts @@ -77,6 +77,8 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui .withOnInit(() => { const encounter = globalScene.currentBattle.mysteryEncounter!; + let isEventEncounter = false; + let species = getSalesmanSpeciesOffer(); let tries = 0; @@ -88,16 +90,12 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui const r = randSeedInt(SHINY_MAGIKARP_WEIGHT); - const validEventEncounters = timedEventManager - .getEventEncounters() - .filter( - s => - !getPokemonSpecies(s.species).legendary - && !getPokemonSpecies(s.species).subLegendary - && !getPokemonSpecies(s.species).mythical - && !NON_LEGEND_PARADOX_POKEMON.includes(s.species) - && !NON_LEGEND_ULTRA_BEASTS.includes(s.species), - ); + const validEventEncounters = timedEventManager.getAllValidEventEncounters( + false, + false, + false, + s => !NON_LEGEND_PARADOX_POKEMON.includes(s.speciesId) && !NON_LEGEND_ULTRA_BEASTS.includes(s.speciesId), + ); let pokemon: PlayerPokemon; /** @@ -122,7 +120,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui ) { tries = 0; do { - // If you roll 20%, give event encounter with 3 extra shiny rolls and its HA, if it has one + // If you roll 50%, give event encounter with 3 extra shiny rolls and its HA, if it has one const enc = randSeedItem(validEventEncounters); species = getPokemonSpecies(enc.species); pokemon = new PlayerPokemon( @@ -135,6 +133,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui pokemon.trySetShinySeed(); pokemon.trySetShinySeed(); if (pokemon.shiny || pokemon.abilityIndex === 2) { + isEventEncounter = true; break; } tries++; @@ -149,6 +148,7 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui pokemon.trySetShinySeed(); pokemon.trySetShinySeed(); pokemon.trySetShinySeed(); + isEventEncounter = true; } else { // If there's, and this would never happen, no eligible event encounters with a hidden ability, just do Magikarp species = getPokemonSpecies(SpeciesId.MAGIKARP); @@ -177,7 +177,9 @@ export const ThePokemonSalesmanEncounter: MysteryEncounter = MysteryEncounterBui if (pokemon.shiny) { // Always max price for shiny (flip HA back to normal), and add special messaging priceMultiplier = MAX_POKEMON_PRICE_MULTIPLIER; - pokemon.abilityIndex = 0; + if (!isEventEncounter) { + pokemon.abilityIndex = 0; + } encounter.dialogue.encounterOptionsDialogue!.description = `${namespace}:descriptionShiny`; encounter.options[0].dialogue!.buttonTooltip = `${namespace}:option.1.tooltipShiny`; } diff --git a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts index cd61a6852f7..7cd6b5e62cc 100644 --- a/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts +++ b/src/data/mystery-encounters/encounters/uncommon-breed-encounter.ts @@ -15,7 +15,7 @@ import { PokemonMove } from "#moves/pokemon-move"; import { queueEncounterMessage } from "#mystery-encounters/encounter-dialogue-utils"; import type { EnemyPartyConfig } from "#mystery-encounters/encounter-phase-utils"; import { - getRandomEncounterSpecies, + getRandomEncounterPokemon, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, @@ -62,7 +62,12 @@ export const UncommonBreedEncounter: MysteryEncounter = MysteryEncounterBuilder. // Calculate boss mon // Level equal to 2 below highest party member const level = getHighestLevelPlayerPokemon(false, true).level - 2; - const pokemon = getRandomEncounterSpecies(level, true, true); + const pokemon = getRandomEncounterPokemon({ + level, + isBoss: true, + eventShinyRerolls: 2, + eventHiddenRerolls: 1, + }); // Pokemon will always have one of its egg moves in its moveset const eggMoves = pokemon.getEggMoves(); diff --git a/src/data/mystery-encounters/utils/encounter-phase-utils.ts b/src/data/mystery-encounters/utils/encounter-phase-utils.ts index d5aecf7055a..64162a1b2ad 100644 --- a/src/data/mystery-encounters/utils/encounter-phase-utils.ts +++ b/src/data/mystery-encounters/utils/encounter-phase-utils.ts @@ -4,6 +4,7 @@ import { timedEventManager } from "#app/global-event-manager"; import { globalScene } from "#app/global-scene"; import { getPokemonNameWithAffix } from "#app/messages"; import { biomeLinks } from "#balance/biomes"; +import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE } from "#balance/rates"; import { initMoveAnim, loadMoveAnimAssets } from "#data/battle-anims"; import { modifierTypes } from "#data/data-lists"; import type { IEggOptions } from "#data/egg"; @@ -47,11 +48,12 @@ import type { PokemonData } from "#system/pokemon-data"; import type { TrainerConfig } from "#trainers/trainer-config"; import { trainerConfigs } from "#trainers/trainer-config"; import type { HeldModifierConfig } from "#types/held-modifier-config"; +import type { RandomEncounterParams } from "#types/pokemon-common"; import type { OptionSelectConfig, OptionSelectItem } from "#ui/abstract-option-select-ui-handler"; import type { PartyOption, PokemonSelectFilter } from "#ui/party-ui-handler"; import { PartyUiMode } from "#ui/party-ui-handler"; import { coerceArray } from "#utils/array"; -import { randomString, randSeedInt, randSeedItem } from "#utils/common"; +import { BooleanHolder, randomString, randSeedInt, randSeedItem } from "#utils/common"; import { getPokemonSpecies } from "#utils/pokemon-utils"; import i18next from "i18next"; @@ -990,19 +992,39 @@ export function handleMysteryEncounterTurnStartEffects(): boolean { /** * Helper function for encounters such as {@linkcode UncommonBreedEncounter} which call for a random species including event encounters. - * If the mon is from the event encounter list, it will do an extra shiny roll. - * @param level the level of the mon, which differs between MEs - * @param isBoss whether the mon should be a Boss - * @param rerollHidden whether the mon should get an extra roll for Hidden Ability - * @returns for the requested encounter + * If the mon is from the event encounter list, it may do an extra shiny or HA roll. + * @param params - The {@linkcode RandomEncounterParams} used to configure the encounter + * @returns The generated {@linkcode EnemyPokemon} for the requested encounter */ -export function getRandomEncounterSpecies(level: number, isBoss = false, rerollHidden = false): EnemyPokemon { +export function getRandomEncounterPokemon(params: RandomEncounterParams): EnemyPokemon { + let { + level, + speciesFunction, + isBoss = false, + includeSubLegendary = true, + includeLegendary = true, + includeMythical = true, + eventChance = 50, + hiddenRerolls = 0, + shinyRerolls = 0, + eventHiddenRerolls = 0, + eventShinyRerolls = 0, + hiddenAbilityChance = BASE_HIDDEN_ABILITY_CHANCE, + shinyChance = BASE_SHINY_CHANCE, + maxShinyChance = 0, + speciesFilter = () => true, + isEventEncounter = new BooleanHolder(false), + } = params; let bossSpecies: PokemonSpecies; - let isEventEncounter = false; - const eventEncounters = timedEventManager.getEventEncounters(); + const eventEncounters = timedEventManager.getAllValidEventEncounters( + includeSubLegendary, + includeLegendary, + includeMythical, + speciesFilter, + ); let formIndex: number | undefined; - if (eventEncounters.length > 0 && randSeedInt(2) === 1) { + if (eventChance && eventEncounters.length > 0 && (eventChance === 100 || randSeedInt(100) < eventChance)) { const eventEncounter = randSeedItem(eventEncounters); const levelSpecies = getPokemonSpecies(eventEncounter.species).getWildSpeciesForLevel( level, @@ -1010,9 +1032,13 @@ export function getRandomEncounterSpecies(level: number, isBoss = false, rerollH isBoss, globalScene.gameMode, ); - isEventEncounter = true; + if (params.isEventEncounter) { + params.isEventEncounter.value = true; + } bossSpecies = getPokemonSpecies(levelSpecies); formIndex = eventEncounter.formIndex; + } else if (speciesFunction) { + bossSpecies = speciesFunction(); } else { bossSpecies = globalScene.arena.randomSpecies( globalScene.currentBattle.waveIndex, @@ -1027,13 +1053,19 @@ export function getRandomEncounterSpecies(level: number, isBoss = false, rerollH ret.formIndex = formIndex; } - //Reroll shiny or variant for event encounters - if (isEventEncounter) { - ret.trySetShinySeed(); + if (isEventEncounter.value) { + hiddenRerolls += eventHiddenRerolls; + shinyRerolls += eventShinyRerolls; } - //Reroll hidden ability - if (rerollHidden && ret.abilityIndex !== 2 && ret.species.abilityHidden) { - ret.tryRerollHiddenAbilitySeed(); + + while (shinyRerolls > 0) { + ret.trySetShinySeed(shinyChance, true, maxShinyChance); + shinyRerolls--; + } + + while (hiddenRerolls > 0) { + ret.tryRerollHiddenAbilitySeed(hiddenAbilityChance, true); + hiddenRerolls--; } return ret; diff --git a/src/data/pokemon/pokemon-data.ts b/src/data/pokemon/pokemon-data.ts index 0094e7310e9..f0a0fc88c59 100644 --- a/src/data/pokemon/pokemon-data.ts +++ b/src/data/pokemon/pokemon-data.ts @@ -13,18 +13,11 @@ import type { SpeciesId } from "#enums/species-id"; import { StatusEffect } from "#enums/status-effect"; import type { AttackMoveResult } from "#types/attack-move-result"; import type { IllusionData } from "#types/illusion-data"; +import type { SerializedSpeciesForm } from "#types/pokemon-common"; import type { TurnMove } from "#types/turn-move"; import type { CoerceNullPropertiesToUndefined } from "#types/type-helpers"; import { getPokemonSpecies, getPokemonSpeciesForm } from "#utils/pokemon-utils"; -/** - * The type that {@linkcode PokemonSpeciesForm} is converted to when an object containing it serializes it. - */ -type SerializedSpeciesForm = { - id: SpeciesId; - formIdx: number; -}; - /** * Permanent data that can customize a Pokemon in non-standard ways from its Species. * Includes abilities, nature, changed types, etc. diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6f9d8b53249..835b9d92c89 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -2903,12 +2903,15 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { if (thresholdOverride === undefined) { if (timedEventManager.isEventActive()) { const tchance = timedEventManager.getClassicTrainerShinyChance(); - shinyThreshold.value *= timedEventManager.getShinyEncounterMultiplier(); - if (this.hasTrainer() && tchance > 0) { + if (this.isEnemy() && this.hasTrainer() && tchance > 0) { shinyThreshold.value = Math.max(tchance, shinyThreshold.value); // Choose the higher boost + } else { + // Wild shiny event multiplier + shinyThreshold.value *= timedEventManager.getShinyEncounterMultiplier(); } } - if (!this.hasTrainer()) { + if (this.isPlayer() || !this.hasTrainer()) { + // Apply shiny modifiers only to Player or wild mons globalScene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold); } } else { @@ -2932,11 +2935,16 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * If it rolls shiny, or if it's already shiny, also sets a random variant and give the Pokemon the associated luck. * * The base shiny odds are {@linkcode BASE_SHINY_CHANCE} / `65536` - * @param thresholdOverride - number that is divided by `2^16` (`65536`) to get the shiny chance, overrides {@linkcode shinyThreshold} if set (bypassing shiny rate modifiers such as Shiny Charm) - * @param applyModifiersToOverride - If {@linkcode thresholdOverride} is set and this is true, will apply Shiny Charm and event modifiers to {@linkcode thresholdOverride} + * @param thresholdOverride number that is divided by `2^16` (`65536`) to get the shiny chance, overrides {@linkcode shinyThreshold} if set (bypassing shiny rate modifiers such as Shiny Charm) + * @param applyModifiersToOverride If {@linkcode thresholdOverride} is set and this is true, will apply Shiny Charm and event modifiers to {@linkcode thresholdOverride} + * @param maxThreshold The maximum threshold allowed after applying modifiers * @returns Whether this Pokémon was set to shiny */ - public trySetShinySeed(thresholdOverride?: number, applyModifiersToOverride?: boolean): boolean { + public trySetShinySeed( + thresholdOverride?: number, + applyModifiersToOverride?: boolean, + maxThreshold?: number, + ): boolean { if (!this.shiny) { const shinyThreshold = new NumberHolder(thresholdOverride ?? BASE_SHINY_CHANCE); if (applyModifiersToOverride) { @@ -2946,6 +2954,10 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { globalScene.applyModifiers(ShinyRateBoosterModifier, true, shinyThreshold); } + if (maxThreshold && maxThreshold > 0) { + shinyThreshold.value = Math.min(maxThreshold, shinyThreshold.value); + } + this.shiny = randSeedInt(65536) < shinyThreshold.value; } diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 391b68d414e..68c0fd07a4c 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -1,6 +1,7 @@ import { globalScene } from "#app/global-scene"; import { SHINY_CATCH_RATE_MULTIPLIER } from "#balance/rates"; import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER } from "#balance/starters"; +import type { PokemonSpeciesFilter } from "#data/pokemon-species"; import type { WeatherPoolEntry } from "#data/weather"; import { Challenges } from "#enums/challenges"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; @@ -11,6 +12,7 @@ import { WeatherType } from "#enums/weather-type"; import type { ModifierTypeKeys } from "#modifiers/modifier-type"; import type { nil } from "#types/common"; import { addTextObject } from "#ui/text"; +import { getPokemonSpecies } from "#utils/pokemon-utils"; import i18next from "i18next"; export enum EventType { @@ -27,7 +29,7 @@ interface EventBanner { readonly availableLangs?: readonly string[]; } -interface EventEncounter { +export interface EventEncounter { readonly species: SpeciesId; readonly blockEvolution?: boolean; readonly formIndex?: number; @@ -390,6 +392,49 @@ const timedEvents: readonly TimedEvent[] = [ ], dailyRunStartingItems: ["SHINY_CHARM", "ABILITY_CHARM"], }, + { + name: "Halloween 25", + eventType: EventType.SHINY, + startDate: new Date(Date.UTC(2025, 9, 29)), + endDate: new Date(Date.UTC(2025, 10, 10)), + bannerKey: "halloween2025", + scale: 0.25, // Replace with actual number + availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-419", "pt-BR", "zh-Hans", "zh-Hant"], + shinyEncounterMultiplier: 2, + shinyCatchMultiplier: 3, + eventEncounters: [ + { species: SpeciesId.CATERPIE }, + { species: SpeciesId.SPEAROW }, + { species: SpeciesId.PARAS }, + { species: SpeciesId.LICKITUNG }, + { species: SpeciesId.AERODACTYL }, + { species: SpeciesId.SMOOCHUM }, + { species: SpeciesId.RALTS }, + { species: SpeciesId.GULPIN }, + { species: SpeciesId.FEEBAS }, + { species: SpeciesId.WYNAUT }, + { species: SpeciesId.CLAMPERL }, + { species: SpeciesId.BUDEW }, + { species: SpeciesId.DEOXYS }, + { species: SpeciesId.CHINGLING }, + { species: SpeciesId.DWEBBLE }, + { species: SpeciesId.TIRTOUGA }, + { species: SpeciesId.LARVESTA }, + { species: SpeciesId.SPRITZEE }, + { species: SpeciesId.SWIRLIX }, + { species: SpeciesId.BINACLE }, + { species: SpeciesId.PUMPKABOO }, + { species: SpeciesId.SANDYGAST }, + ], + classicWaveRewards: [ + { wave: 8, type: "SHINY_CHARM" }, + { wave: 8, type: "ABILITY_CHARM" }, + { wave: 8, type: "CATCHING_CHARM" }, + { wave: 25, type: "SHINY_CHARM" }, + { wave: 25, type: "CANDY_JAR" }, + ], + dailyRunStartingItems: ["ABILITY_CHARM", "SHINY_CHARM", "CANDY_JAR"], + }, ]; export class TimedEventManager { @@ -450,6 +495,23 @@ export class TimedEventManager { return [...(this.activeEvent()?.eventEncounters ?? [])]; } + getAllValidEventEncounters( + allowSubLegendary = true, + allowLegendary = true, + allowMythical = true, + speciesFilter: PokemonSpeciesFilter, + ): EventEncounter[] { + return this.getEventEncounters().filter(enc => { + const species = getPokemonSpecies(enc.species); + return ( + (allowSubLegendary || !species.subLegendary) + && (allowLegendary || !species.legendary) + && (allowMythical || !species.mythical) + && speciesFilter(species) + ); + }); + } + /** * For events that change the classic candy friendship multiplier * @returns The classic friendship multiplier of the active {@linkcode TimedEvent}, or the default {@linkcode CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER} From f791d751e8534c0ef246d95b56cae75cce75071c Mon Sep 17 00:00:00 2001 From: damocleas Date: Thu, 30 Oct 2025 16:13:36 -0400 Subject: [PATCH 19/58] Update assets --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index c5d6e54c2c8..9ac85a7b9c4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit c5d6e54c2c8c0ba3d6c11fd6f3a1c1d07efd2c16 +Subproject commit 9ac85a7b9c4a38976d437569bccab31e45d45346 From c405972e63c98ea96f8dea15f9a2ea02f47b7de5 Mon Sep 17 00:00:00 2001 From: damocleas Date: Thu, 30 Oct 2025 16:49:43 -0400 Subject: [PATCH 20/58] Update assets --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 9ac85a7b9c4..90a227d51fc 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 9ac85a7b9c4a38976d437569bccab31e45d45346 +Subproject commit 90a227d51fcf44c044198afc2753b71fb3da39cd From 77eab80ee5bf356b94590e5fb89825a2a3d137c5 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Thu, 30 Oct 2025 16:06:03 -0500 Subject: [PATCH 21/58] Revert assets to commit 9ac85a7b9 Un-breaking the assets from the previous commit --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 90a227d51fc..9ac85a7b9c4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 90a227d51fcf44c044198afc2753b71fb3da39cd +Subproject commit 9ac85a7b9c4a38976d437569bccab31e45d45346 From a05bd90eb3eadc4b2f9941735c96cb8299315a8d Mon Sep 17 00:00:00 2001 From: damocleas Date: Thu, 30 Oct 2025 18:07:02 -0400 Subject: [PATCH 22/58] Update assets --- assets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets b/assets index 9ac85a7b9c4..55bf128a5c4 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 9ac85a7b9c4a38976d437569bccab31e45d45346 +Subproject commit 55bf128a5c443b48f73744b9de140713b8d283ec From 8650aebd4076b8a74bcab78ddfa93fd501572be5 Mon Sep 17 00:00:00 2001 From: Fabi <192151969+fabske0@users.noreply.github.com> Date: Thu, 30 Oct 2025 23:11:30 +0100 Subject: [PATCH 23/58] [Misc] Allow setting daily boss variant via custom seed (#6714) * Add option to set shiny boss * Update src/data/daily-run.ts Co-authored-by: Bertie690 <136088738+Bertie690@users.noreply.github.com> --- src/data/daily-run.ts | 26 ++++++++++++++++++++++++++ src/field/pokemon.ts | 9 +++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index b86442fac0f..ea2852976e8 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -6,6 +6,7 @@ import { BiomeId } from "#enums/biome-id"; import { MoveId } from "#enums/move-id"; import { PartyMemberStrength } from "#enums/party-member-strength"; import { SpeciesId } from "#enums/species-id"; +import type { Variant } from "#sprites/variant"; import type { Starter, StarterMoveset } from "#types/save-data"; import { isBetween, randSeedGauss, randSeedInt, randSeedItem } from "#utils/common"; import { getEnumValues } from "#utils/enums"; @@ -283,6 +284,31 @@ export function getDailyEventSeedBoss(seed: string): PokemonSpeciesForm | null { return starterForm; } +/** + * Expects the seed to contain `/boss\d{4}\d{2}\d{2}/` + * where the first 4 digits are the species ID, the next 2 digits are the form index, and the last 2 digits are the variant. + * Only the last 2 digits matter for the variant, and it is clamped to 0-2. + * (left padded with `0`s as necessary). + * @returns A {@linkcode Variant} to be used for the boss, or `null` if no valid match. + */ +export function getDailyEventSeedBossVariant(seed: string): Variant | null { + if (!isDailyEventSeed(seed)) { + return null; + } + + const match = /boss\d{6}(\d{2})/g.exec(seed); + if (!match || match.length !== 2) { + return null; + } + + const variant = Number.parseInt(match[1]) as Variant; + if (variant > 2) { + return null; + } + + return variant; +} + /** * Expects the seed to contain `/biome\d{2}/` where the 2 digits are a biome ID (left padded with `0` if necessary). * @returns The biome to use or `null` if no valid match. diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 835b9d92c89..be85e2ebe3a 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -39,7 +39,7 @@ import { TrappedTag, TypeImmuneTag, } from "#data/battler-tags"; -import { getDailyEventSeedBoss } from "#data/daily-run"; +import { getDailyEventSeedBoss, getDailyEventSeedBossVariant } from "#data/daily-run"; import { allAbilities, allMoves } from "#data/data-lists"; import { getLevelTotalExp } from "#data/exp"; import { @@ -6387,8 +6387,13 @@ export class EnemyPokemon extends Pokemon { this.initShinySparkle(); } + const eventBossVariant = getDailyEventSeedBossVariant(globalScene.seed); + if (eventBossVariant != null && globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)) { + this.shiny = true; + } + if (this.shiny) { - this.variant = this.generateShinyVariant(); + this.variant = eventBossVariant ?? this.generateShinyVariant(); if (Overrides.ENEMY_VARIANT_OVERRIDE !== null) { this.variant = Overrides.ENEMY_VARIANT_OVERRIDE; } From 3e3b4173f1488da9a7ac67f200cb51d573a3850b Mon Sep 17 00:00:00 2001 From: damocleas Date: Thu, 30 Oct 2025 18:31:48 -0400 Subject: [PATCH 24/58] balance fixes (#6716) * Update passives.ts revert zygarde because it doesn't work right now * Update tms.ts * shoot gholdengo * filtering duraludon --- src/data/balance/passives.ts | 4 ++-- src/data/balance/tms.ts | 10 +++++----- src/data/trainers/rival-party-config.ts | 1 - 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index 592cee69d7d..223f50471e8 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -753,7 +753,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.NOIVERN]: { 0: AbilityId.PUNK_ROCK }, [SpeciesId.XERNEAS]: { 0: AbilityId.HARVEST, 1: AbilityId.HARVEST }, [SpeciesId.YVELTAL]: { 0: AbilityId.SOUL_HEART }, - [SpeciesId.ZYGARDE]: { 0: AbilityId.TERAFORM_ZERO, 1: AbilityId.MOXIE, 2: AbilityId.TERAFORM_ZERO, 3: AbilityId.MOXIE, 4: AbilityId.ADAPTABILITY, 5: AbilityId.ADAPTABILITY }, + [SpeciesId.ZYGARDE]: { 0: AbilityId.UNNERVE, 1: AbilityId.MOXIE, 2: AbilityId.UNNERVE, 3: AbilityId.MOXIE, 4: AbilityId.ADAPTABILITY, 5: AbilityId.ADAPTABILITY }, [SpeciesId.DIANCIE]: { 0: AbilityId.SOLID_ROCK, 1: AbilityId.PRISM_ARMOR }, [SpeciesId.HOOPA]: { 0: AbilityId.OPPORTUNIST, 1: AbilityId.OPPORTUNIST }, [SpeciesId.VOLCANION]: { 0: AbilityId.NEUTRALIZING_GAS }, @@ -934,7 +934,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.ARCTOZOLT]: { 0: AbilityId.WATER_ABSORB }, [SpeciesId.DRACOVISH]: { 0: AbilityId.THERMAL_EXCHANGE }, [SpeciesId.ARCTOVISH]: { 0: AbilityId.STRONG_JAW }, - [SpeciesId.DURALUDON]: { 0: AbilityId.FILTER, 1: AbilityId.UNAWARE }, + [SpeciesId.DURALUDON]: { 0: AbilityId.FILTER, 1: AbilityId.FILTER }, [SpeciesId.ARCHALUDON]: { 0: AbilityId.TRANSISTOR }, [SpeciesId.DREEPY]: { 0: AbilityId.TECHNICIAN }, [SpeciesId.DRAKLOAK]: { 0: AbilityId.PARENTAL_BOND }, diff --git a/src/data/balance/tms.ts b/src/data/balance/tms.ts index 0ca2c77866b..75413a261ef 100644 --- a/src/data/balance/tms.ts +++ b/src/data/balance/tms.ts @@ -144,7 +144,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.SPITE]: ModifierTier.COMMON, [MoveId.PROTECT]: ModifierTier.COMMON, [MoveId.SCARY_FACE]: ModifierTier.GREAT, - [MoveId.SLUDGE_BOMB]: ModifierTier.GREAT, + [MoveId.SLUDGE_BOMB]: ModifierTier.ULTRA, [MoveId.MUD_SLAP]: ModifierTier.COMMON, [MoveId.SPIKES]: ModifierTier.COMMON, [MoveId.ICY_WIND]: ModifierTier.GREAT, @@ -195,7 +195,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.RECYCLE]: ModifierTier.COMMON, [MoveId.REVENGE]: ModifierTier.GREAT, [MoveId.BRICK_BREAK]: ModifierTier.GREAT, - [MoveId.KNOCK_OFF]: ModifierTier.GREAT, + [MoveId.KNOCK_OFF]: ModifierTier.ULTRA, [MoveId.ENDEAVOR]: ModifierTier.COMMON, [MoveId.SKILL_SWAP]: ModifierTier.COMMON, [MoveId.IMPRISON]: ModifierTier.COMMON, @@ -299,7 +299,7 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.VENOSHOCK]: ModifierTier.GREAT, [MoveId.MAGIC_ROOM]: ModifierTier.COMMON, [MoveId.SMACK_DOWN]: ModifierTier.COMMON, - [MoveId.SLUDGE_WAVE]: ModifierTier.GREAT, + [MoveId.SLUDGE_WAVE]: ModifierTier.ULTRA, [MoveId.HEAVY_SLAM]: ModifierTier.GREAT, [MoveId.ELECTRO_BALL]: ModifierTier.GREAT, [MoveId.FLAME_CHARGE]: ModifierTier.GREAT, @@ -351,9 +351,9 @@ export const tmPoolTiers: TmPoolTiers = { [MoveId.POWER_UP_PUNCH]: ModifierTier.GREAT, [MoveId.DARKEST_LARIAT]: ModifierTier.GREAT, [MoveId.HIGH_HORSEPOWER]: ModifierTier.ULTRA, - [MoveId.SOLAR_BLADE]: ModifierTier.GREAT, + [MoveId.SOLAR_BLADE]: ModifierTier.ULTRA, [MoveId.THROAT_CHOP]: ModifierTier.GREAT, - [MoveId.POLLEN_PUFF]: ModifierTier.GREAT, + [MoveId.POLLEN_PUFF]: ModifierTier.ULTRA, [MoveId.PSYCHIC_TERRAIN]: ModifierTier.COMMON, [MoveId.LUNGE]: ModifierTier.GREAT, [MoveId.SPEED_SWAP]: ModifierTier.COMMON, diff --git a/src/data/trainers/rival-party-config.ts b/src/data/trainers/rival-party-config.ts index 31e72ec5fd7..b5a8cb532b3 100644 --- a/src/data/trainers/rival-party-config.ts +++ b/src/data/trainers/rival-party-config.ts @@ -520,7 +520,6 @@ const SLOT_5_FINAL = [ SpeciesId.DRAGAPULT, SpeciesId.KINGAMBIT, SpeciesId.BAXCALIBUR, - SpeciesId.GHOLDENGO, SpeciesId.ARCHALUDON, SpeciesId.HYDRAPPLE, SpeciesId.HISUI_GOODRA, From 005b3e6eedc90989dc22b85e2c40f7f8c90cba69 Mon Sep 17 00:00:00 2001 From: damocleas Date: Thu, 30 Oct 2025 18:34:48 -0400 Subject: [PATCH 25/58] update assets and thing --- assets | 2 +- src/timed-event-manager.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/assets b/assets index 55bf128a5c4..d2d9309cd1a 160000 --- a/assets +++ b/assets @@ -1 +1 @@ -Subproject commit 55bf128a5c443b48f73744b9de140713b8d283ec +Subproject commit d2d9309cd1acfcebeefbf4c1c63e1104a1294ed8 diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 68c0fd07a4c..5fa6ef0bb87 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -395,10 +395,10 @@ const timedEvents: readonly TimedEvent[] = [ { name: "Halloween 25", eventType: EventType.SHINY, - startDate: new Date(Date.UTC(2025, 9, 29)), + startDate: new Date(Date.UTC(2025, 9, 30)), endDate: new Date(Date.UTC(2025, 10, 10)), bannerKey: "halloween2025", - scale: 0.25, // Replace with actual number + scale: 0.19, availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-419", "pt-BR", "zh-Hans", "zh-Hant"], shinyEncounterMultiplier: 2, shinyCatchMultiplier: 3, From 3159846c508ea4ca2a9c6900591be8bc63742f87 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 30 Oct 2025 16:00:28 -0700 Subject: [PATCH 26/58] [Test] Update some sprite tests to give useful errors on fail --- test/sprites/pokemon-sprite.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/sprites/pokemon-sprite.test.ts b/test/sprites/pokemon-sprite.test.ts index 73fb4b9c7fc..346400874e4 100644 --- a/test/sprites/pokemon-sprite.test.ts +++ b/test/sprites/pokemon-sprite.test.ts @@ -190,7 +190,7 @@ describe("check if every variant's sprite are correctly set", () => { if (errors.length > 0) { console.log("errors", errors); } - expect(errors.length).toBe(0); + expect(errors).toEqual([]); }); it("check exp back male variant files", () => { @@ -270,7 +270,7 @@ describe("check if every variant's sprite are correctly set", () => { if (errors.length > 0) { console.log("errors for ", dirPath, errors); } - expect(errors.length).toBe(0); + expect(errors).toEqual([]); }); it("look over every file in variant exp female and check if present in masterlist", () => { From bfc5aed0ce3d0884be328016be0b82feafb15bf3 Mon Sep 17 00:00:00 2001 From: damocleas Date: Thu, 30 Oct 2025 19:23:33 -0400 Subject: [PATCH 27/58] fix --- src/timed-event-manager.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/timed-event-manager.ts b/src/timed-event-manager.ts index 5fa6ef0bb87..32a49f0a704 100644 --- a/src/timed-event-manager.ts +++ b/src/timed-event-manager.ts @@ -399,7 +399,7 @@ const timedEvents: readonly TimedEvent[] = [ endDate: new Date(Date.UTC(2025, 10, 10)), bannerKey: "halloween2025", scale: 0.19, - availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-419", "pt-BR", "zh-Hans", "zh-Hant"], + availableLangs: ["en", "de", "it", "fr", "ja", "ko", "es-ES", "es-419", "pt-BR", "zh-Hans", "zh-Hant", "da", "ru"], shinyEncounterMultiplier: 2, shinyCatchMultiplier: 3, eventEncounters: [ From a48952e354e69a341f12982cbf46dd6ca05debbf Mon Sep 17 00:00:00 2001 From: damocleas Date: Thu, 30 Oct 2025 21:08:00 -0400 Subject: [PATCH 28/58] [Balance] [Bug] Fix Rhydon not being a Rhyhorn in Rival 2 --- src/data/trainers/rival-party-config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/trainers/rival-party-config.ts b/src/data/trainers/rival-party-config.ts index b5a8cb532b3..fa040ff66de 100644 --- a/src/data/trainers/rival-party-config.ts +++ b/src/data/trainers/rival-party-config.ts @@ -253,7 +253,7 @@ const SLOT_3_FIGHT_2 = [ SpeciesId.MACHOP, SpeciesId.GASTLY, SpeciesId.MAGNEMITE, - SpeciesId.RHYDON, + SpeciesId.RHYHORN, SpeciesId.TANGELA, SpeciesId.PORYGON, SpeciesId.ELEKID, From 9a4381c7766482b3996d29ced5dfe79dc8fed2f4 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Thu, 30 Oct 2025 18:58:06 -0700 Subject: [PATCH 29/58] Re-Add MovePriorityModifier --- src/data/abilities/ability.ts | 25 +++++++++++++++++++++++-- src/data/moves/move.ts | 13 ++++++++----- src/data/terrain.ts | 2 +- src/enums/move-priority-modifier.ts | 13 +++++++++++++ src/queues/move-phase-priority-queue.ts | 7 +++++++ test/arena/psychic-terrain.test.ts | 4 ++-- 6 files changed, 54 insertions(+), 10 deletions(-) create mode 100644 src/enums/move-priority-modifier.ts diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 301016d899b..180ba0f3e90 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -34,6 +34,7 @@ import { MoveCategory } from "#enums/move-category"; import { MoveFlags } from "#enums/move-flags"; import { MoveId } from "#enums/move-id"; import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; +import { MovePriorityModifier } from "#enums/move-priority-modifier"; import { MoveResult } from "#enums/move-result"; import { MoveTarget } from "#enums/move-target"; import { MoveUseMode } from "#enums/move-use-mode"; @@ -4142,6 +4143,25 @@ export class ChangeMovePriorityAbAttr extends AbAttr { } } +export class ChangeMovePriorityModifierAbAttr extends AbAttr { + private readonly newModifier: MovePriorityModifier; + private readonly moveFunc: (pokemon: Pokemon, move: Move) => boolean; + + constructor(moveFunc: (pokemon: Pokemon, move: Move) => boolean, newModifier: MovePriorityModifier) { + super(false); + this.newModifier = newModifier; + this.moveFunc = moveFunc; + } + + override canApply({ pokemon, move }: ChangeMovePriorityAbAttrParams): boolean { + return this.moveFunc(pokemon, move); + } + + override apply({ priority }: ChangeMovePriorityAbAttrParams): void { + priority.value = this.newModifier; + } +} + export class IgnoreContactAbAttr extends AbAttr { private declare readonly _: never; } @@ -6721,6 +6741,7 @@ const AbilityAttrs = Object.freeze({ BlockStatusDamageAbAttr, BlockOneHitKOAbAttr, ChangeMovePriorityAbAttr, + ChangeMovePriorityModifierAbAttr, IgnoreContactAbAttr, PreWeatherEffectAbAttr, PreWeatherDamageAbAttr, @@ -7238,7 +7259,7 @@ export function initAbilities() { .attr(DoubleBattleChanceAbAttr) .build(), new AbBuilder(AbilityId.STALL, 4) - .attr(ChangeMovePriorityAbAttr, (_pokemon, _move: Move) => true, -0.2) + .attr(ChangeMovePriorityModifierAbAttr, (_pokemon, _move: Move) => true, MovePriorityModifier.LAST_IN_BRACKET) .build(), new AbBuilder(AbilityId.TECHNICIAN, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => { @@ -8185,7 +8206,7 @@ export function initAbilities() { .ignorable() .build(), new AbBuilder(AbilityId.MYCELIUM_MIGHT, 9) - .attr(ChangeMovePriorityAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, -0.2) + .attr(ChangeMovePriorityModifierAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, MovePriorityModifier.LAST_IN_BRACKET) .attr(PreventBypassSpeedChanceAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS) .attr(MoveAbilityBypassAbAttr, (_pokemon, move: Move) => move.category === MoveCategory.STATUS) .build(), diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index b32ed6bbee4..44240d7e358 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -101,6 +101,7 @@ import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; import { inSpeedOrder } from "#utils/speed-order-generator"; import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils"; import type { ReadonlyGenericUint8Array } from "#types/typed-arrays"; +import { MovePriorityModifier } from "#enums/move-priority-modifier"; /** * A function used to conditionally determine execution of a given {@linkcode MoveAttr}. @@ -1060,17 +1061,19 @@ export abstract class Move implements Localizable { getPriority(user: Pokemon, simulated: boolean = true) { const priority = new NumberHolder(this.priority); - applyMoveAttrs("IncrementMovePriorityAttr", user, null, this, priority); applyAbAttrs("ChangeMovePriorityAbAttr", {pokemon: user, simulated, move: this, priority}); - if (user.getTag(BattlerTagType.BYPASS_SPEED)) { - priority.value += 0.2; - } - return priority.value; } + public getPriorityModifier(user: Pokemon, simulated = true) { + const modifierHolder = new NumberHolder(MovePriorityModifier.NORMAL); + applyAbAttrs("ChangeMovePriorityModifierAbAttr", {pokemon: user, simulated: simulated, move: this, priority: modifierHolder}); + modifierHolder.value = user.getTag(BattlerTagType.BYPASS_SPEED) ? MovePriorityModifier.FIRST_IN_BRACKET : modifierHolder.value; + return modifierHolder.value; + } + /** * Calculate the [Expected Power](https://en.wikipedia.org/wiki/Expected_value) per turn * of this move, taking into account multi hit moves, accuracy, and the number of turns it diff --git a/src/data/terrain.ts b/src/data/terrain.ts index bd90f3985b4..54b5aeffb6a 100644 --- a/src/data/terrain.ts +++ b/src/data/terrain.ts @@ -67,7 +67,7 @@ export class Terrain { return ( !isFieldTargeted(move) && !isSpreadMove(move) - && move.getPriority(user) > 0.2 // fractional priority is used by quick claw etc and is not blocked by terrain + && move.getPriority(user) > 0 && user.getOpponents(true).some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()) ); } diff --git a/src/enums/move-priority-modifier.ts b/src/enums/move-priority-modifier.ts new file mode 100644 index 00000000000..3e51aaec0a3 --- /dev/null +++ b/src/enums/move-priority-modifier.ts @@ -0,0 +1,13 @@ +import type { ObjectValues } from "#types/type-helpers"; + +/** + * Enum representing modifiers for Move priorities. + */ +export const MovePriorityModifier = Object.freeze({ + /** Used when moves go last in their priority bracket, but before moves of lower priority. */ + LAST_IN_BRACKET: 0, + NORMAL: 1, + /** Used when moves go first in their priority bracket, but before moves of lower priority. */ + FIRST_IN_BRACKET: 2, +}); +export type MovePriorityModifier = ObjectValues; diff --git a/src/queues/move-phase-priority-queue.ts b/src/queues/move-phase-priority-queue.ts index 5f0b20c3c2e..a30162158f3 100644 --- a/src/queues/move-phase-priority-queue.ts +++ b/src/queues/move-phase-priority-queue.ts @@ -92,11 +92,18 @@ export class MovePhasePriorityQueue extends PokemonPhasePriorityQueue }); const timingModifiers = [a, b].map(movePhase => movePhase.timingModifier); + const priorityModifiers = [a, b].map(movePhase => + movePhase.move.getMove().getPriorityModifier(movePhase.pokemon), + ); if (timingModifiers[0] !== timingModifiers[1]) { return timingModifiers[1] - timingModifiers[0]; } + if (priority[0] === priority[1] && priorityModifiers[0] !== priorityModifiers[1]) { + return priorityModifiers[1] - priorityModifiers[0]; + } + return priority[1] - priority[0]; }); } diff --git a/test/arena/psychic-terrain.test.ts b/test/arena/psychic-terrain.test.ts index 6112db41cd8..9e1e5fc9d8e 100644 --- a/test/arena/psychic-terrain.test.ts +++ b/test/arena/psychic-terrain.test.ts @@ -72,7 +72,7 @@ describe("Arena - Psychic Terrain", () => { await game.phaseInterceptor.to("MovePhase", false); const feebas = game.field.getPlayerPokemon(); - expect(allMoves[MoveId.POUND].getPriority(feebas)).toBe(0.2); + expect(allMoves[MoveId.POUND].getPriority(feebas)).toBe(0); await game.toEndOfTurn(); @@ -93,7 +93,7 @@ describe("Arena - Psychic Terrain", () => { await game.phaseInterceptor.to("MovePhase", false); const feebas = game.field.getPlayerPokemon(); - expect(allMoves[MoveId.QUICK_ATTACK].getPriority(feebas)).toBe(1.2); + expect(allMoves[MoveId.QUICK_ATTACK].getPriority(feebas)).toBe(1); await game.toEndOfTurn(); From 9ea5a014a1d0f700fffcd7cc007a436b39d50762 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:14:31 -0700 Subject: [PATCH 30/58] [Bug] Allow fainted Pokemon to be released post-battle in hardcore https://github.com/pagefaultgames/pokerogue/pull/6723 --- src/ui/handlers/party-ui-handler.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/ui/handlers/party-ui-handler.ts b/src/ui/handlers/party-ui-handler.ts index 7806a6111c1..6fbb4052aeb 100644 --- a/src/ui/handlers/party-ui-handler.ts +++ b/src/ui/handlers/party-ui-handler.ts @@ -1586,9 +1586,8 @@ export class PartyUiHandler extends MessageUiHandler { this.updateOptionsWithModifierTransferMode(pokemon); break; case PartyUiMode.SWITCH: - this.options.push(PartyOption.RELEASE); - break; case PartyUiMode.RELEASE: + case PartyUiMode.CHECK: this.options.push(PartyOption.RELEASE); break; } From 1d4a9259b83441c358a6ca591afb282a2e7c88ca Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:14:48 -0700 Subject: [PATCH 31/58] [Hotfix] Fix Queenly Majesty/Dazzling affecting user's moves instead of enemy's (#6722) Fix QM/Dazzling --- src/phases/move-phase.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index 6350791e9bb..5115e3da595 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -286,7 +286,7 @@ export class MovePhase extends PokemonPhase { // Apply queenly majesty / dazzling if (!failed) { - const defendingSidePlayField = user.isPlayer() ? globalScene.getPlayerField() : globalScene.getEnemyField(); + const defendingSidePlayField = user.isPlayer() ? globalScene.getEnemyField() : globalScene.getPlayerField(); const cancelled = new BooleanHolder(false); defendingSidePlayField.forEach((pokemon: Pokemon) => { applyAbAttrs("FieldPriorityMoveImmunityAbAttr", { From d7cfb2087cbcea8aeaaa003e8b074bf7dbfb1215 Mon Sep 17 00:00:00 2001 From: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Date: Fri, 31 Oct 2025 04:21:26 +0100 Subject: [PATCH 32/58] [Bug][UI/UX] Make ribbon option in dex selectable with classic wins https://github.com/pagefaultgames/pokerogue/pull/6720 --- src/ui/handlers/pokedex-page-ui-handler.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/ui/handlers/pokedex-page-ui-handler.ts b/src/ui/handlers/pokedex-page-ui-handler.ts index fa10c88952c..c3be9f87d21 100644 --- a/src/ui/handlers/pokedex-page-ui-handler.ts +++ b/src/ui/handlers/pokedex-page-ui-handler.ts @@ -776,7 +776,8 @@ export class PokedexPageUiHandler extends MessageUiHandler { || (this.tmMoves.length === 0 && o === MenuOptions.TM_MOVES) || (!globalScene.gameData.dexData[this.species.speciesId].ribbons.getRibbons() && o === MenuOptions.RIBBONS - && !globalScene.showMissingRibbons); + && !globalScene.showMissingRibbons + && !globalScene.gameData.starterData[this.species.speciesId]?.classicWinCount); const color = getTextColor(isDark ? TextStyle.SHADOW_TEXT : TextStyle.SETTINGS_VALUE, false); const shadow = getTextColor(isDark ? TextStyle.SHADOW_TEXT : TextStyle.SETTINGS_VALUE, true); return `[shadow=${shadow}][color=${color}]${label}[/color][/shadow]`; @@ -1778,6 +1779,7 @@ export class PokedexPageUiHandler extends MessageUiHandler { } else if ( !globalScene.gameData.dexData[this.species.speciesId].ribbons.getRibbons() && !globalScene.showMissingRibbons + && !globalScene.gameData.starterData[this.species.speciesId]?.classicWinCount ) { ui.showText(i18next.t("pokedexUiHandler:noRibbons")); error = true; From 893333ff3bb0699ac3843dc41169c31e3dc08681 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 30 Oct 2025 20:24:39 -0700 Subject: [PATCH 33/58] Update version to 1.11.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index b23b9b9b75d..102c76830b1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.11.0", + "version": "1.11.1", "type": "module", "scripts": { "start:prod": "vite --mode production", From 30e6e1f00ce6a0e80ac9042109bd7029785f4241 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Fri, 31 Oct 2025 00:37:29 -0400 Subject: [PATCH 34/58] [Dev] Add `.zed` to `gitignore` --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index c74ad9ed5c3..e45ff602303 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ build # Editor directories and files (excluding `extensions.json` for devcontainer) *.code-workspace .vscode/* +.zed !.vscode/extensions.json !.vscode/spdx.code-snippets .idea @@ -50,6 +51,5 @@ coverage /dependency-graph.svg /.vs - # Script outputs -./*.csv \ No newline at end of file +./*.csv From df98e506ad4fdc5fac1f70dec875072081e11f21 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Thu, 30 Oct 2025 21:38:49 -0700 Subject: [PATCH 35/58] [Bug] Prevent self speed ties (#6719) * Prevent self speed ties * Remove outdated parameter doc --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- .../post-summon-phase-priority-queue.ts | 2 +- src/utils/speed-order.ts | 44 +++++++++----- test/utils/speed-order.test.ts | 58 +++++++++++++++++++ 3 files changed, 89 insertions(+), 15 deletions(-) create mode 100644 test/utils/speed-order.test.ts diff --git a/src/queues/post-summon-phase-priority-queue.ts b/src/queues/post-summon-phase-priority-queue.ts index 28e727de01b..fe08713e501 100644 --- a/src/queues/post-summon-phase-priority-queue.ts +++ b/src/queues/post-summon-phase-priority-queue.ts @@ -11,7 +11,7 @@ import { sortInSpeedOrder } from "#app/utils/speed-order"; */ export class PostSummonPhasePriorityQueue extends PokemonPhasePriorityQueue { protected override reorder(): void { - this.queue = sortInSpeedOrder(this.queue, false); + this.queue = sortInSpeedOrder(this.queue); this.queue.sort((phaseA, phaseB) => phaseB.getPriority() - phaseA.getPriority()); } diff --git a/src/utils/speed-order.ts b/src/utils/speed-order.ts index f2733a74998..aaf3a4526c7 100644 --- a/src/utils/speed-order.ts +++ b/src/utils/speed-order.ts @@ -12,15 +12,13 @@ interface hasPokemon { /** * Sorts an array of {@linkcode Pokemon} by speed, taking Trick Room into account. * @param pokemonList - The list of Pokemon or objects containing Pokemon - * @param shuffleFirst - Whether to shuffle the list before sorting (to handle speed ties). Default `true`. * @returns The sorted array of {@linkcode Pokemon} */ -export function sortInSpeedOrder(pokemonList: T[], shuffleFirst = true): T[] { - if (shuffleFirst) { - shufflePokemonList(pokemonList); - } - sortBySpeed(pokemonList); - return pokemonList; +export function sortInSpeedOrder(pokemonList: T[]): T[] { + const grouped = groupPokemon(pokemonList); + shufflePokemonList(grouped); + sortBySpeed(grouped); + return grouped.flat(); } /** @@ -28,7 +26,7 @@ export function sortInSpeedOrder(pokemonList: T[ * @param pokemonList - The array of Pokemon or objects containing Pokemon * @returns The same array instance that was passed in, shuffled. */ -function shufflePokemonList(pokemonList: T[]): T[] { +function shufflePokemonList(pokemonList: T[][]): void { // This is seeded with the current turn to prevent an inconsistency where it // was varying based on how long since you last reloaded globalScene.executeWithSeedOffset( @@ -36,7 +34,6 @@ function shufflePokemonList(pokemonList: T[]): T globalScene.currentBattle.turn * 1000 + pokemonList.length, globalScene.waveSeed, ); - return pokemonList; } /** Type guard for {@linkcode sortBySpeed} to avoid importing {@linkcode Pokemon} */ @@ -44,11 +41,15 @@ function isPokemon(p: Pokemon | hasPokemon): p is Pokemon { return typeof (p as hasPokemon).getPokemon !== "function"; } +function getPokemon(p: Pokemon | hasPokemon): Pokemon { + return isPokemon(p) ? p : p.getPokemon(); +} + /** Sorts an array of {@linkcode Pokemon} by speed (without shuffling) */ -function sortBySpeed(pokemonList: T[]): void { - pokemonList.sort((a, b) => { - const aSpeed = (isPokemon(a) ? a : a.getPokemon()).getEffectiveStat(Stat.SPD); - const bSpeed = (isPokemon(b) ? b : b.getPokemon()).getEffectiveStat(Stat.SPD); +function sortBySpeed(groupedPokemonList: T[][]): void { + groupedPokemonList.sort((a, b) => { + const aSpeed = getPokemon(a[0]).getEffectiveStat(Stat.SPD); + const bSpeed = getPokemon(b[0]).getEffectiveStat(Stat.SPD); return bSpeed - aSpeed; }); @@ -57,6 +58,21 @@ function sortBySpeed(pokemonList: T[]): void { const speedReversed = new BooleanHolder(false); globalScene.arena.applyTags(ArenaTagType.TRICK_ROOM, speedReversed); if (speedReversed.value) { - pokemonList.reverse(); + groupedPokemonList.reverse(); } } + +function groupPokemon(pokemonList: T[]): T[][] { + const runs: T[][] = []; + for (const pkmn of pokemonList) { + const pokemon = getPokemon(pkmn); + const lastGroup = runs.at(-1); + if (lastGroup != null && lastGroup.length > 0 && getPokemon(lastGroup[0]) === pokemon) { + lastGroup.push(pkmn); + } else { + runs.push([pkmn]); + } + } + + return runs; +} diff --git a/test/utils/speed-order.test.ts b/test/utils/speed-order.test.ts new file mode 100644 index 00000000000..e408c5823c4 --- /dev/null +++ b/test/utils/speed-order.test.ts @@ -0,0 +1,58 @@ +import { AbilityId } from "#enums/ability-id"; +import { MoveId } from "#enums/move-id"; +import { SpeciesId } from "#enums/species-id"; +import { Stat } from "#enums/stat"; +import { GameManager } from "#test/test-utils/game-manager"; +import { sortInSpeedOrder } from "#utils/speed-order"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Utils - Speed Order", () => { + 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") + .startingLevel(100) + .enemyLevel(100) + .enemyMoveset(MoveId.SPLASH) + .enemyAbility(AbilityId.BALL_FETCH) + .ability(AbilityId.BALL_FETCH) + .enemySpecies(SpeciesId.REGIELEKI); + }); + + it("Sorts correctly in the basic case", async () => { + await game.classicMode.startBattle([SpeciesId.SLOWPOKE, SpeciesId.MEW]); + const [slowpoke, mew] = game.field.getPlayerParty(); + const regieleki = game.field.getEnemyPokemon(); + const pkmnList = [slowpoke, regieleki, mew]; + + expect(sortInSpeedOrder(pkmnList)).toEqual([regieleki, mew, slowpoke]); + }); + + it("Correctly sorts grouped pokemon", async () => { + await game.classicMode.startBattle([SpeciesId.SLOWPOKE, SpeciesId.MEW, SpeciesId.DITTO]); + const [slowpoke, mew, ditto] = game.field.getPlayerParty(); + const regieleki = game.field.getEnemyPokemon(); + ditto.stats[Stat.SPD] = slowpoke.getStat(Stat.SPD); + + const pkmnList = [slowpoke, slowpoke, ditto, ditto, mew, regieleki, regieleki]; + const sorted = sortInSpeedOrder(pkmnList); + + expect([ + [regieleki, regieleki, mew, slowpoke, slowpoke, ditto, ditto], + [regieleki, regieleki, mew, ditto, ditto, slowpoke, slowpoke], + ]).toContainEqual(sorted); + }); +}); From 76453a31d1ee6bd42f4ea37b93a88e7a008e5240 Mon Sep 17 00:00:00 2001 From: damocleas Date: Fri, 31 Oct 2025 00:47:07 -0400 Subject: [PATCH 36/58] [Balance][Bug] Rival Fight 3 Fix, Move Noibat in Biomes Electivire corrected to be Electabuzz in Slot 3 on Fight 3 (55) Noibat has been moved from Uncommon -> Rare in Grassy Field --- src/data/balance/biomes.ts | 8 ++++---- src/data/balance/init-biomes.ts | 2 +- src/data/trainers/rival-party-config.ts | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/data/balance/biomes.ts b/src/data/balance/biomes.ts index 562c07396e0..f81f76058ec 100644 --- a/src/data/balance/biomes.ts +++ b/src/data/balance/biomes.ts @@ -163,15 +163,15 @@ export const biomePokemonPools: BiomePokemonPools = { [BiomePoolTier.UNCOMMON]: { [TimeOfDay.DAWN]: [ SpeciesId.SUNKERN, SpeciesId.COMBEE ], [TimeOfDay.DAY]: [ SpeciesId.SUNKERN, SpeciesId.COMBEE ], - [TimeOfDay.DUSK]: [ SpeciesId.SEEDOT, SpeciesId.NOIBAT ], - [TimeOfDay.NIGHT]: [ SpeciesId.SEEDOT, SpeciesId.NOIBAT ], + [TimeOfDay.DUSK]: [ SpeciesId.SEEDOT ], + [TimeOfDay.NIGHT]: [ SpeciesId.SEEDOT ], [TimeOfDay.ALL]: [ SpeciesId.MILTANK, SpeciesId.CHERUBI, SpeciesId.FOONGUS, ] }, [BiomePoolTier.RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], - [TimeOfDay.DUSK]: [], - [TimeOfDay.NIGHT]: [], + [TimeOfDay.DUSK]: [ SpeciesId.NOIBAT ], + [TimeOfDay.NIGHT]: [ SpeciesId.NOIBAT ], [TimeOfDay.ALL]: [ SpeciesId.BULBASAUR, SpeciesId.GROWLITHE, SpeciesId.TURTWIG, SpeciesId.BONSLY ] }, [BiomePoolTier.SUPER_RARE]: { [TimeOfDay.DAWN]: [], [TimeOfDay.DAY]: [], [TimeOfDay.DUSK]: [], [TimeOfDay.NIGHT]: [], [TimeOfDay.ALL]: [] }, diff --git a/src/data/balance/init-biomes.ts b/src/data/balance/init-biomes.ts index 1b410e637e8..eb2d4151fbf 100644 --- a/src/data/balance/init-biomes.ts +++ b/src/data/balance/init-biomes.ts @@ -3547,7 +3547,7 @@ export function initBiomes() { ], [SpeciesId.NOIBAT, PokemonType.FLYING, PokemonType.DRAGON, [ [BiomeId.CAVE, BiomePoolTier.UNCOMMON], - [BiomeId.GRASS, BiomePoolTier.UNCOMMON, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] + [BiomeId.GRASS, BiomePoolTier.RARE, [TimeOfDay.DUSK, TimeOfDay.NIGHT]] ] ], [SpeciesId.NOIVERN, PokemonType.FLYING, PokemonType.DRAGON, [ diff --git a/src/data/trainers/rival-party-config.ts b/src/data/trainers/rival-party-config.ts index fa040ff66de..67b3f50d379 100644 --- a/src/data/trainers/rival-party-config.ts +++ b/src/data/trainers/rival-party-config.ts @@ -298,7 +298,7 @@ const SLOT_3_FIGHT_3 = [ SpeciesId.RHYDON, SpeciesId.TANGROWTH, SpeciesId.PORYGON2, - SpeciesId.ELECTIVIRE, + SpeciesId.ELECTABUZZ, SpeciesId.MAGMAR, SpeciesId.AZUMARILL, SpeciesId.URSARING, From babeb32edb9a1e6906d04a2d1e2bd19151d737a8 Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 30 Oct 2025 21:49:37 -0700 Subject: [PATCH 37/58] [Bug] Shinies won't be forced to match event boss shiny if set (#6724) --- src/field/pokemon.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index be85e2ebe3a..6ce5c1ffc2c 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -6388,12 +6388,14 @@ export class EnemyPokemon extends Pokemon { } const eventBossVariant = getDailyEventSeedBossVariant(globalScene.seed); - if (eventBossVariant != null && globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex)) { + const eventBossVariantEnabled = + eventBossVariant != null && globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex); + if (eventBossVariantEnabled) { this.shiny = true; } if (this.shiny) { - this.variant = eventBossVariant ?? this.generateShinyVariant(); + this.variant = eventBossVariantEnabled ? eventBossVariant : this.generateShinyVariant(); if (Overrides.ENEMY_VARIANT_OVERRIDE !== null) { this.variant = Overrides.ENEMY_VARIANT_OVERRIDE; } From 2d955165f9ef63b8db02db0173280170ae925cee Mon Sep 17 00:00:00 2001 From: NightKev <34855794+DayKev@users.noreply.github.com> Date: Thu, 30 Oct 2025 22:03:31 -0700 Subject: [PATCH 38/58] Update version to 1.11.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 102c76830b1..e08e5a393a4 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "pokemon-rogue-battle", "private": true, - "version": "1.11.1", + "version": "1.11.2", "type": "module", "scripts": { "start:prod": "vite --mode production", From 2a1e0c4373b8e14f98badb297a67ccd4cebab133 Mon Sep 17 00:00:00 2001 From: fabske0 <192151969+fabske0@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:12:51 +0100 Subject: [PATCH 39/58] - Add option for shiny starter - change how the starter part of the seed is parsed --- src/data/daily-run.ts | 70 ++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 4 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index ea2852976e8..c3aec54c4e4 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -58,11 +58,19 @@ export function getDailyRunStarters(seed: string): StarterTuple { } // TODO: Refactor this unmaintainable mess -function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: number): Starter { +function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: number, variant?: Variant): Starter { const starterSpecies = starterSpeciesForm instanceof PokemonSpecies ? starterSpeciesForm : getPokemonSpecies(starterSpeciesForm.speciesId); const formIndex = starterSpeciesForm instanceof PokemonSpecies ? undefined : starterSpeciesForm.formIndex; - const pokemon = globalScene.addPlayerPokemon(starterSpecies, startingLevel, undefined, formIndex); + const pokemon = globalScene.addPlayerPokemon( + starterSpecies, + startingLevel, + undefined, + formIndex, + undefined, + variant !== undefined ? true : undefined, + variant, + ); const starter: Starter = { speciesId: starterSpecies.speciesId, shiny: pokemon.shiny, @@ -215,14 +223,68 @@ function setDailyRunEventStarterMovesets(seed: string, starters: StarterTuple): } } +/** + * Expects the seed to contain `starters` followed by 3 `s{\d{4}}` for the starters. The 4 digits are the species ID. \ + * Each starter can optionally be followed by `f{\d{2}}` for the form index and `v{\d{2}}` for the variant. \ + * The order of `f` and `v` does not matter. + * @example `/starterss0003f01s0025v01s0150f02v02` + * @param seed - The daily run seed + * @returns An array of {@linkcode Starter}s, or `null` if no valid match. + */ +// TODO: Rework this setup into JSON or similar - this is quite hard to maintain +function getDailyEventSeedStarters(seed: string): StarterTuple | null { + const speciesCongigurations = + /starters(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?/.exec( + seed, + )?.groups; + + if (!speciesCongigurations) { + const legacyStarters = getDailyEventSeedStartersLegay(seed); + if (legacyStarters != null) { + console.log("Using lecacy starter parsing for daily run seed."); + return legacyStarters; + } + console.error("Invalid starters used for custom daily run seed!"); + return null; + } + console.log(speciesCongigurations); + + const speciesIds = getEnumValues(SpeciesId); + + const starters: Starter[] = []; + for (let i = 0; i < 3; i++) { + const speciesId = Number.parseInt(speciesCongigurations[`species${i + 1}`].slice(1)) as SpeciesId; + const formIndex = Number.parseInt(speciesCongigurations[`form${i + 1}`]?.slice(1) ?? "00"); + let variant: Variant | undefined = Number.parseInt(speciesCongigurations[`variant${i + 1}`]?.slice(1)) as Variant; + + if (!speciesIds.includes(speciesId)) { + console.error("Invalid species ID used for custom daily run seed starter:", speciesId); + return null; + } + + const starterSpecies = getPokemonSpecies(speciesId); + if (Number.isNaN(variant) || variant > 2 || (!starterSpecies.hasVariants() && variant !== 0)) { + console.error("Invalid variant used for custom daily run seed starter:", variant); + variant = undefined; + } + + const starterForm = getPokemonSpeciesForm(speciesId, formIndex); + const startingLevel = globalScene.gameMode.getStartingLevel(); + const starter = getDailyRunStarter(starterForm, startingLevel, variant); + starters.push(starter); + } + + return starters as StarterTuple; +} + /** * Expects the seed to contain `/starters\d{18}/` * where the digits alternate between 4 digits for the species ID and 2 digits for the form index * (left padded with `0`s as necessary). * @returns An array of {@linkcode Starter}s, or `null` if no valid match. */ -// TODO: Rework this setup into JSON or similar - this is quite hard to maintain -export function getDailyEventSeedStarters(seed: string): StarterTuple | null { +// TODO: Can be removed after october 31st 2025 +function getDailyEventSeedStartersLegay(seed: string): StarterTuple | null { if (!isDailyEventSeed(seed)) { return null; } From 8e01876bd0ddf19e3ec3103553b991953a3ee6d7 Mon Sep 17 00:00:00 2001 From: fabske0 <192151969+fabske0@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:16:33 +0100 Subject: [PATCH 40/58] fix typo --- src/data/daily-run.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index c3aec54c4e4..c79bc9a3efd 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -233,12 +233,12 @@ function setDailyRunEventStarterMovesets(seed: string, starters: StarterTuple): */ // TODO: Rework this setup into JSON or similar - this is quite hard to maintain function getDailyEventSeedStarters(seed: string): StarterTuple | null { - const speciesCongigurations = + const speciesConfigurations = /starters(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?/.exec( seed, )?.groups; - if (!speciesCongigurations) { + if (!speciesConfigurations) { const legacyStarters = getDailyEventSeedStartersLegay(seed); if (legacyStarters != null) { console.log("Using lecacy starter parsing for daily run seed."); @@ -247,15 +247,15 @@ function getDailyEventSeedStarters(seed: string): StarterTuple | null { console.error("Invalid starters used for custom daily run seed!"); return null; } - console.log(speciesCongigurations); + console.log(speciesConfigurations); const speciesIds = getEnumValues(SpeciesId); const starters: Starter[] = []; for (let i = 0; i < 3; i++) { - const speciesId = Number.parseInt(speciesCongigurations[`species${i + 1}`].slice(1)) as SpeciesId; - const formIndex = Number.parseInt(speciesCongigurations[`form${i + 1}`]?.slice(1) ?? "00"); - let variant: Variant | undefined = Number.parseInt(speciesCongigurations[`variant${i + 1}`]?.slice(1)) as Variant; + const speciesId = Number.parseInt(speciesConfigurations[`species${i + 1}`].slice(1)) as SpeciesId; + const formIndex = Number.parseInt(speciesConfigurations[`form${i + 1}`]?.slice(1) ?? "00"); + let variant: Variant | undefined = Number.parseInt(speciesConfigurations[`variant${i + 1}`]?.slice(1)) as Variant; if (!speciesIds.includes(speciesId)) { console.error("Invalid species ID used for custom daily run seed starter:", speciesId); From 6049038537de3350448090e84e4934ad15291baa Mon Sep 17 00:00:00 2001 From: fabske0 <192151969+fabske0@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:17:14 +0100 Subject: [PATCH 41/58] remove console.log and another typo --- src/data/daily-run.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index c79bc9a3efd..8cd9ff8a115 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -241,13 +241,12 @@ function getDailyEventSeedStarters(seed: string): StarterTuple | null { if (!speciesConfigurations) { const legacyStarters = getDailyEventSeedStartersLegay(seed); if (legacyStarters != null) { - console.log("Using lecacy starter parsing for daily run seed."); + console.log("Using legacy starter parsing for daily run seed."); return legacyStarters; } console.error("Invalid starters used for custom daily run seed!"); return null; } - console.log(speciesConfigurations); const speciesIds = getEnumValues(SpeciesId); From b150b5208c1544beb343a51f7c59b8736a1050c2 Mon Sep 17 00:00:00 2001 From: fabske0 <192151969+fabske0@users.noreply.github.com> Date: Fri, 31 Oct 2025 14:48:01 +0100 Subject: [PATCH 42/58] split up regex --- src/data/daily-run.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index 8cd9ff8a115..a5635bf464e 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -233,10 +233,12 @@ function setDailyRunEventStarterMovesets(seed: string, starters: StarterTuple): */ // TODO: Rework this setup into JSON or similar - this is quite hard to maintain function getDailyEventSeedStarters(seed: string): StarterTuple | null { - const speciesConfigurations = - /starters(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?(?s\d{4})(?:(?f\d{2})(?v\d{2})?|(?v\d{2})(?f\d{2})?)?/.exec( - seed, - )?.groups; + const speciesRegex = i => + `(?s\\d{4})(?:(?f\\d{2})(?v\\d{2})?|(?v\\d{2})(?f\\d{2})?)?`; + + const matcher = new RegExp(`starters${speciesRegex(1)}${speciesRegex(2)}${speciesRegex(3)}`); + + const speciesConfigurations = matcher.exec(seed)?.groups; if (!speciesConfigurations) { const legacyStarters = getDailyEventSeedStartersLegay(seed); From ac79e82013160f00c9045f06ae5357a96c35ebf3 Mon Sep 17 00:00:00 2001 From: fabske0 <192151969+fabske0@users.noreply.github.com> Date: Fri, 31 Oct 2025 15:11:10 +0100 Subject: [PATCH 43/58] another typo --- src/data/daily-run.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index a5635bf464e..c52bb164f4b 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -241,7 +241,7 @@ function getDailyEventSeedStarters(seed: string): StarterTuple | null { const speciesConfigurations = matcher.exec(seed)?.groups; if (!speciesConfigurations) { - const legacyStarters = getDailyEventSeedStartersLegay(seed); + const legacyStarters = getDailyEventSeedStartersLegacy(seed); if (legacyStarters != null) { console.log("Using legacy starter parsing for daily run seed."); return legacyStarters; @@ -285,7 +285,7 @@ function getDailyEventSeedStarters(seed: string): StarterTuple | null { * @returns An array of {@linkcode Starter}s, or `null` if no valid match. */ // TODO: Can be removed after october 31st 2025 -function getDailyEventSeedStartersLegay(seed: string): StarterTuple | null { +function getDailyEventSeedStartersLegacy(seed: string): StarterTuple | null { if (!isDailyEventSeed(seed)) { return null; } From 6bda024b7eb07bd2207502ed1895e19ffa81e989 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 13:10:11 -0700 Subject: [PATCH 44/58] Only run speed bypass code for fight commands --- src/phases/turn-start-phase.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/phases/turn-start-phase.ts b/src/phases/turn-start-phase.ts index 1f1b78af0ad..c9774c5873a 100644 --- a/src/phases/turn-start-phase.ts +++ b/src/phases/turn-start-phase.ts @@ -69,6 +69,10 @@ export class TurnStartPhase extends FieldPhase { const phaseManager = globalScene.phaseManager; for (const pokemon of inSpeedOrder(ArenaTagSide.BOTH)) { + if (globalScene.currentBattle.turnCommands[pokemon.getBattlerIndex()]?.command !== Command.FIGHT) { + continue; + } + applyAbAttrs("BypassSpeedChanceAbAttr", { pokemon }); globalScene.applyModifiers(BypassSpeedChanceModifier, pokemon.isPlayer(), pokemon); } From e78796077b19e1c11538eb337a8f164ba9401096 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 13:22:40 -0700 Subject: [PATCH 45/58] Disable Illusion --- src/data/abilities/ability.ts | 23 +++++------ test/abilities/illusion.test.ts | 69 +++++++++++++++++---------------- 2 files changed, 48 insertions(+), 44 deletions(-) diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 301016d899b..fd1eb8ea5ef 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -7440,17 +7440,18 @@ export function initAbilities() { 1.3) .build(), new AbBuilder(AbilityId.ILLUSION, 5) - // The Pokemon generate an illusion if it's available - .attr(IllusionPreSummonAbAttr, false) - .attr(IllusionBreakAbAttr) - // The Pokemon loses its illusion when damaged by a move - .attr(PostDefendIllusionBreakAbAttr, true) - // Disable Illusion in fusions - .attr(NoFusionAbilityAbAttr) - // Illusion is available again after a battle - .conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false) - .uncopiable() - .bypassFaint() + // // The Pokemon generate an illusion if it's available + // .attr(IllusionPreSummonAbAttr, false) + // .attr(IllusionBreakAbAttr) + // // The Pokemon loses its illusion when damaged by a move + // .attr(PostDefendIllusionBreakAbAttr, true) + // // Disable Illusion in fusions + // .attr(NoFusionAbilityAbAttr) + // // Illusion is available again after a battle + // .conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false) + // .uncopiable() + // .bypassFaint() + .unimplemented() // TODO reimplement Illusion properly .build(), new AbBuilder(AbilityId.IMPOSTER, 5) .attr(PostSummonTransformAbAttr) diff --git a/test/abilities/illusion.test.ts b/test/abilities/illusion.test.ts index 2343a11cb74..1264b458234 100644 --- a/test/abilities/illusion.test.ts +++ b/test/abilities/illusion.test.ts @@ -33,7 +33,7 @@ describe("Abilities - Illusion", () => { .startingHeldItems([{ name: "WIDE_LENS", count: 3 }]); }); - it("creates illusion at the start", async () => { + it.todo("creates illusion at the start", async () => { await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]); const zoroark = game.field.getPlayerPokemon(); const zorua = game.field.getEnemyPokemon(); @@ -42,7 +42,7 @@ describe("Abilities - Illusion", () => { expect(!!zorua.summonData.illusion).equals(true); }); - it("break after receiving damaging move", async () => { + it.todo("break after receiving damaging move", async () => { await game.classicMode.startBattle([SpeciesId.FEEBAS]); game.move.select(MoveId.TACKLE); @@ -54,7 +54,7 @@ describe("Abilities - Illusion", () => { expect(zorua.name).equals("Zorua"); }); - it("break after getting ability changed", async () => { + it.todo("break after getting ability changed", async () => { await game.classicMode.startBattle([SpeciesId.FEEBAS]); game.move.select(MoveId.WORRY_SEED); @@ -65,7 +65,7 @@ describe("Abilities - Illusion", () => { expect(!!zorua.summonData.illusion).equals(false); }); - it("breaks with neutralizing gas", async () => { + it.todo("breaks with neutralizing gas", async () => { game.override.enemyAbility(AbilityId.NEUTRALIZING_GAS); await game.classicMode.startBattle([SpeciesId.KOFFING]); @@ -74,7 +74,7 @@ describe("Abilities - Illusion", () => { expect(!!zorua.summonData.illusion).equals(false); }); - it("does not activate if neutralizing gas is active", async () => { + it.todo("does not activate if neutralizing gas is active", async () => { game.override .enemyAbility(AbilityId.NEUTRALIZING_GAS) .ability(AbilityId.ILLUSION) @@ -88,35 +88,38 @@ describe("Abilities - Illusion", () => { expect(game.field.getPlayerPokemon().summonData.illusion).toBeFalsy(); }); - it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => { - game.override.enemyMoveset([MoveId.FLAMETHROWER, MoveId.PSYCHIC, MoveId.TACKLE]); - await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]); + it.todo( + "causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", + async () => { + game.override.enemyMoveset([MoveId.FLAMETHROWER, MoveId.PSYCHIC, MoveId.TACKLE]); + await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]); - const enemy = game.field.getEnemyPokemon(); - const zoroark = game.field.getPlayerPokemon(); + const enemy = game.field.getEnemyPokemon(); + const zoroark = game.field.getPlayerPokemon(); - const flameThrower = enemy.getMoveset()[0]!.getMove(); - const psychic = enemy.getMoveset()[1]!.getMove(); - const flameThrowerEffectiveness = zoroark.getAttackTypeEffectiveness( - flameThrower.type, - enemy, - undefined, - undefined, - flameThrower, - true, - ); - const psychicEffectiveness = zoroark.getAttackTypeEffectiveness( - psychic.type, - enemy, - undefined, - undefined, - psychic, - true, - ); - expect(psychicEffectiveness).above(flameThrowerEffectiveness); - }); + const flameThrower = enemy.getMoveset()[0]!.getMove(); + const psychic = enemy.getMoveset()[1]!.getMove(); + const flameThrowerEffectiveness = zoroark.getAttackTypeEffectiveness( + flameThrower.type, + enemy, + undefined, + undefined, + flameThrower, + true, + ); + const psychicEffectiveness = zoroark.getAttackTypeEffectiveness( + psychic.type, + enemy, + undefined, + undefined, + psychic, + true, + ); + expect(psychicEffectiveness).above(flameThrowerEffectiveness); + }, + ); - it("should not break from indirect damage from status, weather or recoil", async () => { + it.todo("should not break from indirect damage from status, weather or recoil", async () => { game.override.enemySpecies(SpeciesId.GIGALITH).enemyAbility(AbilityId.SAND_STREAM); await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.AZUMARILL]); @@ -129,7 +132,7 @@ describe("Abilities - Illusion", () => { expect(!!zoroark.summonData.illusion).equals(true); }); - it("copies the the name, nickname, gender, shininess, and pokeball from the illusion source", async () => { + it.todo("copies the the name, nickname, gender, shininess, and pokeball from the illusion source", async () => { game.override.enemyMoveset(MoveId.SPLASH); await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.ZOROARK, SpeciesId.AXEW]); @@ -152,7 +155,7 @@ describe("Abilities - Illusion", () => { expect(zoroark.getPokeball(true)).equals(PokeballType.GREAT_BALL); }); - it("breaks when suppressed", async () => { + it.todo("breaks when suppressed", async () => { game.override.moveset(MoveId.GASTRO_ACID); await game.classicMode.startBattle([SpeciesId.MAGIKARP]); const zorua = game.field.getEnemyPokemon(); From bfbd71ddde8d51413981a626708370f35c9048d2 Mon Sep 17 00:00:00 2001 From: Lugiad Date: Fri, 31 Oct 2025 22:48:30 +0100 Subject: [PATCH 46/58] [UI/UX] [Localization] Texts position adjustments for Turkish (#6731) * Adjustments for Turkish * Remove now-unnecessary comment Co-authored-by: Fabi <192151969+fabske0@users.noreply.github.com> --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: Fabi <192151969+fabske0@users.noreply.github.com> --- src/ui/handlers/egg-gacha-ui-handler.ts | 11 +++++------ src/ui/handlers/game-stats-ui-handler.ts | 2 +- src/ui/handlers/starter-select-ui-handler.ts | 1 + 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/ui/handlers/egg-gacha-ui-handler.ts b/src/ui/handlers/egg-gacha-ui-handler.ts index c90d4a12139..fcb4cb09538 100644 --- a/src/ui/handlers/egg-gacha-ui-handler.ts +++ b/src/ui/handlers/egg-gacha-ui-handler.ts @@ -81,7 +81,7 @@ export class EggGachaUiHandler extends MessageUiHandler { let pokemonIconX = -20; let pokemonIconY = 6; - if (["de", "es-ES", "es-419", "fr", "ko", "pt-BR", "ja", "ru"].includes(currentLanguage)) { + if (["de", "es-ES", "es-419", "fr", "ko", "pt-BR", "ja", "ru", "tr"].includes(currentLanguage)) { gachaTextStyle = TextStyle.SMALLER_WINDOW_ALT; gachaX = 2; gachaY = 2; @@ -89,7 +89,7 @@ export class EggGachaUiHandler extends MessageUiHandler { let legendaryLabelX = gachaX; let legendaryLabelY = gachaY; - if (["de", "es-ES", "es-419"].includes(currentLanguage)) { + if (["de", "es-ES", "es-419", "tr"].includes(currentLanguage)) { pokemonIconX = -25; pokemonIconY = 10; legendaryLabelX = -6; @@ -108,8 +108,7 @@ export class EggGachaUiHandler extends MessageUiHandler { let xOffset = 0; const pokemonIcon = globalScene.add.sprite(pokemonIconX, pokemonIconY, "pokemon_icons_0"); - // Intentionally left as "array includes" instead of an equality check to allow for future languages to reuse - if (["pt-BR"].includes(currentLanguage)) { + if (["pt-BR", "tr"].includes(currentLanguage)) { xOffset = 2; pokemonIcon.setX(pokemonIconX - 2); } @@ -120,14 +119,14 @@ export class EggGachaUiHandler extends MessageUiHandler { } break; case GachaType.MOVE: - if (["de", "es-ES", "fr", "pt-BR", "ru"].includes(currentLanguage)) { + if (["de", "es-ES", "fr", "pt-BR", "ru", "tr"].includes(currentLanguage)) { gachaUpLabel.setAlign("center").setY(0); } gachaUpLabel.setText(i18next.t("egg:moveUpGacha")).setX(0).setOrigin(0.5, 0); break; case GachaType.SHINY: - if (["de", "fr", "ko", "ru"].includes(currentLanguage)) { + if (["de", "fr", "ko", "ru", "tr"].includes(currentLanguage)) { gachaUpLabel.setAlign("center").setY(0); } diff --git a/src/ui/handlers/game-stats-ui-handler.ts b/src/ui/handlers/game-stats-ui-handler.ts index 53b23781584..30243008626 100644 --- a/src/ui/handlers/game-stats-ui-handler.ts +++ b/src/ui/handlers/game-stats-ui-handler.ts @@ -251,7 +251,7 @@ export class GameStatsUiHandler extends UiHandler { const resolvedLang = i18next.resolvedLanguage ?? "en"; // NOTE TO TRANSLATION TEAM: Add more languages that want to display // in a single-column inside of the `[]` (e.g. `["ru", "fr"]`) - return ["fr", "es-ES", "es-419", "it", "ja", "pt-BR", "ru"].includes(resolvedLang); + return ["fr", "es-ES", "es-419", "it", "ja", "pt-BR", "ru", "tr"].includes(resolvedLang); } /** The number of columns used by this menu in the resolved language */ private get columnCount(): 1 | 2 { diff --git a/src/ui/handlers/starter-select-ui-handler.ts b/src/ui/handlers/starter-select-ui-handler.ts index 2623016eb6b..c527b40dbff 100644 --- a/src/ui/handlers/starter-select-ui-handler.ts +++ b/src/ui/handlers/starter-select-ui-handler.ts @@ -155,6 +155,7 @@ const languageSettings: { [key: string]: LanguageSetting } = { tr: { starterInfoTextSize: "56px", instructionTextSize: "38px", + starterInfoXPos: 34, }, ro: { starterInfoTextSize: "56px", From 525ba57461f2128c1558265c03682cf8e87224f3 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 15:46:43 -0700 Subject: [PATCH 47/58] Review changes --- src/data/abilities/ability.ts | 2 +- test/abilities/illusion.test.ts | 71 ++++++++++++++++----------------- 2 files changed, 35 insertions(+), 38 deletions(-) diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index fd1eb8ea5ef..4bc4a9573ee 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -7449,7 +7449,7 @@ export function initAbilities() { // .attr(NoFusionAbilityAbAttr) // // Illusion is available again after a battle // .conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false) - // .uncopiable() + .uncopiable() // .bypassFaint() .unimplemented() // TODO reimplement Illusion properly .build(), diff --git a/test/abilities/illusion.test.ts b/test/abilities/illusion.test.ts index 1264b458234..9746ecca6d5 100644 --- a/test/abilities/illusion.test.ts +++ b/test/abilities/illusion.test.ts @@ -7,7 +7,7 @@ import { GameManager } from "#test/test-utils/game-manager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -describe("Abilities - Illusion", () => { +describe.todo("Abilities - Illusion", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -33,7 +33,7 @@ describe("Abilities - Illusion", () => { .startingHeldItems([{ name: "WIDE_LENS", count: 3 }]); }); - it.todo("creates illusion at the start", async () => { + it("creates illusion at the start", async () => { await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]); const zoroark = game.field.getPlayerPokemon(); const zorua = game.field.getEnemyPokemon(); @@ -42,7 +42,7 @@ describe("Abilities - Illusion", () => { expect(!!zorua.summonData.illusion).equals(true); }); - it.todo("break after receiving damaging move", async () => { + it("break after receiving damaging move", async () => { await game.classicMode.startBattle([SpeciesId.FEEBAS]); game.move.select(MoveId.TACKLE); @@ -54,7 +54,7 @@ describe("Abilities - Illusion", () => { expect(zorua.name).equals("Zorua"); }); - it.todo("break after getting ability changed", async () => { + it("break after getting ability changed", async () => { await game.classicMode.startBattle([SpeciesId.FEEBAS]); game.move.select(MoveId.WORRY_SEED); @@ -65,7 +65,7 @@ describe("Abilities - Illusion", () => { expect(!!zorua.summonData.illusion).equals(false); }); - it.todo("breaks with neutralizing gas", async () => { + it("breaks with neutralizing gas", async () => { game.override.enemyAbility(AbilityId.NEUTRALIZING_GAS); await game.classicMode.startBattle([SpeciesId.KOFFING]); @@ -74,7 +74,7 @@ describe("Abilities - Illusion", () => { expect(!!zorua.summonData.illusion).equals(false); }); - it.todo("does not activate if neutralizing gas is active", async () => { + it("does not activate if neutralizing gas is active", async () => { game.override .enemyAbility(AbilityId.NEUTRALIZING_GAS) .ability(AbilityId.ILLUSION) @@ -88,38 +88,35 @@ describe("Abilities - Illusion", () => { expect(game.field.getPlayerPokemon().summonData.illusion).toBeFalsy(); }); - it.todo( - "causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", - async () => { - game.override.enemyMoveset([MoveId.FLAMETHROWER, MoveId.PSYCHIC, MoveId.TACKLE]); - await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]); + it("causes enemy AI to consider the illusion's type instead of the actual type when considering move effectiveness", async () => { + game.override.enemyMoveset([MoveId.FLAMETHROWER, MoveId.PSYCHIC, MoveId.TACKLE]); + await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.FEEBAS]); - const enemy = game.field.getEnemyPokemon(); - const zoroark = game.field.getPlayerPokemon(); + const enemy = game.field.getEnemyPokemon(); + const zoroark = game.field.getPlayerPokemon(); - const flameThrower = enemy.getMoveset()[0]!.getMove(); - const psychic = enemy.getMoveset()[1]!.getMove(); - const flameThrowerEffectiveness = zoroark.getAttackTypeEffectiveness( - flameThrower.type, - enemy, - undefined, - undefined, - flameThrower, - true, - ); - const psychicEffectiveness = zoroark.getAttackTypeEffectiveness( - psychic.type, - enemy, - undefined, - undefined, - psychic, - true, - ); - expect(psychicEffectiveness).above(flameThrowerEffectiveness); - }, - ); + const flameThrower = enemy.getMoveset()[0]!.getMove(); + const psychic = enemy.getMoveset()[1]!.getMove(); + const flameThrowerEffectiveness = zoroark.getAttackTypeEffectiveness( + flameThrower.type, + enemy, + undefined, + undefined, + flameThrower, + true, + ); + const psychicEffectiveness = zoroark.getAttackTypeEffectiveness( + psychic.type, + enemy, + undefined, + undefined, + psychic, + true, + ); + expect(psychicEffectiveness).above(flameThrowerEffectiveness); + }); - it.todo("should not break from indirect damage from status, weather or recoil", async () => { + it("should not break from indirect damage from status, weather or recoil", async () => { game.override.enemySpecies(SpeciesId.GIGALITH).enemyAbility(AbilityId.SAND_STREAM); await game.classicMode.startBattle([SpeciesId.ZOROARK, SpeciesId.AZUMARILL]); @@ -132,7 +129,7 @@ describe("Abilities - Illusion", () => { expect(!!zoroark.summonData.illusion).equals(true); }); - it.todo("copies the the name, nickname, gender, shininess, and pokeball from the illusion source", async () => { + it("copies the the name, nickname, gender, shininess, and pokeball from the illusion source", async () => { game.override.enemyMoveset(MoveId.SPLASH); await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.ZOROARK, SpeciesId.AXEW]); @@ -155,7 +152,7 @@ describe("Abilities - Illusion", () => { expect(zoroark.getPokeball(true)).equals(PokeballType.GREAT_BALL); }); - it.todo("breaks when suppressed", async () => { + it("breaks when suppressed", async () => { game.override.moveset(MoveId.GASTRO_ACID); await game.classicMode.startBattle([SpeciesId.MAGIKARP]); const zorua = game.field.getEnemyPokemon(); From 5c8c2151a834077f3bb4c8bf4cd6653c056c992f Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 15:58:35 -0700 Subject: [PATCH 48/58] Update src/data/moves/move.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- src/data/moves/move.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 44240d7e358..43baf361d5e 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -1068,9 +1068,11 @@ export abstract class Move implements Localizable { } public getPriorityModifier(user: Pokemon, simulated = true) { + if (user.getTag(BattlerTagType.BYPASS_SPEED)) { + return MovePriorityModifier.FIRST_IN_BRACKET; + } const modifierHolder = new NumberHolder(MovePriorityModifier.NORMAL); - applyAbAttrs("ChangeMovePriorityModifierAbAttr", {pokemon: user, simulated: simulated, move: this, priority: modifierHolder}); - modifierHolder.value = user.getTag(BattlerTagType.BYPASS_SPEED) ? MovePriorityModifier.FIRST_IN_BRACKET : modifierHolder.value; + applyAbAttrs("ChangeMovePriorityModifierAbAttr", { pokemon: user, simulated, move: this, priority: modifierHolder }); return modifierHolder.value; } From fb274077c233a30a3d24679684cb6e04fe319e45 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Fri, 31 Oct 2025 19:01:33 -0400 Subject: [PATCH 49/58] Reworked regex to use `matchAll`, added error handling + tests --- src/data/daily-run.ts | 92 +++++++++++++++++++++-------- src/utils/pokemon-utils.ts | 8 +-- test/daily-mode.test.ts | 115 ++++++++++++++++++++++++------------- 3 files changed, 145 insertions(+), 70 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index c52bb164f4b..9daabc01529 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -68,9 +68,10 @@ function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLeve undefined, formIndex, undefined, - variant !== undefined ? true : undefined, + variant != null, variant, ); + console.log(`%c${pokemon.shiny} ${variant} ${variant != null}`, "color:blue"); const starter: Starter = { speciesId: starterSpecies.speciesId, shiny: pokemon.shiny, @@ -180,7 +181,11 @@ export function isDailyEventSeed(seed: string): boolean { * Must be updated whenever the `MoveId` enum gets a new digit! */ const MOVE_ID_STRING_LENGTH = 4; - +/** + * The regex literal used to parse daily run custom movesets. + * @privateRemarks + * Intentionally does not use the `g` flag to avoid altering `lastIndex` after each match. + */ const MOVE_ID_SEED_REGEX = /(?<=\/moves)((?:\d{4}){0,4})(?:,((?:\d{4}){0,4}))?(?:,((?:\d{4}){0,4}))?/; /** @@ -223,53 +228,90 @@ function setDailyRunEventStarterMovesets(seed: string, starters: StarterTuple): } } +/** The regex literal string used to extract the content of the "starters" block of Daily Run custom seeds. */ +const STARTER_SEED_PREFIX_REGEX = /\/starters(.*?)(?:\/|$)/; /** - * Expects the seed to contain `starters` followed by 3 `s{\d{4}}` for the starters. The 4 digits are the species ID. \ - * Each starter can optionally be followed by `f{\d{2}}` for the form index and `v{\d{2}}` for the variant. \ - * The order of `f` and `v` does not matter. - * @example `/starterss0003f01s0025v01s0150f02v02` + * The regex literal used to parse daily run custom starter information for a single starter. \ + * Contains a 4-digit species ID, as well as an optional 2-digit form index and 1-digit variant. + * + * If either of form index or variant are omitted, the starter will default to its species' base form/ + * not be shiny, respectively. + */ +const STARTER_SEED_MATCH_REGEX = /(?:s(?\d{4}))(?:f(?
\d{2}))?(?:v(?\d))?/g; + +/** + * Parse a custom daily run seed into a set of pre-defined starters. + * @see {@linkcode STARTER_SEED_MATCH_REGEX} * @param seed - The daily run seed - * @returns An array of {@linkcode Starter}s, or `null` if no valid match. + * @returns An array of {@linkcode Starter}s, or `null` if it did not match. */ // TODO: Rework this setup into JSON or similar - this is quite hard to maintain function getDailyEventSeedStarters(seed: string): StarterTuple | null { - const speciesRegex = i => - `(?s\\d{4})(?:(?f\\d{2})(?v\\d{2})?|(?v\\d{2})(?f\\d{2})?)?`; + if (!isDailyEventSeed(seed)) { + return null; + } - const matcher = new RegExp(`starters${speciesRegex(1)}${speciesRegex(2)}${speciesRegex(3)}`); + const seedAfterPrefix = seed.split(STARTER_SEED_PREFIX_REGEX)[1] as string | undefined; + if (!seedAfterPrefix) { + return null; + } - const speciesConfigurations = matcher.exec(seed)?.groups; + const speciesConfigurations = [...seedAfterPrefix.matchAll(STARTER_SEED_MATCH_REGEX)]; - if (!speciesConfigurations) { + if (speciesConfigurations.length !== 3) { + // TODO: Remove legacy fallback code after next hotfix version - this is needed for Oct 31's daily to function const legacyStarters = getDailyEventSeedStartersLegacy(seed); - if (legacyStarters != null) { - console.log("Using legacy starter parsing for daily run seed."); + if (legacyStarters == null) { return legacyStarters; } - console.error("Invalid starters used for custom daily run seed!"); + console.error("Invalid starters used for custom daily run seed!", seed); return null; } const speciesIds = getEnumValues(SpeciesId); - const starters: Starter[] = []; - for (let i = 0; i < 3; i++) { - const speciesId = Number.parseInt(speciesConfigurations[`species${i + 1}`].slice(1)) as SpeciesId; - const formIndex = Number.parseInt(speciesConfigurations[`form${i + 1}`]?.slice(1) ?? "00"); - let variant: Variant | undefined = Number.parseInt(speciesConfigurations[`variant${i + 1}`]?.slice(1)) as Variant; - if (!speciesIds.includes(speciesId)) { - console.error("Invalid species ID used for custom daily run seed starter:", speciesId); + for (const [i, match] of speciesConfigurations.entries()) { + const { groups } = match; + if (!groups) { + console.error("Invalid seed used for custom daily run starter:", match); + return null; + } + + const { species: speciesStr, form: formStr, variant: variantStr } = groups; + + const speciesId = Number.parseInt(speciesStr) as SpeciesId; + + // NB: We check the parsed integer here to exclude SpeciesID.NONE as well as invalid values; + // other fields only check the string to permit 0 as valid inputs + if (!speciesId || !speciesIds.includes(speciesId)) { + console.error("Invalid species ID used for custom daily run starter:", speciesStr); return null; } const starterSpecies = getPokemonSpecies(speciesId); - if (Number.isNaN(variant) || variant > 2 || (!starterSpecies.hasVariants() && variant !== 0)) { - console.error("Invalid variant used for custom daily run seed starter:", variant); + // Omitted form index = use base form + const starterForm = formStr ? starterSpecies.forms[Number.parseInt(formStr)] : starterSpecies; + + if (!starterForm) { + console.log(starterSpecies.name); + console.error("Invalid form index used for custom daily run starter:", formStr); + return null; + } + + // Get and validate variant + let variant = (variantStr ? Number.parseInt(variantStr) : undefined) as Variant | undefined; + if (!isBetween(variant ?? 0, 0, 2)) { + console.error("Variant used for custom daily run seed starter out of bounds:", variantStr); + return null; + } + + // Fall back to default variant if none exists + if (!starterSpecies.hasVariants() && !!variant) { + console.warn("Variant for custom daily run seed starter does not exist, using base variant...", variant); variant = undefined; } - const starterForm = getPokemonSpeciesForm(speciesId, formIndex); const startingLevel = globalScene.gameMode.getStartingLevel(); const starter = getDailyRunStarter(starterForm, startingLevel, variant); starters.push(starter); diff --git a/src/utils/pokemon-utils.ts b/src/utils/pokemon-utils.ts index e3c8d8eab68..f1716487b34 100644 --- a/src/utils/pokemon-utils.ts +++ b/src/utils/pokemon-utils.ts @@ -118,11 +118,9 @@ export function getFusedSpeciesName(speciesAName: string, speciesBName: string): } export function getPokemonSpeciesForm(species: SpeciesId, formIndex: number): PokemonSpeciesForm { - const retSpecies: PokemonSpecies = - species >= 2000 - ? allSpecies.find(s => s.speciesId === species)! // TODO: is the bang correct? - : allSpecies[species - 1]; - if (formIndex < retSpecies.forms?.length) { + const retSpecies: PokemonSpecies = getPokemonSpecies(species); + + if (formIndex < retSpecies.forms.length) { return retSpecies.forms[formIndex]; } return retSpecies; diff --git a/test/daily-mode.test.ts b/test/daily-mode.test.ts index e5284906318..6ab61cc0ed0 100644 --- a/test/daily-mode.test.ts +++ b/test/daily-mode.test.ts @@ -21,6 +21,8 @@ describe("Daily Mode", () => { beforeEach(() => { game = new GameManager(phaserGame); + + game.override.disableShinies = false; }); afterEach(() => { @@ -41,52 +43,85 @@ describe("Daily Mode", () => { }); describe("Custom Seeds", () => { - it("should support custom moves", async () => { - vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004,03320006,01300919"); - await game.dailyMode.startBattle(); + describe("Moves", () => { + it("should support custom moves", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004,03320006,01300919"); + await game.dailyMode.startBattle(); - const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId)); - expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([ - MoveId.POUND, - MoveId.KARATE_CHOP, - MoveId.DOUBLE_SLAP, - MoveId.COMET_PUNCH, - ]); - expect(moves2, stringifyEnumArray(MoveId, moves2)).toEqual([ - MoveId.AERIAL_ACE, - MoveId.PAY_DAY, - expect.anything(), // make sure it doesn't replace normal moveset gen - expect.anything(), - ]); - expect(moves3, stringifyEnumArray(MoveId, moves3)).toEqual([ - MoveId.SKULL_BASH, - MoveId.MALIGNANT_CHAIN, - expect.anything(), - expect.anything(), - ]); + const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId)); + expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([ + MoveId.POUND, + MoveId.KARATE_CHOP, + MoveId.DOUBLE_SLAP, + MoveId.COMET_PUNCH, + ]); + expect(moves2, stringifyEnumArray(MoveId, moves2)).toEqual([ + MoveId.AERIAL_ACE, + MoveId.PAY_DAY, + expect.anything(), // make sure it doesn't replace normal moveset gen + expect.anything(), + ]); + expect(moves3, stringifyEnumArray(MoveId, moves3)).toEqual([ + MoveId.SKULL_BASH, + MoveId.MALIGNANT_CHAIN, + expect.anything(), + expect.anything(), + ]); + }); + + it("should allow omitting movesets for some starters", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004"); + await game.dailyMode.startBattle(); + + const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId)); + expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([ + MoveId.POUND, + MoveId.KARATE_CHOP, + MoveId.DOUBLE_SLAP, + MoveId.COMET_PUNCH, + ]); + expect(moves2, "was not a random moveset").toHaveLength(4); + expect(moves3, "was not a random moveset").toHaveLength(4); + }); + + it("should skip invalid move IDs", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves9999,,0919"); + await game.dailyMode.startBattle(); + + const moves = game.field.getPlayerPokemon().moveset.map(pm => pm.moveId); + expect(moves, "invalid move was in moveset").not.toContain(MoveId[9999]); + }); }); - it("should allow omitting movesets for some starters", async () => { - vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves0001000200030004"); - await game.dailyMode.startBattle(); + describe("Starters", () => { + it("should support custom species IDs", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("foo/starterss0001s0113s1024"); + await game.dailyMode.startBattle(); - const [moves1, moves2, moves3] = game.scene.getPlayerParty().map(p => p.moveset.map(pm => pm.moveId)); - expect(moves1, stringifyEnumArray(MoveId, moves1)).toEqual([ - MoveId.POUND, - MoveId.KARATE_CHOP, - MoveId.DOUBLE_SLAP, - MoveId.COMET_PUNCH, - ]); - expect(moves2, "was not a random moveset").toHaveLength(4); - expect(moves3, "was not a random moveset").toHaveLength(4); - }); + const party = game.scene.getPlayerParty().map(p => p.species.speciesId); + expect(party, stringifyEnumArray(SpeciesId, party)).toEqual([ + SpeciesId.BULBASAUR, + SpeciesId.CHANSEY, + SpeciesId.TERAPAGOS, + ]); + }); - it("should skip invalid move IDs", async () => { - vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/moves9999,,0919"); - await game.dailyMode.startBattle(); + it("should support custom forms and variants", async () => { + vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/starterss0006f01v2s0113v0s1024f02"); + await game.dailyMode.startBattle(); - const moves = game.field.getPlayerPokemon().moveset.map(pm => pm.moveId); - expect(moves, "invalid move was in moveset").not.toContain(MoveId[9999]); + const party = game.scene.getPlayerParty().map(p => ({ + speciesId: p.species.speciesId, + variant: p.getVariant(), + form: p.formIndex, + shiny: p.isShiny(), + })); + expect(party).toEqual([ + { speciesId: SpeciesId.CHARIZARD, variant: 2, form: 1, shiny: true }, + { speciesId: SpeciesId.CHANSEY, variant: 0, form: 0, shiny: true }, + { speciesId: SpeciesId.TERAPAGOS, variant: expect.anything(), form: 2, shiny: false }, + ]); + }); }); }); }); From 617e12f6342e650355cbdb01b04abaf502b0f2c6 Mon Sep 17 00:00:00 2001 From: Bertie690 Date: Fri, 31 Oct 2025 19:14:19 -0400 Subject: [PATCH 50/58] Removed console log --- src/data/daily-run.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/data/daily-run.ts b/src/data/daily-run.ts index 9daabc01529..215e23be3b9 100644 --- a/src/data/daily-run.ts +++ b/src/data/daily-run.ts @@ -71,7 +71,6 @@ function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLeve variant != null, variant, ); - console.log(`%c${pokemon.shiny} ${variant} ${variant != null}`, "color:blue"); const starter: Starter = { speciesId: starterSpecies.speciesId, shiny: pokemon.shiny, @@ -271,7 +270,7 @@ function getDailyEventSeedStarters(seed: string): StarterTuple | null { const speciesIds = getEnumValues(SpeciesId); const starters: Starter[] = []; - for (const [i, match] of speciesConfigurations.entries()) { + for (const match of speciesConfigurations) { const { groups } = match; if (!groups) { console.error("Invalid seed used for custom daily run starter:", match); From c33f9723f543ccb0693b7fc6966ea406da2c1f86 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:21:38 -0700 Subject: [PATCH 51/58] Update enum name --- src/data/abilities/ability.ts | 14 +++++++------- src/data/moves/move.ts | 8 ++++---- src/enums/move-priority-modifier.ts | 8 ++++---- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index 180ba0f3e90..d3c646b9321 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -34,7 +34,7 @@ import { MoveCategory } from "#enums/move-category"; import { MoveFlags } from "#enums/move-flags"; import { MoveId } from "#enums/move-id"; import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; -import { MovePriorityModifier } from "#enums/move-priority-modifier"; +import { MovePriorityInBracket } from "#enums/move-priority-modifier"; import { MoveResult } from "#enums/move-result"; import { MoveTarget } from "#enums/move-target"; import { MoveUseMode } from "#enums/move-use-mode"; @@ -4143,11 +4143,11 @@ export class ChangeMovePriorityAbAttr extends AbAttr { } } -export class ChangeMovePriorityModifierAbAttr extends AbAttr { - private readonly newModifier: MovePriorityModifier; +export class ChangeMovePriorityInBracketAbAttr extends AbAttr { + private readonly newModifier: MovePriorityInBracket; private readonly moveFunc: (pokemon: Pokemon, move: Move) => boolean; - constructor(moveFunc: (pokemon: Pokemon, move: Move) => boolean, newModifier: MovePriorityModifier) { + constructor(moveFunc: (pokemon: Pokemon, move: Move) => boolean, newModifier: MovePriorityInBracket) { super(false); this.newModifier = newModifier; this.moveFunc = moveFunc; @@ -6741,7 +6741,7 @@ const AbilityAttrs = Object.freeze({ BlockStatusDamageAbAttr, BlockOneHitKOAbAttr, ChangeMovePriorityAbAttr, - ChangeMovePriorityModifierAbAttr, + ChangeMovePriorityInBracketAbAttr, IgnoreContactAbAttr, PreWeatherEffectAbAttr, PreWeatherDamageAbAttr, @@ -7259,7 +7259,7 @@ export function initAbilities() { .attr(DoubleBattleChanceAbAttr) .build(), new AbBuilder(AbilityId.STALL, 4) - .attr(ChangeMovePriorityModifierAbAttr, (_pokemon, _move: Move) => true, MovePriorityModifier.LAST_IN_BRACKET) + .attr(ChangeMovePriorityInBracketAbAttr, (_pokemon, _move: Move) => true, MovePriorityInBracket.LAST) .build(), new AbBuilder(AbilityId.TECHNICIAN, 4) .attr(MovePowerBoostAbAttr, (user, target, move) => { @@ -8206,7 +8206,7 @@ export function initAbilities() { .ignorable() .build(), new AbBuilder(AbilityId.MYCELIUM_MIGHT, 9) - .attr(ChangeMovePriorityModifierAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, MovePriorityModifier.LAST_IN_BRACKET) + .attr(ChangeMovePriorityInBracketAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, MovePriorityInBracket.LAST) .attr(PreventBypassSpeedChanceAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS) .attr(MoveAbilityBypassAbAttr, (_pokemon, move: Move) => move.category === MoveCategory.STATUS) .build(), diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 43baf361d5e..417ae7c3b93 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -101,7 +101,7 @@ import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; import { inSpeedOrder } from "#utils/speed-order-generator"; import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils"; import type { ReadonlyGenericUint8Array } from "#types/typed-arrays"; -import { MovePriorityModifier } from "#enums/move-priority-modifier"; +import { MovePriorityInBracket } from "#enums/move-priority-modifier"; /** * A function used to conditionally determine execution of a given {@linkcode MoveAttr}. @@ -1069,10 +1069,10 @@ export abstract class Move implements Localizable { public getPriorityModifier(user: Pokemon, simulated = true) { if (user.getTag(BattlerTagType.BYPASS_SPEED)) { - return MovePriorityModifier.FIRST_IN_BRACKET; + return MovePriorityInBracket.FIRST; } - const modifierHolder = new NumberHolder(MovePriorityModifier.NORMAL); - applyAbAttrs("ChangeMovePriorityModifierAbAttr", { pokemon: user, simulated, move: this, priority: modifierHolder }); + const modifierHolder = new NumberHolder(MovePriorityInBracket.NORMAL); + applyAbAttrs("ChangeMovePriorityInBracketAbAttr", { pokemon: user, simulated, move: this, priority: modifierHolder }); return modifierHolder.value; } diff --git a/src/enums/move-priority-modifier.ts b/src/enums/move-priority-modifier.ts index 3e51aaec0a3..ea314fda0e4 100644 --- a/src/enums/move-priority-modifier.ts +++ b/src/enums/move-priority-modifier.ts @@ -3,11 +3,11 @@ import type { ObjectValues } from "#types/type-helpers"; /** * Enum representing modifiers for Move priorities. */ -export const MovePriorityModifier = Object.freeze({ +export const MovePriorityInBracket = Object.freeze({ /** Used when moves go last in their priority bracket, but before moves of lower priority. */ - LAST_IN_BRACKET: 0, + LAST: 0, NORMAL: 1, /** Used when moves go first in their priority bracket, but before moves of lower priority. */ - FIRST_IN_BRACKET: 2, + FIRST: 2, }); -export type MovePriorityModifier = ObjectValues; +export type MovePriorityInBracket = ObjectValues; From f928ca9bdf1d37c7e842df9bc2e9d74d6d02abe6 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:23:57 -0700 Subject: [PATCH 52/58] Update enum filename --- src/data/abilities/ability.ts | 2 +- src/data/moves/move.ts | 2 +- .../{move-priority-modifier.ts => move-priority-in-bracket.ts} | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename src/enums/{move-priority-modifier.ts => move-priority-in-bracket.ts} (100%) diff --git a/src/data/abilities/ability.ts b/src/data/abilities/ability.ts index d3c646b9321..90adcd86b5d 100644 --- a/src/data/abilities/ability.ts +++ b/src/data/abilities/ability.ts @@ -34,7 +34,7 @@ import { MoveCategory } from "#enums/move-category"; import { MoveFlags } from "#enums/move-flags"; import { MoveId } from "#enums/move-id"; import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; -import { MovePriorityInBracket } from "#enums/move-priority-modifier"; +import { MovePriorityInBracket } from "#enums/move-priority-in-bracket"; import { MoveResult } from "#enums/move-result"; import { MoveTarget } from "#enums/move-target"; import { MoveUseMode } from "#enums/move-use-mode"; diff --git a/src/data/moves/move.ts b/src/data/moves/move.ts index 417ae7c3b93..8637c65966b 100644 --- a/src/data/moves/move.ts +++ b/src/data/moves/move.ts @@ -101,7 +101,7 @@ import { MovePhaseTimingModifier } from "#enums/move-phase-timing-modifier"; import { inSpeedOrder } from "#utils/speed-order-generator"; import { canSpeciesTera, willTerastallize } from "#utils/pokemon-utils"; import type { ReadonlyGenericUint8Array } from "#types/typed-arrays"; -import { MovePriorityInBracket } from "#enums/move-priority-modifier"; +import { MovePriorityInBracket } from "#enums/move-priority-in-bracket"; /** * A function used to conditionally determine execution of a given {@linkcode MoveAttr}. diff --git a/src/enums/move-priority-modifier.ts b/src/enums/move-priority-in-bracket.ts similarity index 100% rename from src/enums/move-priority-modifier.ts rename to src/enums/move-priority-in-bracket.ts From c1c12e479223ce3e08e07dab736b87f69a8bed99 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:51:22 -0700 Subject: [PATCH 53/58] Revert uxie passive --- src/data/balance/passives.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/data/balance/passives.ts b/src/data/balance/passives.ts index 223f50471e8..bc7f8377b9e 100644 --- a/src/data/balance/passives.ts +++ b/src/data/balance/passives.ts @@ -506,7 +506,7 @@ export const starterPassiveAbilities: StarterPassiveAbilities = { [SpeciesId.SNOVER]: { 0: AbilityId.SLUSH_RUSH }, [SpeciesId.ABOMASNOW]: { 0: AbilityId.SLUSH_RUSH, 1: AbilityId.SEED_SOWER }, [SpeciesId.ROTOM]: { 0: AbilityId.HADRON_ENGINE, 1: AbilityId.HADRON_ENGINE, 2: AbilityId.HADRON_ENGINE, 3: AbilityId.HADRON_ENGINE, 4: AbilityId.HADRON_ENGINE, 5: AbilityId.HADRON_ENGINE }, - [SpeciesId.UXIE]: { 0: AbilityId.ILLUSION }, + [SpeciesId.UXIE]: { 0: AbilityId.MAGIC_BOUNCE }, [SpeciesId.MESPRIT]: { 0: AbilityId.MOODY }, [SpeciesId.AZELF]: { 0: AbilityId.NEUROFORCE }, [SpeciesId.DIALGA]: { 0: AbilityId.BERSERK, 1: AbilityId.BERSERK }, From 7a56989a3c1761287dcfb8ab55a3b1cc9fd97569 Mon Sep 17 00:00:00 2001 From: Dean <69436131+emdeann@users.noreply.github.com> Date: Fri, 31 Oct 2025 16:51:49 -0700 Subject: [PATCH 54/58] Remove illusion bypassing summondata reset --- src/field/pokemon.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6ce5c1ffc2c..1d58f7de883 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -143,7 +143,6 @@ import type { AbAttrMap, AbAttrString, TypeMultiplierAbAttrParams } from "#types import type { Constructor } from "#types/common"; import type { getAttackDamageParams, getBaseDamageParams } from "#types/damage-params"; import type { DamageCalculationResult, DamageResult } from "#types/damage-result"; -import type { IllusionData } from "#types/illusion-data"; import type { LevelMoves } from "#types/pokemon-level-moves"; import type { StarterDataEntry, StarterMoveset } from "#types/save-data"; import type { TurnMove } from "#types/turn-move"; @@ -5119,14 +5118,12 @@ export abstract class Pokemon extends Phaser.GameObjects.Container { * in preparation for switching pokemon, as well as removing any relevant on-switch tags. */ public resetSummonData(): void { - const illusion: IllusionData | null = this.summonData.illusion; if (this.summonData.speciesForm) { this.summonData.speciesForm = null; this.updateFusionPalette(); } this.summonData = new PokemonSummonData(); this.tempSummonData = new PokemonTempSummonData(); - this.summonData.illusion = illusion; this.updateInfo(); } From 3b704913e920d628efb321d5134c628702d09e1f Mon Sep 17 00:00:00 2001 From: fabske0 <192151969+fabske0@users.noreply.github.com> Date: Sat, 1 Nov 2025 00:52:51 +0100 Subject: [PATCH 55/58] update locales --- locales | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/locales b/locales index 67a0c026068..ddf9509e1c6 160000 --- a/locales +++ b/locales @@ -1 +1 @@ -Subproject commit 67a0c02606848cc6ca3f8998a7cbacb0d7dd5a9e +Subproject commit ddf9509e1c6abe8fc93b455d79bfaa0202e05ede From 58f42bc5c2a0351f934b1c9eb0346d828a12e9a8 Mon Sep 17 00:00:00 2001 From: Madmadness65 Date: Sat, 1 Nov 2025 15:55:06 -0500 Subject: [PATCH 56/58] Fix formatting in pokemon-evolutions.ts No functional changes, just matching how all other evolutions are formatted in the file. --- src/data/balance/pokemon-evolutions.ts | 96 +++++++++++++++++++------- 1 file changed, 72 insertions(+), 24 deletions(-) diff --git a/src/data/balance/pokemon-evolutions.ts b/src/data/balance/pokemon-evolutions.ts index b33f690e04d..04c3660d2eb 100644 --- a/src/data/balance/pokemon-evolutions.ts +++ b/src/data/balance/pokemon-evolutions.ts @@ -655,10 +655,18 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(SpeciesId.GARDEVOIR, 30, null, null), new SpeciesEvolution(SpeciesId.GALLADE, 1, EvolutionItem.DAWN_STONE, {key: EvoCondKey.GENDER, gender: Gender.MALE}, [30, 30, 30]), ], - [SpeciesId.SURSKIT]: [new SpeciesEvolution(SpeciesId.MASQUERAIN, 22, null, null)], - [SpeciesId.SHROOMISH]: [new SpeciesEvolution(SpeciesId.BRELOOM, 23, null, null)], - [SpeciesId.SLAKOTH]: [new SpeciesEvolution(SpeciesId.VIGOROTH, 18, null, null)], - [SpeciesId.VIGOROTH]: [new SpeciesEvolution(SpeciesId.SLAKING, 36, null, null)], + [SpeciesId.SURSKIT]: [ + new SpeciesEvolution(SpeciesId.MASQUERAIN, 22, null, null) + ], + [SpeciesId.SHROOMISH]: [ + new SpeciesEvolution(SpeciesId.BRELOOM, 23, null, null) + ], + [SpeciesId.SLAKOTH]: [ + new SpeciesEvolution(SpeciesId.VIGOROTH, 18, null, null) + ], + [SpeciesId.VIGOROTH]: [ + new SpeciesEvolution(SpeciesId.SLAKING, 36, null, null) + ], [SpeciesId.NINCADA]: [ new SpeciesEvolution(SpeciesId.NINJASK, 20, null, null), new SpeciesEvolution(SpeciesId.SHEDINJA, 20, null, {key: EvoCondKey.SHEDINJA}) @@ -736,26 +744,66 @@ export const pokemonEvolutions: PokemonEvolutions = { new SpeciesEvolution(SpeciesId.GLALIE, 42, null, null), new SpeciesEvolution(SpeciesId.FROSLASS, 1, EvolutionItem.DAWN_STONE, {key: EvoCondKey.GENDER, gender: Gender.FEMALE}, [42, 42, 42]), ], - [SpeciesId.SPHEAL]: [new SpeciesEvolution(SpeciesId.SEALEO, 32, null, null)], - [SpeciesId.SEALEO]: [new SpeciesEvolution(SpeciesId.WALREIN, 44, null, null)], - [SpeciesId.BAGON]: [new SpeciesEvolution(SpeciesId.SHELGON, 30, null, null)], - [SpeciesId.SHELGON]: [new SpeciesEvolution(SpeciesId.SALAMENCE, 50, null, null)], - [SpeciesId.BELDUM]: [new SpeciesEvolution(SpeciesId.METANG, 20, null, null)], - [SpeciesId.METANG]: [new SpeciesEvolution(SpeciesId.METAGROSS, 45, null, null)], - [SpeciesId.TURTWIG]: [new SpeciesEvolution(SpeciesId.GROTLE, 18, null, null)], - [SpeciesId.GROTLE]: [new SpeciesEvolution(SpeciesId.TORTERRA, 32, null, null)], - [SpeciesId.CHIMCHAR]: [new SpeciesEvolution(SpeciesId.MONFERNO, 14, null, null)], - [SpeciesId.MONFERNO]: [new SpeciesEvolution(SpeciesId.INFERNAPE, 36, null, null)], - [SpeciesId.PIPLUP]: [new SpeciesEvolution(SpeciesId.PRINPLUP, 16, null, null)], - [SpeciesId.PRINPLUP]: [new SpeciesEvolution(SpeciesId.EMPOLEON, 36, null, null)], - [SpeciesId.STARLY]: [new SpeciesEvolution(SpeciesId.STARAVIA, 14, null, null)], - [SpeciesId.STARAVIA]: [new SpeciesEvolution(SpeciesId.STARAPTOR, 34, null, null)], - [SpeciesId.BIDOOF]: [new SpeciesEvolution(SpeciesId.BIBAREL, 15, null, null)], - [SpeciesId.KRICKETOT]: [new SpeciesEvolution(SpeciesId.KRICKETUNE, 10, null, null)], - [SpeciesId.SHINX]: [new SpeciesEvolution(SpeciesId.LUXIO, 15, null, null)], - [SpeciesId.LUXIO]: [new SpeciesEvolution(SpeciesId.LUXRAY, 30, null, null)], - [SpeciesId.CRANIDOS]: [new SpeciesEvolution(SpeciesId.RAMPARDOS, 30, null, null)], - [SpeciesId.SHIELDON]: [new SpeciesEvolution(SpeciesId.BASTIODON, 30, null, null)], + [SpeciesId.SPHEAL]: [ + new SpeciesEvolution(SpeciesId.SEALEO, 32, null, null) + ], + [SpeciesId.SEALEO]: [ + new SpeciesEvolution(SpeciesId.WALREIN, 44, null, null) + ], + [SpeciesId.BAGON]: [ + new SpeciesEvolution(SpeciesId.SHELGON, 30, null, null) + ], + [SpeciesId.SHELGON]: [ + new SpeciesEvolution(SpeciesId.SALAMENCE, 50, null, null) + ], + [SpeciesId.BELDUM]: [ + new SpeciesEvolution(SpeciesId.METANG, 20, null, null) + ], + [SpeciesId.METANG]: [ + new SpeciesEvolution(SpeciesId.METAGROSS, 45, null, null) + ], + [SpeciesId.TURTWIG]: [ + new SpeciesEvolution(SpeciesId.GROTLE, 18, null, null) + ], + [SpeciesId.GROTLE]: [ + new SpeciesEvolution(SpeciesId.TORTERRA, 32, null, null) + ], + [SpeciesId.CHIMCHAR]: [ + new SpeciesEvolution(SpeciesId.MONFERNO, 14, null, null) + ], + [SpeciesId.MONFERNO]: [ + new SpeciesEvolution(SpeciesId.INFERNAPE, 36, null, null) + ], + [SpeciesId.PIPLUP]: [ + new SpeciesEvolution(SpeciesId.PRINPLUP, 16, null, null) + ], + [SpeciesId.PRINPLUP]: [ + new SpeciesEvolution(SpeciesId.EMPOLEON, 36, null, null) + ], + [SpeciesId.STARLY]: [ + new SpeciesEvolution(SpeciesId.STARAVIA, 14, null, null) + ], + [SpeciesId.STARAVIA]: [ + new SpeciesEvolution(SpeciesId.STARAPTOR, 34, null, null) + ], + [SpeciesId.BIDOOF]: [ + new SpeciesEvolution(SpeciesId.BIBAREL, 15, null, null) + ], + [SpeciesId.KRICKETOT]: [ + new SpeciesEvolution(SpeciesId.KRICKETUNE, 10, null, null) + ], + [SpeciesId.SHINX]: [ + new SpeciesEvolution(SpeciesId.LUXIO, 15, null, null) + ], + [SpeciesId.LUXIO]: [ + new SpeciesEvolution(SpeciesId.LUXRAY, 30, null, null) + ], + [SpeciesId.CRANIDOS]: [ + new SpeciesEvolution(SpeciesId.RAMPARDOS, 30, null, null) + ], + [SpeciesId.SHIELDON]: [ + new SpeciesEvolution(SpeciesId.BASTIODON, 30, null, null) + ], [SpeciesId.BURMY]: [ new SpeciesEvolution(SpeciesId.MOTHIM, 20, null, {key: EvoCondKey.GENDER, gender: Gender.MALE}), new SpeciesEvolution(SpeciesId.WORMADAM, 20, null, {key: EvoCondKey.GENDER, gender: Gender.FEMALE}) From 4e8b8862a19fe80a3302e851f26fd063ed6e2241 Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Sat, 1 Nov 2025 18:51:30 -0400 Subject: [PATCH 57/58] [Dev] Add `biome:staged` command to lint currently staged files (#6737) * [Dev] Adde `biome:staged` command to lint currently staged files * Apply suggestion from @DayKev Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --------- Co-authored-by: Wlowscha <54003515+Wlowscha@users.noreply.github.com> Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- lefthook.yml | 4 ++-- package.json | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/lefthook.yml b/lefthook.yml index e5ed457a1b6..9b4be96056f 100644 --- a/lefthook.yml +++ b/lefthook.yml @@ -8,9 +8,9 @@ pre-commit: - rebase commands: biome-lint: - # Disable colors as certain IDEs don't support it in the output pane. + # Disable colors as certain IDEs (such as VSCode) don't support it in the output pane. # Summary mode looks decent in plain ASCII anyhow - run: pnpm exec biome check --write --colors=off --reporter=summary --staged --no-errors-on-unmatched --diagnostic-level=error + run: pnpm biome:staged --colors=off --reporter=summary stage_fixed: true ls-lint: run: pnpm exec ls-lint diff --git a/package.json b/package.json index e08e5a393a4..0730cc5197b 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "typecheck": "tsc --noEmit", "typecheck:scripts": "tsc -p scripts/jsconfig.json", "biome": "biome check --write --changed --no-errors-on-unmatched --diagnostic-level=error", + "biome:staged": "biome check --write --staged --no-errors-on-unmatched --diagnostic-level=error", "biome:all": "biome check --write --no-errors-on-unmatched --diagnostic-level=error", "biome-ci": "biome ci --diagnostic-level=error --reporter=github --no-errors-on-unmatched", "typedoc": "typedoc", From f41752c3f9b6a619b6958333d9dfe8688701ab1c Mon Sep 17 00:00:00 2001 From: Bertie690 <136088738+Bertie690@users.noreply.github.com> Date: Sat, 1 Nov 2025 19:09:36 -0400 Subject: [PATCH 58/58] [Test] Fix test end log check mark (#6726) * [Test] Fix test end log check mark heavy check mark looks weird on more fonts than the normal one * Added variant selector codepoint to force rendering as thin version * Update test/test-utils/setup/test-end-log.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Changed checkmark back to normal one idfk how this works maaaan --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --- test/test-utils/setup/test-end-log.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/test-utils/setup/test-end-log.ts b/test/test-utils/setup/test-end-log.ts index 5be8299b124..a230cccca11 100644 --- a/test/test-utils/setup/test-end-log.ts +++ b/test/test-utils/setup/test-end-log.ts @@ -66,8 +66,8 @@ function getResultStr(result: RunnerTaskResult | undefined): string { const resultStr = result.state === "pass" - ? chalk.green.bold("✔ Passed") - : (result?.duration ?? 0) > 2 + ? chalk.green.bold("✓ Passed") + : (result?.duration ?? 0) > 20_000 ? chalk.cyan.bold("◴ Timed out") : chalk.red.bold("✗ Failed");