Merge branch 'beta' into cached-fetch

This commit is contained in:
Wlowscha 2025-11-02 00:13:59 +01:00 committed by GitHub
commit f2f8cc67ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
76 changed files with 2070 additions and 1125 deletions

4
.gitignore vendored
View File

@ -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
./*.csv

2
assets

@ -1 +1 @@
Subproject commit c5d6e54c2c8c0ba3d6c11fd6f3a1c1d07efd2c16
Subproject commit d2d9309cd1acfcebeefbf4c1c63e1104a1294ed8

View File

@ -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

@ -1 +1 @@
Subproject commit 01a0aa4441b85221c61211eb1097d93e004f4334
Subproject commit ddf9509e1c6abe8fc93b455d79bfaa0202e05ede

View File

@ -1,7 +1,7 @@
{
"name": "pokemon-rogue-battle",
"private": true,
"version": "1.10.7",
"version": "1.11.2",
"type": "module",
"scripts": {
"start:prod": "vite --mode production",
@ -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",
@ -80,5 +81,5 @@
"engines": {
"node": ">=24.9.0"
},
"packageManager": "pnpm@10.18.3"
"packageManager": "pnpm@10.19.0"
}

View File

@ -1,6 +1,7 @@
onlyBuiltDependencies:
- core-js
- esbuild
- msw
- lefthook
- msw
shellEmulator: true

View File

@ -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;
}

View File

@ -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,
});
@ -803,6 +811,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);
@ -1621,6 +1633,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:
@ -1640,11 +1653,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;
@ -1714,7 +1726,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);
}

View File

@ -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 { 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";
@ -66,6 +67,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 +2859,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 +3170,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)),
@ -4143,6 +4143,25 @@ export class ChangeMovePriorityAbAttr extends AbAttr {
}
}
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: MovePriorityInBracket) {
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;
}
@ -4214,28 +4233,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 () => {
@ -4423,7 +4440,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 +5009,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 +5562,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;
@ -6725,6 +6741,7 @@ const AbilityAttrs = Object.freeze({
BlockStatusDamageAbAttr,
BlockOneHitKOAbAttr,
ChangeMovePriorityAbAttr,
ChangeMovePriorityInBracketAbAttr,
IgnoreContactAbAttr,
PreWeatherEffectAbAttr,
PreWeatherDamageAbAttr,
@ -6908,7 +6925,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)
@ -7242,7 +7259,7 @@ export function initAbilities() {
.attr(DoubleBattleChanceAbAttr)
.build(),
new AbBuilder(AbilityId.STALL, 4)
.attr(ChangeMovePriorityAbAttr, (_pokemon, _move: Move) => true, -0.2)
.attr(ChangeMovePriorityInBracketAbAttr, (_pokemon, _move: Move) => true, MovePriorityInBracket.LAST)
.build(),
new AbBuilder(AbilityId.TECHNICIAN, 4)
.attr(MovePowerBoostAbAttr, (user, target, move) => {
@ -7344,7 +7361,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)
@ -7444,17 +7461,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)
// // 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()
// .bypassFaint()
.unimplemented() // TODO reimplement Illusion properly
.build(),
new AbBuilder(AbilityId.IMPOSTER, 5)
.attr(PostSummonTransformAbAttr)
@ -7658,10 +7676,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)
@ -7701,7 +7721,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)
@ -8061,7 +8081,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)
@ -8187,7 +8207,7 @@ export function initAbilities() {
.ignorable()
.build(),
new AbBuilder(AbilityId.MYCELIUM_MIGHT, 9)
.attr(ChangeMovePriorityAbAttr, (_pokemon, move) => move.category === MoveCategory.STATUS, -0.2)
.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(),

View File

@ -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 => {

View File

@ -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 ],
[TimeOfDay.NIGHT]: [ SpeciesId.SEEDOT ],
[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.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]: [ 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]: {

View File

@ -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.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 ],
@ -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<Record<SpeciesId, [MoveId, MoveId, MoveId, MoveId]>>;

File diff suppressed because it is too large Load Diff

View File

@ -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 },
@ -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 },
@ -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 },
@ -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 },
@ -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 },

View File

@ -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})

View File

@ -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,

View File

@ -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,

View File

@ -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);

View File

@ -1,42 +1,37 @@
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 { 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";
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<string | null> {
return new Promise<string | null>((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,14 +52,25 @@ export function getDailyRunStarters(seed: string): Starter[] {
seed,
);
return starters;
setDailyRunEventStarterMovesets(seed, starters as StarterTuple);
return starters as StarterTuple;
}
function getDailyRunStarter(starterSpeciesForm: PokemonSpeciesForm, startingLevel: number): Starter {
// TODO: Refactor this unmaintainable mess
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 != null,
variant,
);
const starter: Starter = {
speciesId: starterSpecies.speciesId,
shiny: pokemon.shiny,
@ -169,30 +175,179 @@ 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;
/**
* 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}))?/;
/**
* 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;
}
}
/** The regex literal string used to extract the content of the "starters" block of Daily Run custom seeds. */
const STARTER_SEED_PREFIX_REGEX = /\/starters(.*?)(?:\/|$)/;
/**
* 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(?<species>\d{4}))(?:f(?<form>\d{2}))?(?:v(?<variant>\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 it did not match.
*/
// TODO: Rework this setup into JSON or similar - this is quite hard to maintain
function getDailyEventSeedStarters(seed: string): StarterTuple | null {
if (!isDailyEventSeed(seed)) {
return null;
}
const seedAfterPrefix = seed.split(STARTER_SEED_PREFIX_REGEX)[1] as string | undefined;
if (!seedAfterPrefix) {
return null;
}
const speciesConfigurations = [...seedAfterPrefix.matchAll(STARTER_SEED_MATCH_REGEX)];
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) {
return legacyStarters;
}
console.error("Invalid starters used for custom daily run seed!", seed);
return null;
}
const speciesIds = getEnumValues(SpeciesId);
const starters: Starter[] = [];
for (const match of speciesConfigurations) {
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);
// 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 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.
*/
export function getDailyEventSeedStarters(seed: string): Starter[] | null {
// TODO: Can be removed after october 31st 2025
function getDailyEventSeedStartersLegacy(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 +357,7 @@ export function getDailyEventSeedStarters(seed: string): Starter[] | null {
starters.push(starter);
}
return starters;
return starters as StarterTuple;
}
/**
@ -233,6 +388,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.

View File

@ -98,8 +98,10 @@ 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";
import { MovePriorityInBracket } from "#enums/move-priority-in-bracket";
/**
* A function used to conditionally determine execution of a given {@linkcode MoveAttr}.
@ -1031,8 +1033,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;
@ -1058,17 +1061,21 @@ 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) {
if (user.getTag(BattlerTagType.BYPASS_SPEED)) {
return MovePriorityInBracket.FIRST;
}
const modifierHolder = new NumberHolder(MovePriorityInBracket.NORMAL);
applyAbAttrs("ChangeMovePriorityInBracketAbAttr", { pokemon: user, simulated, move: this, priority: modifierHolder });
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
@ -6218,8 +6225,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 +8165,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 }));

View File

@ -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: [

View File

@ -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([

View File

@ -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: [

View File

@ -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

View File

@ -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(

View File

@ -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`;
}

View File

@ -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",

View File

@ -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() {

View File

@ -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();

View File

@ -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",

View File

@ -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;

View File

@ -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.

View File

@ -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())
);
}

View File

@ -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,
@ -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,
@ -520,7 +520,6 @@ const SLOT_5_FINAL = [
SpeciesId.DRAGAPULT,
SpeciesId.KINGAMBIT,
SpeciesId.BAXCALIBUR,
SpeciesId.GHOLDENGO,
SpeciesId.ARCHALUDON,
SpeciesId.HYDRAPPLE,
SpeciesId.HISUI_GOODRA,

View File

@ -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;
}

View File

@ -0,0 +1,13 @@
import type { ObjectValues } from "#types/type-helpers";
/**
* Enum representing modifiers for Move priorities.
*/
export const MovePriorityInBracket = Object.freeze({
/** Used when moves go last in their priority bracket, but before moves of lower priority. */
LAST: 0,
NORMAL: 1,
/** Used when moves go first in their priority bracket, but before moves of lower priority. */
FIRST: 2,
});
export type MovePriorityInBracket = ObjectValues<typeof MovePriorityInBracket>;

View File

@ -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;
@ -248,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) {
@ -358,15 +345,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 +360,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 +372,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 +437,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;
}

View File

@ -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 {
@ -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";
@ -173,6 +172,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 +2347,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 +2467,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 +2475,7 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
cancelled: cancelledHolder,
simulated,
});
});
}
}
}
@ -2904,12 +2902,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 {
@ -2933,11 +2934,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) {
@ -2947,6 +2953,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;
}
@ -3243,7 +3253,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 +3263,13 @@ export abstract class Pokemon extends Phaser.GameObjects.Container {
);
}
/**
* @returns A generator of pokemon that oppose this one in speed order
*/
public getOpponentsGenerator(): Generator<Pokemon, number> {
return inSpeedOrder(this.isPlayer() ? ArenaTagSide.ENEMY : ArenaTagSide.PLAYER);
}
getOpponentDescriptor(): string {
return this.isPlayer() ? i18next.t("arenaTag:opposingTeam") : i18next.t("arenaTag:yourTeam");
}
@ -3262,12 +3279,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<Pokemon, number> {
return inSpeedOrder(this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY);
}
/**
@ -4020,16 +4035,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 +4077,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 +4825,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,
@ -5104,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();
}
@ -5619,10 +5631,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();
@ -5845,19 +5858,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);
});
}
/**
@ -6363,8 +6384,15 @@ export class EnemyPokemon extends Pokemon {
this.initShinySparkle();
}
const eventBossVariant = getDailyEventSeedBossVariant(globalScene.seed);
const eventBossVariantEnabled =
eventBossVariant != null && globalScene.gameMode.isWaveFinal(globalScene.currentBattle.waveIndex);
if (eventBossVariantEnabled) {
this.shiny = true;
}
if (this.shiny) {
this.variant = this.generateShinyVariant();
this.variant = eventBossVariantEnabled ? eventBossVariant : this.generateShinyVariant();
if (Overrides.ENEMY_VARIANT_OVERRIDE !== null) {
this.variant = Overrides.ENEMY_VARIANT_OVERRIDE;
}

View File

@ -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;

View File

@ -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;
});

View File

@ -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());
}
}

View File

@ -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) {

View File

@ -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);
}
}

View File

@ -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 {
@ -284,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", {
@ -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 });
});
}
}
}

View File

@ -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);

View File

@ -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 });
}

View File

@ -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;
}

View File

@ -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 });
}
}

View File

@ -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);

View File

@ -1,10 +1,12 @@
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";
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";
@ -217,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<void>[] = [];
for (const starter of starters) {
@ -236,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());
}
@ -259,6 +267,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(() => {
@ -275,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);

View File

@ -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);
}

View File

@ -92,11 +92,18 @@ export class MovePhasePriorityQueue extends PokemonPhasePriorityQueue<MovePhase>
});
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];
});
}

View File

@ -11,7 +11,7 @@ import { sortInSpeedOrder } from "#app/utils/speed-order";
*/
export class PostSummonPhasePriorityQueue extends PokemonPhasePriorityQueue<PostSummonPhase> {
protected override reorder(): void {
this.queue = sortInSpeedOrder(this.queue, false);
this.queue = sortInSpeedOrder(this.queue);
this.queue.sort((phaseA, phaseB) => phaseB.getPriority() - phaseA.getPriority());
}

View File

@ -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

View File

@ -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
}
}

View File

@ -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;
@ -75,6 +77,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 +390,50 @@ const timedEvents: readonly TimedEvent[] = [
{ wave: 8, type: "CATCHING_CHARM" },
{ wave: 25, type: "SHINY_CHARM" },
],
dailyRunStartingItems: ["SHINY_CHARM", "ABILITY_CHARM"],
},
{
name: "Halloween 25",
eventType: EventType.SHINY,
startDate: new Date(Date.UTC(2025, 9, 30)),
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", "da", "ru"],
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"],
},
];
@ -448,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}
@ -566,6 +630,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 {

View File

@ -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,22 @@ 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));
// Classic win count (always 0 for evolutions)
const classicWinCount = globalScene.gameData.starterData[species.speciesId]?.classicWinCount ?? 0;
for (const ribbon of availableOrderedRibbons) {
// 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;
}

View File

@ -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);
}

View File

@ -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 {

View File

@ -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;
}

View File

@ -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;

View File

@ -155,6 +155,7 @@ const languageSettings: { [key: string]: LanguageSetting } = {
tr: {
starterInfoTextSize: "56px",
instructionTextSize: "38px",
starterInfoXPos: 34,
},
ro: {
starterInfoTextSize: "56px",

View File

@ -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;

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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);
@ -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,
];

View File

@ -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";
@ -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<T extends Pokemon | hasPokemon>(pokemonList: T[], shuffleFirst = true): T[] {
if (shuffleFirst) {
shufflePokemonList(pokemonList);
}
sortBySpeed(pokemonList);
return pokemonList;
export function sortInSpeedOrder<T extends Pokemon | hasPokemon>(pokemonList: T[]): T[] {
const grouped = groupPokemon(pokemonList);
shufflePokemonList(grouped);
sortBySpeed(grouped);
return grouped.flat();
}
/**
@ -28,7 +26,7 @@ export function sortInSpeedOrder<T extends Pokemon | hasPokemon>(pokemonList: T[
* @param pokemonList - The array of Pokemon or objects containing Pokemon
* @returns The same array instance that was passed in, shuffled.
*/
function shufflePokemonList<T extends Pokemon | hasPokemon>(pokemonList: T[]): T[] {
function shufflePokemonList<T extends Pokemon | hasPokemon>(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,14 +34,22 @@ function shufflePokemonList<T extends Pokemon | hasPokemon>(pokemonList: T[]): T
globalScene.currentBattle.turn * 1000 + pokemonList.length,
globalScene.waveSeed,
);
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";
}
function getPokemon(p: Pokemon | hasPokemon): Pokemon {
return isPokemon(p) ? p : p.getPokemon();
}
/** Sorts an array of {@linkcode Pokemon} by speed (without shuffling) */
function sortBySpeed<T extends Pokemon | hasPokemon>(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);
function sortBySpeed<T extends Pokemon | hasPokemon>(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;
});
@ -52,6 +58,21 @@ function sortBySpeed<T extends Pokemon | hasPokemon>(pokemonList: T[]): void {
const speedReversed = new BooleanHolder(false);
globalScene.arena.applyTags(ArenaTagType.TRICK_ROOM, speedReversed);
if (speedReversed.value) {
pokemonList.reverse();
groupedPokemonList.reverse();
}
}
function groupPokemon<T extends Pokemon | hasPokemon>(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;
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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();

View File

@ -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,8 @@ describe("Daily Mode", () => {
beforeEach(() => {
game = new GameManager(phaserGame);
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("test-seed");
game.override.disableShinies = false;
});
afterEach(() => {
@ -28,6 +30,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 +39,90 @@ 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", () => {
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(),
]);
});
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]);
});
});
describe("Starters", () => {
it("should support custom species IDs", async () => {
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("foo/starterss0001s0113s1024");
await game.dailyMode.startBattle();
const party = game.scene.getPlayerParty().map(p => p.species.speciesId);
expect(party, stringifyEnumArray(SpeciesId, party)).toEqual([
SpeciesId.BULBASAUR,
SpeciesId.CHANSEY,
SpeciesId.TERAPAGOS,
]);
});
it("should support custom forms and variants", async () => {
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("/starterss0006f01v2s0113v0s1024f02");
await game.dailyMode.startBattle();
const party = game.scene.getPlayerParty().map(p => ({
speciesId: p.species.speciesId,
variant: p.getVariant(),
form: p.formIndex,
shiny: p.isShiny(),
}));
expect(party).toEqual<typeof party>([
{ 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 },
]);
});
});
});
});

View File

@ -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();
});
});
});

View File

@ -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", () => {

View File

@ -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");

View File

@ -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);
});
});