Merge remote-tracking branch 'upstream/beta' into waveData

This commit is contained in:
Bertie690 2025-04-20 17:37:28 -04:00
commit c3db9e3532
577 changed files with 2729 additions and 2302 deletions

View File

@ -37,7 +37,7 @@ jobs:
- name: Setup Node 22.14.1 - name: Setup Node 22.14.1
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: 22 node-version-file: "pokerogue_docs/.nvmrc"
- name: Checkout repository for Github Pages - name: Checkout repository for Github Pages
if: github.event_name == 'push' if: github.event_name == 'push'

View File

@ -1,7 +1,7 @@
import { pokerogueApi } from "#app/plugins/api/pokerogue-api"; import { pokerogueApi } from "#app/plugins/api/pokerogue-api";
import type { UserInfo } from "#app/@types/UserInfo"; import type { UserInfo } from "#app/@types/UserInfo";
import { bypassLogin } from "#app/battle-scene"; import { bypassLogin } from "./global-vars/bypass-login";
import { randomString } from "#app/utils"; import { randomString } from "#app/utils/common";
export let loggedInUser: UserInfo | null = null; export let loggedInUser: UserInfo | null = null;
// This is a random string that is used to identify the client session - unique per session (tab or window) so that the game will only save on the one that the server is expecting // This is a random string that is used to identify the client session - unique per session (tab or window) so that the game will only save on the one that the server is expecting

View File

@ -18,7 +18,7 @@ import {
isNullOrUndefined, isNullOrUndefined,
BooleanHolder, BooleanHolder,
type Constructor, type Constructor,
} from "#app/utils"; } from "#app/utils/common";
import type { Modifier, ModifierPredicate, TurnHeldItemTransferModifier } from "./modifier/modifier"; import type { Modifier, ModifierPredicate, TurnHeldItemTransferModifier } from "./modifier/modifier";
import { import {
ConsumableModifier, ConsumableModifier,
@ -77,7 +77,8 @@ import {
} from "#app/data/abilities/ability"; } from "#app/data/abilities/ability";
import { allAbilities } from "./data/data-lists"; import { allAbilities } from "./data/data-lists";
import type { FixedBattleConfig } from "#app/battle"; import type { FixedBattleConfig } from "#app/battle";
import Battle, { BattleType } from "#app/battle"; import Battle from "#app/battle";
import { BattleType } from "#enums/battle-type";
import type { GameMode } from "#app/game-mode"; import type { GameMode } from "#app/game-mode";
import { GameModes, getGameMode } from "#app/game-mode"; import { GameModes, getGameMode } from "#app/game-mode";
import FieldSpritePipeline from "#app/pipelines/field-sprite"; import FieldSpritePipeline from "#app/pipelines/field-sprite";
@ -184,8 +185,8 @@ import { HideAbilityPhase } from "#app/phases/hide-ability-phase";
import { expSpriteKeys } from "./sprites/sprite-keys"; import { expSpriteKeys } from "./sprites/sprite-keys";
import { hasExpSprite } from "./sprites/sprite-utils"; import { hasExpSprite } from "./sprites/sprite-utils";
import { timedEventManager } from "./global-event-manager"; import { timedEventManager } from "./global-event-manager";
import { starterColors } from "./global-vars/starter-colors";
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; import { startingWave } from "./starting-wave";
const DEBUG_RNG = false; const DEBUG_RNG = false;
@ -193,13 +194,6 @@ const OPP_IVS_OVERRIDE_VALIDATED: number[] = (
Array.isArray(Overrides.OPP_IVS_OVERRIDE) ? Overrides.OPP_IVS_OVERRIDE : new Array(6).fill(Overrides.OPP_IVS_OVERRIDE) Array.isArray(Overrides.OPP_IVS_OVERRIDE) ? Overrides.OPP_IVS_OVERRIDE : new Array(6).fill(Overrides.OPP_IVS_OVERRIDE)
).map(iv => (Number.isNaN(iv) || iv === null || iv > 31 ? -1 : iv)); ).map(iv => (Number.isNaN(iv) || iv === null || iv > 31 ? -1 : iv));
export const startingWave = Overrides.STARTING_WAVE_OVERRIDE || 1;
export let starterColors: StarterColors;
interface StarterColors {
[key: string]: [string, string];
}
export interface PokeballCounts { export interface PokeballCounts {
[pb: string]: number; [pb: string]: number;
} }
@ -809,11 +803,11 @@ export default class BattleScene extends SceneBase {
} }
async initStarterColors(): Promise<void> { async initStarterColors(): Promise<void> {
if (starterColors) { if (Object.keys(starterColors).length > 0) {
// already initialized
return; return;
} }
const sc = await this.cachedFetch("./starter-colors.json").then(res => res.json()); const sc = await this.cachedFetch("./starter-colors.json").then(res => res.json());
starterColors = {};
for (const key of Object.keys(sc)) { for (const key of Object.keys(sc)) {
starterColors[key] = sc[key]; starterColors[key] = sc[key];
} }
@ -1338,22 +1332,27 @@ export default class BattleScene extends SceneBase {
} else { } else {
if ( if (
!this.gameMode.hasTrainers || !this.gameMode.hasTrainers ||
Overrides.BATTLE_TYPE_OVERRIDE === BattleType.WILD ||
(Overrides.DISABLE_STANDARD_TRAINERS_OVERRIDE && isNullOrUndefined(trainerData)) (Overrides.DISABLE_STANDARD_TRAINERS_OVERRIDE && isNullOrUndefined(trainerData))
) { ) {
newBattleType = BattleType.WILD; newBattleType = BattleType.WILD;
} else if (battleType === undefined) {
newBattleType = this.gameMode.isWaveTrainer(newWaveIndex, this.arena) ? BattleType.TRAINER : BattleType.WILD;
} else { } else {
newBattleType = battleType; newBattleType =
Overrides.BATTLE_TYPE_OVERRIDE ??
battleType ??
(this.gameMode.isWaveTrainer(newWaveIndex, this.arena) ? BattleType.TRAINER : BattleType.WILD);
} }
if (newBattleType === BattleType.TRAINER) { if (newBattleType === BattleType.TRAINER) {
const trainerType = this.arena.randomTrainerType(newWaveIndex); const trainerType =
Overrides.RANDOM_TRAINER_OVERRIDE?.trainerType ?? this.arena.randomTrainerType(newWaveIndex);
let doubleTrainer = false; let doubleTrainer = false;
if (trainerConfigs[trainerType].doubleOnly) { if (trainerConfigs[trainerType].doubleOnly) {
doubleTrainer = true; doubleTrainer = true;
} else if (trainerConfigs[trainerType].hasDouble) { } else if (trainerConfigs[trainerType].hasDouble) {
doubleTrainer = !randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField)); doubleTrainer =
Overrides.RANDOM_TRAINER_OVERRIDE?.alwaysDouble ||
!randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField));
// Add a check that special trainers can't be double except for tate and liza - they should use the normal double chance // Add a check that special trainers can't be double except for tate and liza - they should use the normal double chance
if ( if (
trainerConfigs[trainerType].trainerTypeDouble && trainerConfigs[trainerType].trainerTypeDouble &&
@ -1373,7 +1372,10 @@ export default class BattleScene extends SceneBase {
// Check for mystery encounter // Check for mystery encounter
// Can only occur in place of a standard (non-boss) wild battle, waves 10-180 // Can only occur in place of a standard (non-boss) wild battle, waves 10-180
if (this.isWaveMysteryEncounter(newBattleType, newWaveIndex) || newBattleType === BattleType.MYSTERY_ENCOUNTER) { if (
!Overrides.BATTLE_TYPE_OVERRIDE &&
(this.isWaveMysteryEncounter(newBattleType, newWaveIndex) || newBattleType === BattleType.MYSTERY_ENCOUNTER)
) {
newBattleType = BattleType.MYSTERY_ENCOUNTER; newBattleType = BattleType.MYSTERY_ENCOUNTER;
// Reset to base spawn weight // Reset to base spawn weight
this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT; this.mysteryEncounterSaveData.encounterSpawnChance = BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT;
@ -1383,9 +1385,9 @@ export default class BattleScene extends SceneBase {
if (double === undefined && newWaveIndex > 1) { if (double === undefined && newWaveIndex > 1) {
if (newBattleType === BattleType.WILD && !this.gameMode.isWaveFinal(newWaveIndex)) { if (newBattleType === BattleType.WILD && !this.gameMode.isWaveFinal(newWaveIndex)) {
newDouble = !randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField)); newDouble = !randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField));
} else if (newBattleType === BattleType.TRAINER) {
newDouble = newTrainer?.variant === TrainerVariant.DOUBLE;
} }
} else if (double === undefined && newBattleType === BattleType.TRAINER) {
newDouble = newTrainer?.variant === TrainerVariant.DOUBLE;
} else if (!battleConfig) { } else if (!battleConfig) {
newDouble = !!double; newDouble = !!double;
} }
@ -1395,10 +1397,10 @@ export default class BattleScene extends SceneBase {
newDouble = false; newDouble = false;
} }
if (!isNullOrUndefined(Overrides.BATTLE_TYPE_OVERRIDE)) { if (!isNullOrUndefined(Overrides.BATTLE_STYLE_OVERRIDE)) {
let doubleOverrideForWave: "single" | "double" | null = null; let doubleOverrideForWave: "single" | "double" | null = null;
switch (Overrides.BATTLE_TYPE_OVERRIDE) { switch (Overrides.BATTLE_STYLE_OVERRIDE) {
case "double": case "double":
doubleOverrideForWave = "double"; doubleOverrideForWave = "double";
break; break;
@ -1418,7 +1420,7 @@ export default class BattleScene extends SceneBase {
} }
/** /**
* Override battles into single only if not fighting with trainers. * Override battles into single only if not fighting with trainers.
* @see {@link https://github.com/pagefaultgames/pokerogue/issues/1948 | GitHub Issue #1948} * @see {@link https://github.com/pagefaultgames/pokerogue/issues/1948 GitHub Issue #1948}
*/ */
if (newBattleType !== BattleType.TRAINER && doubleOverrideForWave === "single") { if (newBattleType !== BattleType.TRAINER && doubleOverrideForWave === "single") {
newDouble = false; newDouble = false;

View File

@ -8,7 +8,7 @@ import {
shiftCharCodes, shiftCharCodes,
randSeedItem, randSeedItem,
randInt, randInt,
} from "#app/utils"; } from "#app/utils/common";
import Trainer, { TrainerVariant } from "./field/trainer"; import Trainer, { TrainerVariant } from "./field/trainer";
import type { GameMode } from "./game-mode"; import type { GameMode } from "./game-mode";
import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier";
@ -30,6 +30,7 @@ import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import type { CustomModifierSettings } from "#app/modifier/modifier-type"; import type { CustomModifierSettings } from "#app/modifier/modifier-type";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { BattleType } from "#enums/battle-type";
export enum ClassicFixedBossWaves { export enum ClassicFixedBossWaves {
TOWN_YOUNGSTER = 5, TOWN_YOUNGSTER = 5,
@ -54,13 +55,6 @@ export enum ClassicFixedBossWaves {
RIVAL_6 = 195, RIVAL_6 = 195,
} }
export enum BattleType {
WILD,
TRAINER,
CLEAR,
MYSTERY_ENCOUNTER,
}
export enum BattlerIndex { export enum BattlerIndex {
ATTACKER = -1, ATTACKER = -1,
PLAYER, PLAYER,

View File

@ -1,6 +1,6 @@
import type { AbAttrCondition } from "#app/@types/ability-types"; import type { AbAttrCondition } from "#app/@types/ability-types";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import type * as Utils from "#app/utils"; import type { BooleanHolder } from "#app/utils/common";
export abstract class AbAttr { export abstract class AbAttr {
public showAbility: boolean; public showAbility: boolean;
@ -22,7 +22,7 @@ export abstract class AbAttr {
_pokemon: Pokemon, _pokemon: Pokemon,
_passive: boolean, _passive: boolean,
_simulated: boolean, _simulated: boolean,
_cancelled: Utils.BooleanHolder | null, _cancelled: BooleanHolder | null,
_args: any[], _args: any[],
): void {} ): void {}

View File

@ -3,7 +3,7 @@ import type { AbAttrCondition } from "#app/@types/ability-types";
import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr"; import type { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr";
import i18next from "i18next"; import i18next from "i18next";
import type { Localizable } from "#app/interfaces/locales"; import type { Localizable } from "#app/interfaces/locales";
import type { Constructor } from "#app/utils"; import type { Constructor } from "#app/utils/common";
export class Ability implements Localizable { export class Ability implements Localizable {
public id: Abilities; public id: Abilities;

View File

@ -1,5 +1,5 @@
import { HitResult, MoveResult, PlayerPokemon } from "#app/field/pokemon"; import { HitResult, MoveResult, PlayerPokemon } from "#app/field/pokemon";
import { BooleanHolder, NumberHolder, toDmgValue, isNullOrUndefined, randSeedItem, randSeedInt, type Constructor } from "#app/utils"; import { BooleanHolder, NumberHolder, toDmgValue, isNullOrUndefined, randSeedItem, randSeedInt, type Constructor } from "#app/utils/common";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { BattlerTagLapseType, GroundedTag } from "#app/data/battler-tags"; import { BattlerTagLapseType, GroundedTag } from "#app/data/battler-tags";
import { getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "#app/data/status-effect"; import { getNonVolatileStatusEffects, getStatusEffectDescriptor, getStatusEffectHealText } from "#app/data/status-effect";
@ -30,7 +30,7 @@ import i18next from "i18next";
import { Command } from "#app/ui/command-ui-handler"; import { Command } from "#app/ui/command-ui-handler";
import { BerryModifierType } from "#app/modifier/modifier-type"; import { BerryModifierType } from "#app/modifier/modifier-type";
import { getPokeballName } from "#app/data/pokeball"; import { getPokeballName } from "#app/data/pokeball";
import { BattleType } from "#app/battle"; import { BattleType } from "#enums/battle-type";
import { MovePhase } from "#app/phases/move-phase"; import { MovePhase } from "#app/phases/move-phase";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
@ -44,6 +44,7 @@ import { PokemonTransformPhase } from "#app/phases/pokemon-transform-phase";
import { allAbilities } from "#app/data/data-lists"; import { allAbilities } from "#app/data/data-lists";
import { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr"; import { AbAttr } from "#app/data/abilities/ab-attrs/ab-attr";
import { Ability } from "#app/data/abilities/ability-class"; import { Ability } from "#app/data/abilities/ability-class";
import { TrainerVariant } from "#app/field/trainer";
// Enum imports // Enum imports
import { Stat, type BattleStat , BATTLE_STATS, EFFECTIVE_STATS, getStatKey, type EffectiveStat } from "#enums/stat"; import { Stat, type BattleStat , BATTLE_STATS, EFFECTIVE_STATS, getStatKey, type EffectiveStat } from "#enums/stat";
@ -66,6 +67,7 @@ import { CommonAnim } from "../battle-anims";
import { getBerryEffectFunc } from "../berry"; import { getBerryEffectFunc } from "../berry";
import { BerryUsedEvent } from "#app/events/battle-scene"; import { BerryUsedEvent } from "#app/events/battle-scene";
// Type imports // Type imports
import type { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import type { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
@ -2222,18 +2224,6 @@ export class PostSummonMessageAbAttr extends PostSummonAbAttr {
} }
} }
/**
* Removes illusions when a Pokemon is summoned.
*/
export class PostSummonRemoveIllusionAbAttr extends PostSummonAbAttr {
applyPostSummon(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): boolean {
for (const pokemon of globalScene.getField(true)) {
pokemon.breakIllusion();
}
return true;
}
}
export class PostSummonUnnamedMessageAbAttr extends PostSummonAbAttr { export class PostSummonUnnamedMessageAbAttr extends PostSummonAbAttr {
//Attr doesn't force pokemon name on the message //Attr doesn't force pokemon name on the message
private message: string; private message: string;
@ -4038,7 +4028,9 @@ export class PostTurnResetStatusAbAttr extends PostTurnAbAttr {
} else { } else {
this.target = pokemon; this.target = pokemon;
} }
return !isNullOrUndefined(this.target?.status);
const effect = this.target?.status?.effect;
return !!effect && effect !== StatusEffect.FAINT;
} }
override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void { override applyPostTurn(pokemon: Pokemon, passive: boolean, simulated: boolean, args: any[]): void {
@ -5265,7 +5257,14 @@ export class IllusionPreSummonAbAttr extends PreSummonAbAttr {
} }
} }
export class IllusionBreakAbAttr extends PostDefendAbAttr { export class IllusionBreakAbAttr extends AbAttr {
override apply(pokemon: Pokemon, _passive: boolean, _simulated: boolean, _cancelled: BooleanHolder | null, _args: any[]): void {
pokemon.breakIllusion();
pokemon.summonData.illusionBroken = true;
}
}
export class PostDefendIllusionBreakAbAttr extends PostDefendAbAttr {
/** /**
* Destroy the illusion upon taking damage * Destroy the illusion upon taking damage
* *
@ -5613,8 +5612,8 @@ class ForceSwitchOutHelper {
const party = player ? globalScene.getPlayerParty() : globalScene.getEnemyParty(); const party = player ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
return (!player && globalScene.currentBattle.battleType === BattleType.WILD) return (!player && globalScene.currentBattle.battleType === BattleType.WILD)
|| party.filter(p => p.isAllowedInBattle() || party.filter(p => p.isAllowedInBattle() && !p.isOnField()
&& (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > globalScene.currentBattle.getBattlerCount(); && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > 0;
} }
/** /**
@ -6354,7 +6353,7 @@ export function applyOnGainAbAttrs(
} }
/** /**
* Clears primal weather/neutralizing gas during the turn if {@linkcode pokemon}'s ability corresponds to one * Applies ability attributes which activate when the ability is lost or suppressed (i.e. primal weather)
*/ */
export function applyOnLoseAbAttrs(pokemon: Pokemon, passive = false, simulated = false, ...args: any[]): void { export function applyOnLoseAbAttrs(pokemon: Pokemon, passive = false, simulated = false, ...args: any[]): void {
applySingleAbAttrs<PreLeaveFieldAbAttr>( applySingleAbAttrs<PreLeaveFieldAbAttr>(
@ -6366,6 +6365,17 @@ export function applyOnLoseAbAttrs(pokemon: Pokemon, passive = false, simulated
args, args,
true, true,
simulated); simulated);
applySingleAbAttrs<IllusionBreakAbAttr>(
pokemon,
passive,
IllusionBreakAbAttr,
(attr, passive) => attr.apply(pokemon, passive, simulated, null, args),
(attr, passive) => attr.canApply(pokemon, passive, simulated, args),
args,
true,
simulated
)
} }
/** /**
@ -6785,11 +6795,11 @@ export function initAbilities() {
new Ability(Abilities.BAD_DREAMS, 4) new Ability(Abilities.BAD_DREAMS, 4)
.attr(PostTurnHurtIfSleepingAbAttr), .attr(PostTurnHurtIfSleepingAbAttr),
new Ability(Abilities.PICKPOCKET, 5) new Ability(Abilities.PICKPOCKET, 5)
.attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT)) .attr(PostDefendStealHeldItemAbAttr, (target, user, move) => move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user, target}))
.condition(getSheerForceHitDisableAbCondition()), .condition(getSheerForceHitDisableAbCondition()),
new Ability(Abilities.SHEER_FORCE, 5) new Ability(Abilities.SHEER_FORCE, 5)
.attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 5461 / 4096) .attr(MovePowerBoostAbAttr, (user, target, move) => move.chance >= 1, 1.3)
.attr(MoveEffectChanceMultiplierAbAttr, 0), // Should disable life orb, eject button, red card, kee/maranga berry if they get implemented .attr(MoveEffectChanceMultiplierAbAttr, 0), // This attribute does not seem to function - Should disable life orb, eject button, red card, kee/maranga berry if they get implemented
new Ability(Abilities.CONTRARY, 5) new Ability(Abilities.CONTRARY, 5)
.attr(StatStageChangeMultiplierAbAttr, -1) .attr(StatStageChangeMultiplierAbAttr, -1)
.ignorable(), .ignorable(),
@ -6861,11 +6871,12 @@ export function initAbilities() {
return isNullOrUndefined(movePhase); return isNullOrUndefined(movePhase);
}, 1.3), }, 1.3),
new Ability(Abilities.ILLUSION, 5) new Ability(Abilities.ILLUSION, 5)
//The pokemon generate an illusion if it's available // The Pokemon generate an illusion if it's available
.attr(IllusionPreSummonAbAttr, false) .attr(IllusionPreSummonAbAttr, false)
//The pokemon loses his illusion when he is damaged by a move .attr(IllusionBreakAbAttr)
.attr(IllusionBreakAbAttr, true) // The Pokemon loses its illusion when damaged by a move
//Illusion is available again after a battle .attr(PostDefendIllusionBreakAbAttr, true)
// Illusion is available again after a battle
.conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false) .conditionalAttr((pokemon) => pokemon.isAllowedInBattle(), IllusionPostBattleAbAttr, false)
.uncopiable() .uncopiable()
.bypassFaint(), .bypassFaint(),
@ -7134,7 +7145,7 @@ export function initAbilities() {
new Ability(Abilities.BATTERY, 7) new Ability(Abilities.BATTERY, 7)
.attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL ], 1.3), .attr(AllyMoveCategoryPowerBoostAbAttr, [ MoveCategory.SPECIAL ], 1.3),
new Ability(Abilities.FLUFFY, 7) new Ability(Abilities.FLUFFY, 7)
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), 0.5) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user, target}), 0.5)
.attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => user.getMoveType(move) === PokemonType.FIRE, 2) .attr(ReceivedMoveDamageMultiplierAbAttr, (target, user, move) => user.getMoveType(move) === PokemonType.FIRE, 2)
.ignorable(), .ignorable(),
new Ability(Abilities.DAZZLING, 7) new Ability(Abilities.DAZZLING, 7)
@ -7143,7 +7154,7 @@ export function initAbilities() {
new Ability(Abilities.SOUL_HEART, 7) new Ability(Abilities.SOUL_HEART, 7)
.attr(PostKnockOutStatStageChangeAbAttr, Stat.SPATK, 1), .attr(PostKnockOutStatStageChangeAbAttr, Stat.SPATK, 1),
new Ability(Abilities.TANGLING_HAIR, 7) new Ability(Abilities.TANGLING_HAIR, 7)
.attr(PostDefendStatStageChangeAbAttr, (target, user, move) => move.hasFlag(MoveFlags.MAKES_CONTACT), Stat.SPD, -1, false), .attr(PostDefendStatStageChangeAbAttr, (target, user, move) => move.doesFlagEffectApply({flag: MoveFlags.MAKES_CONTACT, user, target}), Stat.SPD, -1, false),
new Ability(Abilities.RECEIVER, 7) new Ability(Abilities.RECEIVER, 7)
.attr(CopyFaintedAllyAbilityAbAttr) .attr(CopyFaintedAllyAbilityAbAttr)
.uncopiable(), .uncopiable(),
@ -7279,8 +7290,6 @@ export function initAbilities() {
.attr(PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr) .attr(PreLeaveFieldRemoveSuppressAbilitiesSourceAbAttr)
.uncopiable() .uncopiable()
.attr(NoTransformAbilityAbAttr) .attr(NoTransformAbilityAbAttr)
.attr(PostSummonMessageAbAttr, (pokemon: Pokemon) => i18next.t("abilityTriggers:postSummonNeutralizingGas", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon) }))
.attr(PostSummonRemoveIllusionAbAttr)
.bypassFaint(), .bypassFaint(),
new Ability(Abilities.PASTEL_VEIL, 8) new Ability(Abilities.PASTEL_VEIL, 8)
.attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC) .attr(PostSummonUserFieldRemoveStatusEffectAbAttr, StatusEffect.POISON, StatusEffect.TOXIC)

View File

@ -1,7 +1,7 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type { Arena } from "#app/field/arena"; import type { Arena } from "#app/field/arena";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import { BooleanHolder, NumberHolder, toDmgValue } from "#app/utils"; import { BooleanHolder, NumberHolder, toDmgValue } from "#app/utils/common";
import { allMoves } from "#app/data/moves/move"; import { allMoves } from "#app/data/moves/move";
import { MoveTarget } from "#enums/MoveTarget"; import { MoveTarget } from "#enums/MoveTarget";
import { MoveCategory } from "#enums/MoveCategory"; import { MoveCategory } from "#enums/MoveCategory";

View File

@ -1,5 +1,5 @@
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import { randSeedInt, getEnumValues } from "#app/utils"; import { randSeedInt, getEnumValues } from "#app/utils/common";
import type { SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions"; import type { SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -1,5 +1,5 @@
import { allMoves } from "#app/data/moves/move"; import { allMoves } from "#app/data/moves/move";
import { getEnumKeys, getEnumValues } from "#app/utils"; import { getEnumKeys, getEnumValues } from "#app/utils/common";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";

View File

@ -3,7 +3,7 @@ import { Gender } from "#app/data/gender";
import { PokeballType } from "#enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
@ -14,6 +14,7 @@ import { DamageMoneyRewardModifier, ExtraModifierModifier, MoneyMultiplierModifi
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
import { speciesStarterCosts } from "./starters"; import { speciesStarterCosts } from "./starters";
import i18next from "i18next"; import i18next from "i18next";
import { initI18n } from "#app/plugins/i18n";
export enum SpeciesWildEvolutionDelay { export enum SpeciesWildEvolutionDelay {
@ -95,6 +96,9 @@ export class SpeciesFormEvolution {
public description = ""; public description = "";
constructor(speciesId: Species, preFormKey: string | null, evoFormKey: string | null, level: number, item: EvolutionItem | null, condition: SpeciesEvolutionCondition | null, wildDelay?: SpeciesWildEvolutionDelay) { constructor(speciesId: Species, preFormKey: string | null, evoFormKey: string | null, level: number, item: EvolutionItem | null, condition: SpeciesEvolutionCondition | null, wildDelay?: SpeciesWildEvolutionDelay) {
if (!i18next.isInitialized) {
initI18n();
}
this.speciesId = speciesId; this.speciesId = speciesId;
this.preFormKey = preFormKey; this.preFormKey = preFormKey;
this.evoFormKey = evoFormKey; this.evoFormKey = evoFormKey;

View File

@ -11,87 +11,87 @@ export type SignatureSpecies = {
*/ */
export const signatureSpecies: SignatureSpecies = { export const signatureSpecies: SignatureSpecies = {
// Gym Leaders- Kanto // Gym Leaders- Kanto
BROCK: [Species.GEODUDE, Species.ONIX], BROCK: [Species.ONIX, Species.GEODUDE, [Species.OMANYTE, Species.KABUTO], Species.AERODACTYL],
MISTY: [Species.STARYU, Species.PSYDUCK], MISTY: [Species.STARYU, Species.PSYDUCK, Species.WOOPER, Species.LAPRAS],
LT_SURGE: [Species.VOLTORB, Species.PIKACHU, Species.ELECTABUZZ], LT_SURGE: [Species.PICHU, Species.VOLTORB, Species.ELEKID, Species.JOLTEON],
ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP], ERIKA: [Species.ODDISH, Species.BELLSPROUT, Species.TANGELA, Species.HOPPIP],
JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT], JANINE: [Species.VENONAT, Species.SPINARAK, Species.ZUBAT, Species.KOFFING],
SABRINA: [Species.ABRA, Species.MR_MIME, Species.ESPEON], SABRINA: [Species.ABRA, Species.MR_MIME, Species.SMOOCHUM, Species.ESPEON],
BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGMAR], BLAINE: [Species.GROWLITHE, Species.PONYTA, Species.MAGBY, Species.VULPIX],
GIOVANNI: [Species.SANDILE, Species.MURKROW, Species.NIDORAN_M, Species.NIDORAN_F], GIOVANNI: [Species.RHYHORN, Species.MEOWTH, [Species.NIDORAN_F, Species.NIDORAN_M], Species.DIGLETT], // Tera Ground Meowth
// Gym Leaders- Johto // Gym Leaders- Johto
FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.DODUO], FALKNER: [Species.PIDGEY, Species.HOOTHOOT, Species.NATU, Species.MURKROW],
BUGSY: [Species.SCYTHER, Species.HERACROSS, Species.SHUCKLE, Species.PINSIR], BUGSY: [Species.SCYTHER, Species.SHUCKLE, Species.YANMA, [Species.PINSIR, Species.HERACROSS]],
WHITNEY: [Species.JIGGLYPUFF, Species.MILTANK, Species.AIPOM, Species.GIRAFARIG], WHITNEY: [Species.MILTANK, Species.AIPOM, Species.IGGLYBUFF, [Species.GIRAFARIG, Species.STANTLER]],
MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.SABLEYE], MORTY: [Species.GASTLY, Species.MISDREAVUS, Species.DUSKULL, Species.SABLEYE],
CHUCK: [Species.POLIWRATH, Species.MANKEY], CHUCK: [Species.POLIWRATH, Species.MANKEY, Species.TYROGUE, Species.MACHOP],
JASMINE: [Species.MAGNEMITE, Species.STEELIX], JASMINE: [Species.STEELIX, Species.MAGNEMITE, Species.PINECO, Species.SKARMORY],
PRYCE: [Species.SEEL, Species.SWINUB], PRYCE: [Species.SWINUB, Species.SEEL, Species.SHELLDER, Species.SNEASEL],
CLAIR: [Species.DRATINI, Species.HORSEA, Species.GYARADOS], CLAIR: [Species.HORSEA, Species.DRATINI, Species.MAGIKARP, Species.DRUDDIGON], // Tera Dragon Magikarp
// Gym Leaders- Hoenn // Gym Leaders- Hoenn
ROXANNE: [Species.GEODUDE, Species.NOSEPASS], ROXANNE: [Species.NOSEPASS, Species.GEODUDE, [Species.LILEEP, Species.ANORITH], Species.ARON],
BRAWLY: [Species.MACHOP, Species.MAKUHITA], BRAWLY: [Species.MAKUHITA, Species.MACHOP, Species.MEDITITE, Species.SHROOMISH],
WATTSON: [Species.MAGNEMITE, Species.VOLTORB, Species.ELECTRIKE], WATTSON: [Species.ELECTRIKE, Species.VOLTORB, Species.MAGNEMITE, [Species.PLUSLE, Species.MINUN]],
FLANNERY: [Species.SLUGMA, Species.TORKOAL, Species.NUMEL], FLANNERY: [Species.TORKOAL, Species.SLUGMA, Species.NUMEL, Species.HOUNDOUR],
NORMAN: [Species.SLAKOTH, Species.SPINDA, Species.ZIGZAGOON, Species.KECLEON], NORMAN: [Species.SLAKOTH, Species.KECLEON, Species.WHISMUR, Species.ZANGOOSE],
WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY], WINONA: [Species.SWABLU, Species.WINGULL, Species.TROPIUS, Species.SKARMORY],
TATE: [Species.SOLROCK, Species.NATU, Species.CHIMECHO, Species.GALLADE], TATE: [Species.SOLROCK, Species.NATU, Species.CHINGLING, Species.GALLADE],
LIZA: [Species.LUNATONE, Species.SPOINK, Species.BALTOY, Species.GARDEVOIR], LIZA: [Species.LUNATONE, Species.BALTOY, Species.SPOINK, Species.GARDEVOIR],
JUAN: [Species.HORSEA, Species.BARBOACH, Species.SPHEAL, Species.RELICANTH], JUAN: [Species.HORSEA, Species.SPHEAL, Species.BARBOACH, Species.CORPHISH],
// Gym Leaders- Sinnoh // Gym Leaders- Sinnoh
ROARK: [Species.CRANIDOS, Species.LARVITAR, Species.GEODUDE], ROARK: [Species.CRANIDOS, Species.GEODUDE, Species.NOSEPASS, Species.LARVITAR],
GARDENIA: [Species.ROSELIA, Species.TANGELA, Species.TURTWIG], GARDENIA: [Species.BUDEW, Species.CHERUBI, Species.TURTWIG, Species.LEAFEON],
MAYLENE: [Species.LUCARIO, Species.MEDITITE, Species.CHIMCHAR], MAYLENE: [Species.RIOLU, Species.MEDITITE, Species.CHIMCHAR, Species.CROAGUNK],
CRASHER_WAKE: [Species.BUIZEL, Species.WOOPER, Species.PIPLUP, Species.MAGIKARP], CRASHER_WAKE: [Species.BUIZEL, Species.WOOPER, Species.PIPLUP, Species.MAGIKARP],
FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.SPIRITOMB], FANTINA: [Species.MISDREAVUS, Species.DRIFLOON, Species.DUSKULL, Species.SPIRITOMB],
BYRON: [Species.SHIELDON, Species.BRONZOR, Species.AGGRON], BYRON: [Species.SHIELDON, Species.BRONZOR, Species.ARON, Species.SKARMORY],
CANDICE: [Species.SNEASEL, Species.SNOVER, Species.SNORUNT], CANDICE: [Species.FROSLASS, Species.SNOVER, Species.SNEASEL, Species.GLACEON],
VOLKNER: [Species.SHINX, Species.CHINCHOU, Species.ROTOM], VOLKNER: [Species.ELEKID, Species.SHINX, Species.CHINCHOU, Species.ROTOM],
// Gym Leaders- Unova // Gym Leaders- Unova
CILAN: [Species.PANSAGE, Species.FOONGUS, Species.PETILIL], CILAN: [Species.PANSAGE, Species.SNIVY, Species.MARACTUS, Species.FERROSEED],
CHILI: [Species.PANSEAR, Species.DARUMAKA, Species.NUMEL], CHILI: [Species.PANSEAR, Species.TEPIG, Species.HEATMOR, Species.DARUMAKA],
CRESS: [Species.PANPOUR, Species.TYMPOLE, Species.SLOWPOKE], CRESS: [Species.PANPOUR, Species.OSHAWOTT, Species.BASCULIN, Species.TYMPOLE],
CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PIDOVE], CHEREN: [Species.LILLIPUP, Species.MINCCINO, Species.PIDOVE, Species.BOUFFALANT],
LENORA: [Species.PATRAT, Species.DEERLING, Species.AUDINO], LENORA: [Species.PATRAT, Species.DEERLING, Species.AUDINO, Species.BRAVIARY],
ROXIE: [Species.VENIPEDE, Species.TRUBBISH, Species.SKORUPI], ROXIE: [Species.VENIPEDE, Species.KOFFING, Species.TRUBBISH, Species.TOXEL],
BURGH: [Species.SEWADDLE, Species.SHELMET, Species.KARRABLAST], BURGH: [Species.SEWADDLE, Species.DWEBBLE, [Species.KARRABLAST, Species.SHELMET], Species.DURANT],
ELESA: [Species.EMOLGA, Species.BLITZLE, Species.JOLTIK], ELESA: [Species.BLITZLE, Species.EMOLGA, Species.JOLTIK, Species.TYNAMO],
CLAY: [Species.DRILBUR, Species.SANDILE, Species.GOLETT], CLAY: [Species.DRILBUR, Species.SANDILE, Species.TYMPOLE, Species.GOLETT],
SKYLA: [Species.DUCKLETT, Species.WOOBAT, Species.RUFFLET], SKYLA: [Species.DUCKLETT, Species.WOOBAT, [Species.RUFFLET, Species.VULLABY], Species.ARCHEN],
BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO], BRYCEN: [Species.CRYOGONAL, Species.VANILLITE, Species.CUBCHOO, Species.GALAR_DARUMAKA],
DRAYDEN: [Species.DRUDDIGON, Species.AXEW, Species.DEINO], DRAYDEN: [Species.AXEW, Species.DRUDDIGON, Species.TRAPINCH, Species.DEINO],
MARLON: [Species.WAILMER, Species.FRILLISH, Species.TIRTOUGA], MARLON: [Species.FRILLISH, Species.TIRTOUGA, Species.WAILMER, Species.MANTYKE],
// Gym Leaders- Kalos // Gym Leaders- Kalos
VIOLA: [Species.SURSKIT, Species.SCATTERBUG], VIOLA: [Species.SCATTERBUG, Species.SURSKIT, Species.CUTIEFLY, Species.BLIPBUG],
GRANT: [Species.AMAURA, Species.TYRUNT], GRANT: [Species.TYRUNT, Species.AMAURA, Species.BINACLE, Species.DWEBBLE],
KORRINA: [Species.HAWLUCHA, Species.LUCARIO, Species.MIENFOO], KORRINA: [Species.RIOLU, Species.MIENFOO, Species.HAWLUCHA, Species.PANCHAM],
RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT], RAMOS: [Species.SKIDDO, Species.HOPPIP, Species.BELLSPROUT, [Species.PHANTUMP, Species.PUMPKABOO]],
CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.EMOLGA], CLEMONT: [Species.HELIOPTILE, Species.MAGNEMITE, Species.DEDENNE, Species.ROTOM],
VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME], VALERIE: [Species.SYLVEON, Species.MAWILE, Species.MR_MIME, [Species.SPRITZEE, Species.SWIRLIX]],
OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.SLOWKING], OLYMPIA: [Species.ESPURR, Species.SIGILYPH, Species.INKAY, Species.SLOWKING],
WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL], WULFRIC: [Species.BERGMITE, Species.SNOVER, Species.CRYOGONAL, Species.SWINUB],
// Gym Leaders- Galar // Gym Leaders- Galar
MILO: [Species.GOSSIFLEUR, Species.APPLIN, Species.BOUNSWEET], MILO: [Species.GOSSIFLEUR, Species.SEEDOT, Species.APPLIN, Species.LOTAD],
NESSA: [Species.CHEWTLE, Species.ARROKUDA, Species.WIMPOD], NESSA: [Species.CHEWTLE, Species.WIMPOD, Species.ARROKUDA, Species.MAREANIE],
KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.TORKOAL], KABU: [Species.SIZZLIPEDE, Species.VULPIX, Species.GROWLITHE, Species.TORKOAL],
BEA: [Species.GALAR_FARFETCHD, Species.MACHOP, Species.CLOBBOPUS], BEA: [Species.MACHOP, Species.GALAR_FARFETCHD, Species.CLOBBOPUS, Species.FALINKS],
ALLISTER: [Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.GASTLY], ALLISTER: [Species.GASTLY, Species.GALAR_YAMASK, Species.GALAR_CORSOLA, Species.SINISTEA],
OPAL: [Species.MILCERY, Species.TOGETIC, Species.GALAR_WEEZING], OPAL: [Species.MILCERY, Species.GALAR_WEEZING, Species.TOGEPI, Species.MAWILE],
BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR], BEDE: [Species.HATENNA, Species.GALAR_PONYTA, Species.GARDEVOIR, Species.SYLVEON],
GORDIE: [Species.ROLYCOLY, Species.STONJOURNER, Species.BINACLE], GORDIE: [Species.ROLYCOLY, [Species.SHUCKLE, Species.BINACLE], Species.STONJOURNER, Species.LARVITAR],
MELONY: [Species.SNOM, Species.GALAR_DARUMAKA, Species.GALAR_MR_MIME], MELONY: [Species.LAPRAS, Species.SNOM, Species.EISCUE, [Species.GALAR_MR_MIME, Species.GALAR_DARUMAKA]],
PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.INKAY], PIERS: [Species.GALAR_ZIGZAGOON, Species.SCRAGGY, Species.TOXEL, Species.INKAY], // Tera Dark Toxel
MARNIE: [Species.IMPIDIMP, Species.PURRLOIN, Species.MORPEKO], MARNIE: [Species.IMPIDIMP, Species.MORPEKO, Species.PURRLOIN, Species.CROAGUNK], // Tera Dark Croagunk
RAIHAN: [Species.DURALUDON, Species.TURTONATOR, Species.GOOMY], RAIHAN: [Species.DURALUDON, Species.TRAPINCH, Species.GOOMY, Species.TURTONATOR],
// Gym Leaders- Paldea; First slot is Tera // Gym Leaders- Paldea; First slot is Tera
KATY: [Species.TEDDIURSA, Species.NYMBLE, Species.TAROUNTULA], // Tera Bug Teddiursa KATY: [Species.TEDDIURSA, Species.NYMBLE, Species.TAROUNTULA, Species.RELLOR], // Tera Bug Teddiursa
BRASSIUS: [Species.SUDOWOODO, Species.BRAMBLIN, Species.SMOLIV], // Tera Grass Sudowoodo BRASSIUS: [Species.BONSLY, Species.SMOLIV, Species.BRAMBLIN, Species.SUNKERN], // Tera Grass Bonsly
IONO: [Species.MISDREAVUS, Species.TADBULB, Species.WATTREL], // Tera Ghost Misdreavus IONO: [Species.MISDREAVUS, Species.TADBULB, Species.WATTREL, Species.MAGNEMITE], // Tera Ghost Misdreavus
KOFU: [Species.CRABRAWLER, Species.VELUZA, Species.WIGLETT, Species.WINGULL], // Tera Water Crabrawler KOFU: [Species.CRABRAWLER, Species.VELUZA, Species.WIGLETT, Species.WINGULL], // Tera Water Crabrawler
LARRY: [Species.STARLY, Species.DUNSPARCE, Species.LECHONK, Species.KOMALA], // Tera Normal Starly LARRY: [Species.STARLY, Species.DUNSPARCE, Species.LECHONK, Species.KOMALA], // Tera Normal Starly
RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel RYME: [Species.TOXEL, Species.GREAVARD, Species.SHUPPET, Species.MIMIKYU], // Tera Ghost Toxel
TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe TULIP: [Species.FLABEBE, Species.FLITTLE, Species.RALTS, Species.GIRAFARIG], // Tera Psychic Flabebe
GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.CUBCHOO, Species.ALOLA_VULPIX], // Tera Ice Swablu GRUSHA: [Species.SWABLU, Species.CETODDLE, Species.SNOM, Species.CUBCHOO], // Tera Ice Swablu
// Elite Four- Kanto // Elite Four- Kanto
LORELEI: [ LORELEI: [

View File

@ -2,11 +2,11 @@ import { globalScene } from "#app/global-scene";
import { AttackMove, BeakBlastHeaderAttr, DelayedAttackAttr, SelfStatusMove, allMoves } from "./moves/move"; import { AttackMove, BeakBlastHeaderAttr, DelayedAttackAttr, SelfStatusMove, allMoves } from "./moves/move";
import { MoveFlags } from "#enums/MoveFlags"; import { MoveFlags } from "#enums/MoveFlags";
import type Pokemon from "../field/pokemon"; import type Pokemon from "../field/pokemon";
import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName } from "../utils"; import { type nil, getFrameMs, getEnumKeys, getEnumValues, animationFileName } from "../utils/common";
import type { BattlerIndex } from "../battle"; import type { BattlerIndex } from "../battle";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { SubstituteTag } from "./battler-tags"; import { SubstituteTag } from "./battler-tags";
import { isNullOrUndefined } from "../utils"; import { isNullOrUndefined } from "../utils/common";
import Phaser from "phaser"; import Phaser from "phaser";
import { EncounterAnim } from "#enums/encounter-anims"; import { EncounterAnim } from "#enums/encounter-anims";

View File

@ -34,7 +34,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
import type { StatStageChangeCallback } from "#app/phases/stat-stage-change-phase"; import type { StatStageChangeCallback } from "#app/phases/stat-stage-change-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
import i18next from "#app/plugins/i18n"; import i18next from "#app/plugins/i18n";
import { BooleanHolder, getFrameMs, NumberHolder, toDmgValue } from "#app/utils"; import { BooleanHolder, getFrameMs, NumberHolder, toDmgValue } from "#app/utils/common";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
@ -43,7 +43,7 @@ import { Species } from "#enums/species";
import { EFFECTIVE_STATS, getStatKey, Stat, type BattleStat, type EffectiveStat } from "#enums/stat"; import { EFFECTIVE_STATS, getStatKey, Stat, type BattleStat, type EffectiveStat } from "#enums/stat";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
export enum BattlerTagLapseType { export enum BattlerTagLapseType {
FAINT, FAINT,
@ -53,6 +53,7 @@ export enum BattlerTagLapseType {
MOVE_EFFECT, MOVE_EFFECT,
TURN_END, TURN_END,
HIT, HIT,
/** Tag lapses AFTER_HIT, applying its effects even if the user faints */
AFTER_HIT, AFTER_HIT,
CUSTOM, CUSTOM,
} }
@ -504,7 +505,13 @@ export class BeakBlastChargingTag extends BattlerTag {
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
if (lapseType === BattlerTagLapseType.AFTER_HIT) { if (lapseType === BattlerTagLapseType.AFTER_HIT) {
const phaseData = getMoveEffectPhaseData(pokemon); const phaseData = getMoveEffectPhaseData(pokemon);
if (phaseData?.move.hasFlag(MoveFlags.MAKES_CONTACT)) { if (
phaseData?.move.doesFlagEffectApply({
flag: MoveFlags.MAKES_CONTACT,
user: phaseData.attacker,
target: pokemon,
})
) {
phaseData.attacker.trySetStatus(StatusEffect.BURN, true, pokemon); phaseData.attacker.trySetStatus(StatusEffect.BURN, true, pokemon);
} }
return true; return true;
@ -1615,19 +1622,50 @@ export class ProtectedTag extends BattlerTag {
} }
} }
/** Base class for `BattlerTag`s that block damaging moves but not status moves */ /** Class for `BattlerTag`s that apply some effect when hit by a contact move */
export class DamageProtectedTag extends ProtectedTag {} export class ContactProtectedTag extends ProtectedTag {
/**
* Function to call when a contact move hits the pokemon with this tag.
* @param _attacker - The pokemon using the contact move
* @param _user - The pokemon that is being attacked and has the tag
* @param _move - The move used by the attacker
*/
onContact(_attacker: Pokemon, _user: Pokemon) {}
/**
* Lapse the tag and apply `onContact` if the move makes contact and
* `lapseType` is custom, respecting the move's flags and the pokemon's
* abilities, and whether the lapseType is custom.
*
* @param pokemon - The pokemon with the tag
* @param lapseType - The type of lapse to apply. If this is not {@linkcode BattlerTagLapseType.CUSTOM CUSTOM}, no effect will be applied.
* @returns Whether the tag continues to exist after the lapse.
*/
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = super.lapse(pokemon, lapseType);
const moveData = getMoveEffectPhaseData(pokemon);
if (
lapseType === BattlerTagLapseType.CUSTOM &&
moveData &&
moveData.move.doesFlagEffectApply({ flag: MoveFlags.MAKES_CONTACT, user: moveData.attacker, target: pokemon })
) {
this.onContact(moveData.attacker, pokemon);
}
return ret;
}
}
/** /**
* `BattlerTag` class for moves that block damaging moves damage the enemy if the enemy's move makes contact * `BattlerTag` class for moves that block damaging moves damage the enemy if the enemy's move makes contact
* Used by {@linkcode Moves.SPIKY_SHIELD} * Used by {@linkcode Moves.SPIKY_SHIELD}
*/ */
export class ContactDamageProtectedTag extends ProtectedTag { export class ContactDamageProtectedTag extends ContactProtectedTag {
private damageRatio: number; private damageRatio: number;
constructor(sourceMove: Moves, damageRatio: number) { constructor(sourceMove: Moves, damageRatio: number) {
super(sourceMove, BattlerTagType.SPIKY_SHIELD); super(sourceMove, BattlerTagType.SPIKY_SHIELD);
this.damageRatio = damageRatio; this.damageRatio = damageRatio;
} }
@ -1640,22 +1678,46 @@ export class ContactDamageProtectedTag extends ProtectedTag {
this.damageRatio = source.damageRatio; this.damageRatio = source.damageRatio;
} }
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { /**
const ret = super.lapse(pokemon, lapseType); * Damage the attacker by `this.damageRatio` of the target's max HP
* @param attacker - The pokemon using the contact move
if (lapseType === BattlerTagLapseType.CUSTOM) { * @param user - The pokemon that is being attacked and has the tag
const effectPhase = globalScene.getCurrentPhase(); */
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) { override onContact(attacker: Pokemon, user: Pokemon): void {
const attacker = effectPhase.getPokemon(); const cancelled = new BooleanHolder(false);
if (!attacker.hasAbilityWithAttr(BlockNonDirectDamageAbAttr)) { applyAbAttrs(BlockNonDirectDamageAbAttr, user, cancelled);
attacker.damageAndUpdate(toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), { if (!cancelled.value) {
result: HitResult.INDIRECT, attacker.damageAndUpdate(toDmgValue(attacker.getMaxHp() * (1 / this.damageRatio)), {
}); result: HitResult.INDIRECT,
} });
}
} }
}
}
return ret; /** Base class for `BattlerTag`s that block damaging moves but not status moves */
export class DamageProtectedTag extends ContactProtectedTag {}
export class ContactSetStatusProtectedTag extends DamageProtectedTag {
/**
* @param sourceMove The move that caused the tag to be applied
* @param tagType The type of the tag
* @param statusEffect The status effect to apply to the attacker
*/
constructor(
sourceMove: Moves,
tagType: BattlerTagType,
private statusEffect: StatusEffect,
) {
super(sourceMove, tagType);
}
/**
* Set the status effect on the attacker
* @param attacker - The pokemon using the contact move
* @param user - The pokemon that is being attacked and has the tag
*/
override onContact(attacker: Pokemon, user: Pokemon): void {
attacker.trySetStatus(this.statusEffect, true, user);
} }
} }
@ -1678,68 +1740,19 @@ export class ContactStatStageChangeProtectedTag extends DamageProtectedTag {
* When given a battler tag or json representing one, load the data for it. * When given a battler tag or json representing one, load the data for it.
* @param {BattlerTag | any} source A battler tag * @param {BattlerTag | any} source A battler tag
*/ */
loadTag(source: BattlerTag | any): void { override loadTag(source: BattlerTag | any): void {
super.loadTag(source); super.loadTag(source);
this.stat = source.stat; this.stat = source.stat;
this.levels = source.levels; this.levels = source.levels;
} }
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean { /**
const ret = super.lapse(pokemon, lapseType); * Initiate the stat stage change on the attacker
* @param attacker - The pokemon using the contact move
if (lapseType === BattlerTagLapseType.CUSTOM) { * @param user - The pokemon that is being attacked and has the tag
const effectPhase = globalScene.getCurrentPhase(); */
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) { override onContact(attacker: Pokemon, _user: Pokemon): void {
const attacker = effectPhase.getPokemon(); globalScene.unshiftPhase(new StatStageChangePhase(attacker.getBattlerIndex(), false, [this.stat], this.levels));
globalScene.unshiftPhase(new StatStageChangePhase(attacker.getBattlerIndex(), false, [this.stat], this.levels));
}
}
return ret;
}
}
export class ContactPoisonProtectedTag extends ProtectedTag {
constructor(sourceMove: Moves) {
super(sourceMove, BattlerTagType.BANEFUL_BUNKER);
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = super.lapse(pokemon, lapseType);
if (lapseType === BattlerTagLapseType.CUSTOM) {
const effectPhase = globalScene.getCurrentPhase();
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) {
const attacker = effectPhase.getPokemon();
attacker.trySetStatus(StatusEffect.POISON, true, pokemon);
}
}
return ret;
}
}
/**
* `BattlerTag` class for moves that block damaging moves and burn the enemy if the enemy's move makes contact
* Used by {@linkcode Moves.BURNING_BULWARK}
*/
export class ContactBurnProtectedTag extends DamageProtectedTag {
constructor(sourceMove: Moves) {
super(sourceMove, BattlerTagType.BURNING_BULWARK);
}
lapse(pokemon: Pokemon, lapseType: BattlerTagLapseType): boolean {
const ret = super.lapse(pokemon, lapseType);
if (lapseType === BattlerTagLapseType.CUSTOM) {
const effectPhase = globalScene.getCurrentPhase();
if (effectPhase instanceof MoveEffectPhase && effectPhase.move.getMove().hasFlag(MoveFlags.MAKES_CONTACT)) {
const attacker = effectPhase.getPokemon();
attacker.trySetStatus(StatusEffect.BURN, true);
}
}
return ret;
} }
} }
@ -3522,9 +3535,9 @@ export function getBattlerTag(
case BattlerTagType.SILK_TRAP: case BattlerTagType.SILK_TRAP:
return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1); return new ContactStatStageChangeProtectedTag(sourceMove, tagType, Stat.SPD, -1);
case BattlerTagType.BANEFUL_BUNKER: case BattlerTagType.BANEFUL_BUNKER:
return new ContactPoisonProtectedTag(sourceMove); return new ContactSetStatusProtectedTag(sourceMove, tagType, StatusEffect.POISON);
case BattlerTagType.BURNING_BULWARK: case BattlerTagType.BURNING_BULWARK:
return new ContactBurnProtectedTag(sourceMove); return new ContactSetStatusProtectedTag(sourceMove, tagType, StatusEffect.BURN);
case BattlerTagType.ENDURING: case BattlerTagType.ENDURING:
return new EnduringTag(tagType, BattlerTagLapseType.TURN_END, sourceMove); return new EnduringTag(tagType, BattlerTagLapseType.TURN_END, sourceMove);
case BattlerTagType.ENDURE_TOKEN: case BattlerTagType.ENDURE_TOKEN:

View File

@ -2,8 +2,12 @@ import { getPokemonNameWithAffix } from "../messages";
import type Pokemon from "../field/pokemon"; import type Pokemon from "../field/pokemon";
import { HitResult } from "../field/pokemon"; import { HitResult } from "../field/pokemon";
import { getStatusEffectHealText } from "./status-effect"; import { getStatusEffectHealText } from "./status-effect";
import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils"; import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils/common";
import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./abilities/ability"; import {
DoubleBerryEffectAbAttr,
ReduceBerryUseThresholdAbAttr,
applyAbAttrs,
} from "./abilities/ability";
import i18next from "i18next"; import i18next from "i18next";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";

View File

@ -1,4 +1,4 @@
import { BooleanHolder, type NumberHolder, randSeedItem, deepCopy } from "#app/utils"; import { BooleanHolder, type NumberHolder, randSeedItem, deepCopy } from "#app/utils/common";
import i18next from "i18next"; import i18next from "i18next";
import type { DexAttrProps, GameData } from "#app/system/game-data"; import type { DexAttrProps, GameData } from "#app/system/game-data";
import { defaultStarterSpecies } from "#app/system/game-data"; import { defaultStarterSpecies } from "#app/system/game-data";
@ -8,7 +8,8 @@ import { speciesStarterCosts } from "#app/data/balance/starters";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { PokemonMove } from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon";
import type { FixedBattleConfig } from "#app/battle"; import type { FixedBattleConfig } from "#app/battle";
import { ClassicFixedBossWaves, BattleType, getRandomTrainerFunc } from "#app/battle"; import { ClassicFixedBossWaves, getRandomTrainerFunc } from "#app/battle";
import { BattleType } from "#enums/battle-type";
import Trainer, { TrainerVariant } from "#app/field/trainer"; import Trainer, { TrainerVariant } from "#app/field/trainer";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import { Challenges } from "#enums/challenges"; import { Challenges } from "#enums/challenges";

View File

@ -1,6 +1,6 @@
import type { Abilities } from "#enums/abilities"; import type { Abilities } from "#enums/abilities";
import type { PokemonType } from "#enums/pokemon-type"; import type { PokemonType } from "#enums/pokemon-type";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import type { Nature } from "#enums/nature"; import type { Nature } from "#enums/nature";
/** /**

View File

@ -3,7 +3,7 @@ import type { Species } from "#enums/species";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { PlayerPokemon } from "#app/field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import type { Starter } from "#app/ui/starter-select-ui-handler"; import type { Starter } from "#app/ui/starter-select-ui-handler";
import { randSeedGauss, randSeedInt, randSeedItem, getEnumValues } from "#app/utils"; import { randSeedGauss, randSeedInt, randSeedItem, getEnumValues } from "#app/utils/common";
import type { PokemonSpeciesForm } from "#app/data/pokemon-species"; import type { PokemonSpeciesForm } from "#app/data/pokemon-species";
import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; import PokemonSpecies, { getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#app/data/balance/starters";

View File

@ -4,7 +4,7 @@ import type PokemonSpecies from "#app/data/pokemon-species";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#app/data/balance/starters";
import { VariantTier } from "#enums/variant-tier"; import { VariantTier } from "#enums/variant-tier";
import { randInt, randomString, randSeedInt, getIvsFromId } from "#app/utils"; import { randInt, randomString, randSeedInt, getIvsFromId } from "#app/utils/common";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";

View File

@ -29,7 +29,7 @@ import {
} from "../status-effect"; } from "../status-effect";
import { getTypeDamageMultiplier } from "../type"; import { getTypeDamageMultiplier } from "../type";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import { BooleanHolder, NumberHolder, isNullOrUndefined, toDmgValue, randSeedItem, randSeedInt, getEnumValues, toReadableString, type Constructor } from "#app/utils"; import { BooleanHolder, NumberHolder, isNullOrUndefined, toDmgValue, randSeedItem, randSeedInt, getEnumValues, toReadableString, type Constructor } from "#app/utils/common";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import type { ArenaTrapTag } from "../arena-tag"; import type { ArenaTrapTag } from "../arena-tag";
import { ArenaTagSide, WeakenMoveTypeTag } from "../arena-tag"; import { ArenaTagSide, WeakenMoveTypeTag } from "../arena-tag";
@ -75,7 +75,7 @@ import {
PreserveBerryModifier, PreserveBerryModifier,
} from "../../modifier/modifier"; } from "../../modifier/modifier";
import type { BattlerIndex } from "../../battle"; import type { BattlerIndex } from "../../battle";
import { BattleType } from "../../battle"; import { BattleType } from "#enums/battle-type";
import { TerrainType } from "../terrain"; import { TerrainType } from "../terrain";
import { ModifierPoolType } from "#app/modifier/modifier-type"; import { ModifierPoolType } from "#app/modifier/modifier-type";
import { Command } from "../../ui/command-ui-handler"; import { Command } from "../../ui/command-ui-handler";
@ -121,6 +121,7 @@ import { MoveFlags } from "#enums/MoveFlags";
import { MoveEffectTrigger } from "#enums/MoveEffectTrigger"; import { MoveEffectTrigger } from "#enums/MoveEffectTrigger";
import { MultiHitType } from "#enums/MultiHitType"; import { MultiHitType } from "#enums/MultiHitType";
import { invalidAssistMoves, invalidCopycatMoves, invalidMetronomeMoves, invalidMirrorMoveMoves, invalidSleepTalkMoves } from "./invalid-moves"; import { invalidAssistMoves, invalidCopycatMoves, invalidMetronomeMoves, invalidMirrorMoveMoves, invalidSleepTalkMoves } from "./invalid-moves";
import { TrainerVariant } from "#app/field/trainer";
type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean; type MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => boolean;
type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean; type UserMoveConditionFunc = (user: Pokemon, move: Move) => boolean;
@ -3485,8 +3486,7 @@ export class CutHpStatStageBoostAttr extends StatStageChangeAttr {
/** /**
* Attribute implementing the stat boosting effect of {@link https://bulbapedia.bulbagarden.net/wiki/Order_Up_(move) | Order Up}. * Attribute implementing the stat boosting effect of {@link https://bulbapedia.bulbagarden.net/wiki/Order_Up_(move) | Order Up}.
* If the user has a Pokemon with {@link https://bulbapedia.bulbagarden.net/wiki/Commander_(Ability) | Commander} in their mouth, * If the user has a Pokemon with {@link https://bulbapedia.bulbagarden.net/wiki/Commander_(Ability) | Commander} in their mouth,
* one of the user's stats are increased by 1 stage, depending on the "commanding" Pokemon's form. This effect does not respect * one of the user's stats are increased by 1 stage, depending on the "commanding" Pokemon's form.
* effect chance, but Order Up itself may be boosted by Sheer Force.
*/ */
export class OrderUpStatBoostAttr extends MoveEffectAttr { export class OrderUpStatBoostAttr extends MoveEffectAttr {
constructor() { constructor() {
@ -6308,9 +6308,10 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
return false; return false;
} else if (globalScene.currentBattle.battleType !== BattleType.WILD) { // Switch out logic for enemy trainers } else if (globalScene.currentBattle.battleType !== BattleType.WILD) { // Switch out logic for enemy trainers
// Find indices of off-field Pokemon that are eligible to be switched into // Find indices of off-field Pokemon that are eligible to be switched into
const isPartnerTrainer = globalScene.currentBattle.trainer?.isPartner();
const eligibleNewIndices: number[] = []; const eligibleNewIndices: number[] = [];
globalScene.getEnemyParty().forEach((pokemon, index) => { globalScene.getEnemyParty().forEach((pokemon, index) => {
if (pokemon.isAllowedInBattle() && !pokemon.isOnField()) { if (pokemon.isAllowedInBattle() && !pokemon.isOnField() && (!isPartnerTrainer || pokemon.trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)) {
eligibleNewIndices.push(index); eligibleNewIndices.push(index);
} }
}); });
@ -6360,15 +6361,6 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
} }
} }
if (globalScene.currentBattle.waveIndex % 10 === 0) {
return false;
}
// Don't allow wild mons to flee with U-turn et al.
if (this.selfSwitch && !user.isPlayer() && move.category !== MoveCategory.STATUS) {
return false;
}
const allyPokemon = switchOutTarget.getAlly(); const allyPokemon = switchOutTarget.getAlly();
if (switchOutTarget.hp > 0) { if (switchOutTarget.hp > 0) {
@ -6381,13 +6373,12 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
} }
} }
if (!allyPokemon?.isActive(true)) { // clear out enemy held item modifiers of the switch out target
globalScene.clearEnemyHeldItemModifiers(); globalScene.clearEnemyHeldItemModifiers(switchOutTarget);
if (switchOutTarget.hp) { if (!allyPokemon?.isActive(true) && switchOutTarget.hp) {
globalScene.pushPhase(new BattleEndPhase(false)); globalScene.pushPhase(new BattleEndPhase(false));
globalScene.pushPhase(new NewBattlePhase()); globalScene.pushPhase(new NewBattlePhase());
}
} }
} }
@ -6406,6 +6397,7 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
} }
} }
getSwitchOutCondition(): MoveConditionFunc { getSwitchOutCondition(): MoveConditionFunc {
return (user, target, move) => { return (user, target, move) => {
const switchOutTarget = (this.selfSwitch ? user : target); const switchOutTarget = (this.selfSwitch ? user : target);
@ -6429,23 +6421,23 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
const blockedByAbility = new BooleanHolder(false); const blockedByAbility = new BooleanHolder(false);
applyAbAttrs(ForceSwitchOutImmunityAbAttr, target, blockedByAbility); applyAbAttrs(ForceSwitchOutImmunityAbAttr, target, blockedByAbility);
return !blockedByAbility.value; if (blockedByAbility.value) {
return false;
}
} }
if (!player && globalScene.currentBattle.battleType === BattleType.WILD) { if (!player && globalScene.currentBattle.battleType === BattleType.WILD) {
if (this.isBatonPass()) { // wild pokemon cannot switch out with baton pass.
return false; return !this.isBatonPass()
} && globalScene.currentBattle.waveIndex % 10 !== 0
// Don't allow wild opponents to flee on the boss stage since it can ruin a run early on // Don't allow wild mons to flee with U-turn et al.
if (globalScene.currentBattle.waveIndex % 10 === 0) { && !(this.selfSwitch && MoveCategory.STATUS !== move.category);
return false;
}
} }
const party = player ? globalScene.getPlayerParty() : globalScene.getEnemyParty(); const party = player ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
return (!player && !globalScene.currentBattle.battleType) return party.filter(p => p.isAllowedInBattle() && !p.isOnField()
|| party.filter(p => p.isAllowedInBattle() && (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > 0;
&& (player || (p as EnemyPokemon).trainerSlot === (switchOutTarget as EnemyPokemon).trainerSlot)).length > globalScene.currentBattle.getBattlerCount();
}; };
} }
@ -8203,7 +8195,7 @@ export type MoveTargetSet = {
export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveTarget): MoveTargetSet { export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveTarget): MoveTargetSet {
const variableTarget = new NumberHolder(0); const variableTarget = new NumberHolder(0);
user.getOpponents().forEach(p => applyMoveAttrs(VariableTargetAttr, user, p, allMoves[move], variableTarget)); user.getOpponents(false).forEach(p => applyMoveAttrs(VariableTargetAttr, user, p, allMoves[move], variableTarget));
let moveTarget: MoveTarget | undefined; let moveTarget: MoveTarget | undefined;
if (allMoves[move].hasAttr(VariableTargetAttr)) { if (allMoves[move].hasAttr(VariableTargetAttr)) {
@ -8215,7 +8207,7 @@ export function getMoveTargets(user: Pokemon, move: Moves, replaceTarget?: MoveT
} else if (move === undefined) { } else if (move === undefined) {
moveTarget = MoveTarget.NEAR_ENEMY; moveTarget = MoveTarget.NEAR_ENEMY;
} }
const opponents = user.getOpponents(); const opponents = user.getOpponents(false);
let set: Pokemon[] = []; let set: Pokemon[] = [];
let multiple = false; let multiple = false;
@ -9743,7 +9735,7 @@ export function initMoves() {
.ignoresProtect() .ignoresProtect()
.target(MoveTarget.BOTH_SIDES) .target(MoveTarget.BOTH_SIDES)
.unimplemented(), .unimplemented(),
new AttackMove(Moves.SMACK_DOWN, PokemonType.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, 100, 0, 5) new AttackMove(Moves.SMACK_DOWN, PokemonType.ROCK, MoveCategory.PHYSICAL, 50, 100, 15, -1, 0, 5)
.attr(FallDownAttr) .attr(FallDownAttr)
.attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED) .attr(AddBattlerTagAttr, BattlerTagType.INTERRUPTED)
.attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ]) .attr(RemoveBattlerTagAttr, [ BattlerTagType.FLYING, BattlerTagType.FLOATING, BattlerTagType.TELEKINESIS ])
@ -9910,7 +9902,7 @@ export function initMoves() {
.attr(MovePowerMultiplierAttr, (user, target, move) => globalScene.arena.getTerrainType() === TerrainType.GRASSY && target.isGrounded() ? 0.5 : 1) .attr(MovePowerMultiplierAttr, (user, target, move) => globalScene.arena.getTerrainType() === TerrainType.GRASSY && target.isGrounded() ? 0.5 : 1)
.makesContact(false) .makesContact(false)
.target(MoveTarget.ALL_NEAR_OTHERS), .target(MoveTarget.ALL_NEAR_OTHERS),
new AttackMove(Moves.FROST_BREATH, PokemonType.ICE, MoveCategory.SPECIAL, 60, 90, 10, 100, 0, 5) new AttackMove(Moves.FROST_BREATH, PokemonType.ICE, MoveCategory.SPECIAL, 60, 90, 10, -1, 0, 5)
.attr(CritOnlyAttr), .attr(CritOnlyAttr),
new AttackMove(Moves.DRAGON_TAIL, PokemonType.DRAGON, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5) new AttackMove(Moves.DRAGON_TAIL, PokemonType.DRAGON, MoveCategory.PHYSICAL, 60, 90, 10, -1, -6, 5)
.attr(ForceSwitchOutAttr, false, SwitchType.FORCE_SWITCH) .attr(ForceSwitchOutAttr, false, SwitchType.FORCE_SWITCH)
@ -10552,7 +10544,7 @@ export function initMoves() {
.attr(AddArenaTagAttr, ArenaTagType.LIGHT_SCREEN, 5, false, true), .attr(AddArenaTagAttr, ArenaTagType.LIGHT_SCREEN, 5, false, true),
new AttackMove(Moves.BADDY_BAD, PokemonType.DARK, MoveCategory.SPECIAL, 80, 95, 15, -1, 0, 7) new AttackMove(Moves.BADDY_BAD, PokemonType.DARK, MoveCategory.SPECIAL, 80, 95, 15, -1, 0, 7)
.attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, false, true), .attr(AddArenaTagAttr, ArenaTagType.REFLECT, 5, false, true),
new AttackMove(Moves.SAPPY_SEED, PokemonType.GRASS, MoveCategory.PHYSICAL, 100, 90, 10, 100, 0, 7) new AttackMove(Moves.SAPPY_SEED, PokemonType.GRASS, MoveCategory.PHYSICAL, 100, 90, 10, -1, 0, 7)
.attr(LeechSeedAttr) .attr(LeechSeedAttr)
.makesContact(false), .makesContact(false),
new AttackMove(Moves.FREEZY_FROST, PokemonType.ICE, MoveCategory.SPECIAL, 100, 90, 10, -1, 0, 7) new AttackMove(Moves.FREEZY_FROST, PokemonType.ICE, MoveCategory.SPECIAL, 100, 90, 10, -1, 0, 7)
@ -10880,7 +10872,7 @@ export function initMoves() {
.attr(StatStageChangeAttr, [ Stat.SPD ], 1, true), .attr(StatStageChangeAttr, [ Stat.SPD ], 1, true),
new AttackMove(Moves.BITTER_MALICE, PokemonType.GHOST, MoveCategory.SPECIAL, 75, 100, 10, 100, 0, 8) new AttackMove(Moves.BITTER_MALICE, PokemonType.GHOST, MoveCategory.SPECIAL, 75, 100, 10, 100, 0, 8)
.attr(StatStageChangeAttr, [ Stat.ATK ], -1), .attr(StatStageChangeAttr, [ Stat.ATK ], -1),
new SelfStatusMove(Moves.SHELTER, PokemonType.STEEL, -1, 10, 100, 0, 8) new SelfStatusMove(Moves.SHELTER, PokemonType.STEEL, -1, 10, -1, 0, 8)
.attr(StatStageChangeAttr, [ Stat.DEF ], 2, true), .attr(StatStageChangeAttr, [ Stat.DEF ], 2, true),
new AttackMove(Moves.TRIPLE_ARROWS, PokemonType.FIGHTING, MoveCategory.PHYSICAL, 90, 100, 10, 30, 0, 8) new AttackMove(Moves.TRIPLE_ARROWS, PokemonType.FIGHTING, MoveCategory.PHYSICAL, 90, 100, 10, 30, 0, 8)
.makesContact(false) .makesContact(false)
@ -11035,7 +11027,7 @@ export function initMoves() {
.makesContact(false), .makesContact(false),
new AttackMove(Moves.LUMINA_CRASH, PokemonType.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, 100, 0, 9) new AttackMove(Moves.LUMINA_CRASH, PokemonType.PSYCHIC, MoveCategory.SPECIAL, 80, 100, 10, 100, 0, 9)
.attr(StatStageChangeAttr, [ Stat.SPDEF ], -2), .attr(StatStageChangeAttr, [ Stat.SPDEF ], -2),
new AttackMove(Moves.ORDER_UP, PokemonType.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, 100, 0, 9) new AttackMove(Moves.ORDER_UP, PokemonType.DRAGON, MoveCategory.PHYSICAL, 80, 100, 10, -1, 0, 9)
.attr(OrderUpStatBoostAttr) .attr(OrderUpStatBoostAttr)
.makesContact(false), .makesContact(false),
new AttackMove(Moves.JET_PUNCH, PokemonType.WATER, MoveCategory.PHYSICAL, 60, 100, 15, -1, 1, 9) new AttackMove(Moves.JET_PUNCH, PokemonType.WATER, MoveCategory.PHYSICAL, 60, 100, 15, -1, 1, 9)
@ -11089,7 +11081,7 @@ export function initMoves() {
.attr(CutHpStatStageBoostAttr, [ Stat.ATK, Stat.SPATK, Stat.SPD ], 2, 2), .attr(CutHpStatStageBoostAttr, [ Stat.ATK, Stat.SPATK, Stat.SPD ], 2, 2),
new AttackMove(Moves.KOWTOW_CLEAVE, PokemonType.DARK, MoveCategory.PHYSICAL, 85, -1, 10, -1, 0, 9) new AttackMove(Moves.KOWTOW_CLEAVE, PokemonType.DARK, MoveCategory.PHYSICAL, 85, -1, 10, -1, 0, 9)
.slicingMove(), .slicingMove(),
new AttackMove(Moves.FLOWER_TRICK, PokemonType.GRASS, MoveCategory.PHYSICAL, 70, -1, 10, 100, 0, 9) new AttackMove(Moves.FLOWER_TRICK, PokemonType.GRASS, MoveCategory.PHYSICAL, 70, -1, 10, -1, 0, 9)
.attr(CritOnlyAttr) .attr(CritOnlyAttr)
.makesContact(false), .makesContact(false),
new AttackMove(Moves.TORCH_SONG, PokemonType.FIRE, MoveCategory.SPECIAL, 80, 100, 10, 100, 0, 9) new AttackMove(Moves.TORCH_SONG, PokemonType.FIRE, MoveCategory.SPECIAL, 80, 100, 10, 100, 0, 9)
@ -11207,7 +11199,7 @@ export function initMoves() {
.attr(StatusEffectAttr, StatusEffect.BURN) .attr(StatusEffectAttr, StatusEffect.BURN)
.target(MoveTarget.ALL_NEAR_ENEMIES) .target(MoveTarget.ALL_NEAR_ENEMIES)
.triageMove(), .triageMove(),
new AttackMove(Moves.SYRUP_BOMB, PokemonType.GRASS, MoveCategory.SPECIAL, 60, 85, 10, -1, 0, 9) new AttackMove(Moves.SYRUP_BOMB, PokemonType.GRASS, MoveCategory.SPECIAL, 60, 85, 10, 100, 0, 9)
.attr(AddBattlerTagAttr, BattlerTagType.SYRUP_BOMB, false, false, 3) .attr(AddBattlerTagAttr, BattlerTagType.SYRUP_BOMB, false, false, 3)
.ballBombMove(), .ballBombMove(),
new AttackMove(Moves.IVY_CUDGEL, PokemonType.GRASS, MoveCategory.PHYSICAL, 100, 100, 10, -1, 0, 9) new AttackMove(Moves.IVY_CUDGEL, PokemonType.GRASS, MoveCategory.PHYSICAL, 100, 100, 10, -1, 0, 9)
@ -11225,7 +11217,8 @@ export function initMoves() {
.partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */ .partial(), /** Does not ignore abilities that affect stats, relevant in determining the move's category {@see TeraMoveCategoryAttr} */
new AttackMove(Moves.FICKLE_BEAM, PokemonType.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9) new AttackMove(Moves.FICKLE_BEAM, PokemonType.DRAGON, MoveCategory.SPECIAL, 80, 100, 5, 30, 0, 9)
.attr(PreMoveMessageAttr, doublePowerChanceMessageFunc) .attr(PreMoveMessageAttr, doublePowerChanceMessageFunc)
.attr(DoublePowerChanceAttr), .attr(DoublePowerChanceAttr)
.edgeCase(), // Should not interact with Sheer Force
new SelfStatusMove(Moves.BURNING_BULWARK, PokemonType.FIRE, -1, 10, -1, 4, 9) new SelfStatusMove(Moves.BURNING_BULWARK, PokemonType.FIRE, -1, 10, -1, 4, 9)
.attr(ProtectAttr, BattlerTagType.BURNING_BULWARK) .attr(ProtectAttr, BattlerTagType.BURNING_BULWARK)
.condition(failIfLastCondition), .condition(failIfLastCondition),
@ -11248,16 +11241,18 @@ export function initMoves() {
new StatusMove(Moves.DRAGON_CHEER, PokemonType.DRAGON, -1, 15, -1, 0, 9) new StatusMove(Moves.DRAGON_CHEER, PokemonType.DRAGON, -1, 15, -1, 0, 9)
.attr(AddBattlerTagAttr, BattlerTagType.DRAGON_CHEER, false, true) .attr(AddBattlerTagAttr, BattlerTagType.DRAGON_CHEER, false, true)
.target(MoveTarget.NEAR_ALLY), .target(MoveTarget.NEAR_ALLY),
new AttackMove(Moves.ALLURING_VOICE, PokemonType.FAIRY, MoveCategory.SPECIAL, 80, 100, 10, -1, 0, 9) new AttackMove(Moves.ALLURING_VOICE, PokemonType.FAIRY, MoveCategory.SPECIAL, 80, 100, 10, 100, 0, 9)
.attr(AddBattlerTagIfBoostedAttr, BattlerTagType.CONFUSED) .attr(AddBattlerTagIfBoostedAttr, BattlerTagType.CONFUSED)
.soundBased(), .soundBased(),
new AttackMove(Moves.TEMPER_FLARE, PokemonType.FIRE, MoveCategory.PHYSICAL, 75, 100, 10, -1, 0, 9) new AttackMove(Moves.TEMPER_FLARE, PokemonType.FIRE, MoveCategory.PHYSICAL, 75, 100, 10, -1, 0, 9)
.attr(MovePowerMultiplierAttr, (user, target, move) => user.getLastXMoves(2)[1]?.result === MoveResult.MISS || user.getLastXMoves(2)[1]?.result === MoveResult.FAIL ? 2 : 1), .attr(MovePowerMultiplierAttr, (user, target, move) => user.getLastXMoves(2)[1]?.result === MoveResult.MISS || user.getLastXMoves(2)[1]?.result === MoveResult.FAIL ? 2 : 1),
new AttackMove(Moves.SUPERCELL_SLAM, PokemonType.ELECTRIC, MoveCategory.PHYSICAL, 100, 95, 15, -1, 0, 9) new AttackMove(Moves.SUPERCELL_SLAM, PokemonType.ELECTRIC, MoveCategory.PHYSICAL, 100, 95, 15, -1, 0, 9)
.attr(AlwaysHitMinimizeAttr)
.attr(HitsTagForDoubleDamageAttr, BattlerTagType.MINIMIZED)
.attr(MissEffectAttr, crashDamageFunc) .attr(MissEffectAttr, crashDamageFunc)
.attr(NoEffectAttr, crashDamageFunc) .attr(NoEffectAttr, crashDamageFunc)
.recklessMove(), .recklessMove(),
new AttackMove(Moves.PSYCHIC_NOISE, PokemonType.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, -1, 0, 9) new AttackMove(Moves.PSYCHIC_NOISE, PokemonType.PSYCHIC, MoveCategory.SPECIAL, 75, 100, 10, 100, 0, 9)
.soundBased() .soundBased()
.attr(AddBattlerTagAttr, BattlerTagType.HEAL_BLOCK, false, false, 2), .attr(AddBattlerTagAttr, BattlerTagType.HEAL_BLOCK, false, false, 2),
new AttackMove(Moves.UPPER_HAND, PokemonType.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9) new AttackMove(Moves.UPPER_HAND, PokemonType.FIGHTING, MoveCategory.PHYSICAL, 65, 100, 15, 100, 3, 9)

View File

@ -14,7 +14,7 @@ import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import i18next from "i18next"; import i18next from "i18next";
import type { IEggOptions } from "#app/data/egg"; import type { IEggOptions } from "#app/data/egg";
import { EggSourceType } from "#enums/egg-source-types"; import { EggSourceType } from "#enums/egg-source-types";

View File

@ -24,7 +24,7 @@ import { BerryModifier, PokemonInstantReviveModifier } from "#app/modifier/modif
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { randInt } from "#app/utils"; import { randInt } from "#app/utils/common";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { import {
applyModifierTypeToPlayerPokemon, applyModifierTypeToPlayerPokemon,

View File

@ -13,7 +13,7 @@ import type { PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import type { BerryModifierType, ModifierTypeOption } from "#app/modifier/modifier-type"; import type { BerryModifierType, ModifierTypeOption } from "#app/modifier/modifier-type";
import { ModifierPoolType, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; import { ModifierPoolType, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -16,7 +16,7 @@ import { TrainerSlot } from "#enums/trainer-slot";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { PartyMemberStrength } from "#enums/party-member-strength"; import { PartyMemberStrength } from "#enums/party-member-strength";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils"; import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils/common";
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -31,9 +31,9 @@ import {
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { randSeedInt, randSeedShuffle } from "#app/utils"; import { randSeedInt, randSeedShuffle } from "#app/utils/common";
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import type { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
@ -437,7 +437,7 @@ async function handleSwapAbility() {
await showEncounterDialogue(`${namespace}:option.1.apply_ability_dialogue`, `${namespace}:speaker`); await showEncounterDialogue(`${namespace}:option.1.apply_ability_dialogue`, `${namespace}:speaker`);
await showEncounterText(`${namespace}:option.1.apply_ability_message`); await showEncounterText(`${namespace}:option.1.apply_ability_message`);
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
displayYesNoOptions(resolve); displayYesNoOptions(resolve);
}); });
}); });
@ -467,7 +467,7 @@ function displayYesNoOptions(resolve) {
maxOptions: 7, maxOptions: 7,
yOffset: 0, yOffset: 0,
}; };
globalScene.ui.setModeWithoutClear(Mode.OPTION_SELECT, config, null, true); globalScene.ui.setModeWithoutClear(UiMode.OPTION_SELECT, config, null, true);
} }
function onYesAbilitySwap(resolve) { function onYesAbilitySwap(resolve) {
@ -477,11 +477,11 @@ function onYesAbilitySwap(resolve) {
applyAbilityOverrideToPokemon(pokemon, encounter.misc.ability); applyAbilityOverrideToPokemon(pokemon, encounter.misc.ability);
encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender()); encounter.setDialogueToken("chosenPokemon", pokemon.getNameToRender());
globalScene.ui.setMode(Mode.MESSAGE).then(() => resolve(true)); globalScene.ui.setMode(UiMode.MESSAGE).then(() => resolve(true));
}; };
const onPokemonNotSelected = () => { const onPokemonNotSelected = () => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
displayYesNoOptions(resolve); displayYesNoOptions(resolve);
}); });
}; };

View File

@ -1,5 +1,5 @@
import type { PokemonType } from "#enums/pokemon-type"; import type { PokemonType } from "#enums/pokemon-type";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -32,7 +32,7 @@ import { modifierTypes } from "#app/modifier/modifier-type";
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
import i18next from "#app/plugins/i18n"; import i18next from "#app/plugins/i18n";
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { randSeedItem } from "#app/utils"; import { randSeedItem } from "#app/utils/common";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";

View File

@ -4,7 +4,7 @@ import {
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import type { ModifierTypeFunc } from "#app/modifier/modifier-type"; import type { ModifierTypeFunc } from "#app/modifier/modifier-type";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";

View File

@ -30,7 +30,7 @@ import { PokemonMove } from "#app/field/pokemon";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { EncounterBattleAnim } from "#app/data/battle-anims"; import { EncounterBattleAnim } from "#app/data/battle-anims";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { import {

View File

@ -31,7 +31,7 @@ import {
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -23,7 +23,14 @@ import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
import { getTypeRgb } from "#app/data/type"; import { getTypeRgb } from "#app/data/type";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { NumberHolder, isNullOrUndefined, randInt, randSeedInt, randSeedShuffle, randSeedItem } from "#app/utils"; import {
NumberHolder,
isNullOrUndefined,
randInt,
randSeedInt,
randSeedShuffle,
randSeedItem,
} from "#app/utils/common";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";

View File

@ -12,7 +12,7 @@ import { modifierTypes } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { PartyMemberStrength } from "#enums/party-member-strength"; import { PartyMemberStrength } from "#enums/party-member-strength";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -18,7 +18,7 @@ import { getPokemonSpecies } from "#app/data/pokemon-species";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { GameOverPhase } from "#app/phases/game-over-phase"; import { GameOverPhase } from "#app/phases/game-over-phase";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -15,7 +15,7 @@ import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifi
import type { EnemyPokemon } from "#app/field/pokemon"; import type { EnemyPokemon } from "#app/field/pokemon";
import { PokeballType } from "#enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { NumberHolder, randSeedInt } from "#app/utils"; import { NumberHolder, randSeedInt } from "#app/utils/common";
import type PokemonSpecies from "#app/data/pokemon-species"; import type PokemonSpecies from "#app/data/pokemon-species";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";

View File

@ -8,7 +8,7 @@ import {
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -7,7 +7,7 @@ import {
transitionMysteryEncounterIntroVisuals, transitionMysteryEncounterIntroVisuals,
updatePlayerMoney, updatePlayerMoney,
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";

View File

@ -7,7 +7,7 @@ import {
import { trainerConfigs } from "#app/data/trainers/trainer-config"; import { trainerConfigs } from "#app/data/trainers/trainer-config";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { randSeedShuffle } from "#app/utils"; import { randSeedShuffle } from "#app/utils/common";
import type MysteryEncounter from "../mystery-encounter"; import type MysteryEncounter from "../mystery-encounter";
import { MysteryEncounterBuilder } from "../mystery-encounter"; import { MysteryEncounterBuilder } from "../mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -3,7 +3,7 @@ import {
transitionMysteryEncounterIntroVisuals, transitionMysteryEncounterIntroVisuals,
updatePlayerMoney, updatePlayerMoney,
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";

View File

@ -15,7 +15,7 @@ import type { PokemonHeldItemModifier } from "#app/modifier/modifier";
import { AbilityAttr } from "#app/system/game-data"; import { AbilityAttr } from "#app/system/game-data";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import type { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { isNullOrUndefined, randSeedShuffle } from "#app/utils"; import { isNullOrUndefined, randSeedShuffle } from "#app/utils/common";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -27,7 +27,7 @@ import { Moves } from "#enums/moves";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { PokemonMove } from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
/** the i18n namespace for this encounter */ /** the i18n namespace for this encounter */
const namespace = "mysteryEncounters/trashToTreasure"; const namespace = "mysteryEncounters/trashToTreasure";

View File

@ -27,7 +27,7 @@ import {
getSpriteKeysFromPokemon, getSpriteKeysFromPokemon,
} from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
import type { Moves } from "#enums/moves"; import type { Moves } from "#enums/moves";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { SelfStatusMove } from "#app/data/moves/move"; import { SelfStatusMove } from "#app/data/moves/move";

View File

@ -17,7 +17,7 @@ import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { PokemonMove } from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon";
import { NumberHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils"; import { NumberHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils/common";
import type PokemonSpecies from "#app/data/pokemon-species"; import type PokemonSpecies from "#app/data/pokemon-species";
import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species"; import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
import type { PokemonHeldItemModifier } from "#app/modifier/modifier"; import type { PokemonHeldItemModifier } from "#app/modifier/modifier";

View File

@ -12,7 +12,7 @@ import {
} from "#app/data/mystery-encounters/mystery-encounter-requirements"; } from "#app/data/mystery-encounters/mystery-encounter-requirements";
import type { CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement"; import type { CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
import { CanLearnMoveRequirement } from "./requirements/can-learn-move-requirement"; import { CanLearnMoveRequirement } from "./requirements/can-learn-move-requirement";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
// biome-ignore lint/suspicious/noConfusingVoidType: void unions in callbacks are OK // biome-ignore lint/suspicious/noConfusingVoidType: void unions in callbacks are OK

View File

@ -9,7 +9,7 @@ import { WeatherType } from "#enums/weather-type";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import { AttackTypeBoosterModifier } from "#app/modifier/modifier"; import { AttackTypeBoosterModifier } from "#app/modifier/modifier";
import type { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type"; import type { AttackTypeBoosterModifierType } from "#app/modifier/modifier-type";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import type { Abilities } from "#enums/abilities"; import type { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type";

View File

@ -1,6 +1,6 @@
import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounters/mystery-encounters"; import { BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT } from "#app/data/mystery-encounters/mystery-encounters";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import type { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import type { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
export class SeenEncounterData { export class SeenEncounterData {

View File

@ -1,11 +1,11 @@
import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import type { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils";
import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import type { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils"; import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils/common";
import type { MysteryEncounterType } from "#enums/mystery-encounter-type"; import type { MysteryEncounterType } from "#enums/mystery-encounter-type";
import type { MysteryEncounterSpriteConfig } from "#app/field/mystery-encounter-intro"; import type { MysteryEncounterSpriteConfig } from "#app/field/mystery-encounter-intro";
import MysteryEncounterIntroVisuals from "#app/field/mystery-encounter-intro"; import MysteryEncounterIntroVisuals from "#app/field/mystery-encounter-intro";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import type { StatusEffect } from "#enums/status-effect"; import type { StatusEffect } from "#enums/status-effect";
import type { OptionTextDisplay } from "./mystery-encounter-dialogue"; import type { OptionTextDisplay } from "./mystery-encounter-dialogue";
import type MysteryEncounterDialogue from "./mystery-encounter-dialogue"; import type MysteryEncounterDialogue from "./mystery-encounter-dialogue";

View File

@ -1,7 +1,7 @@
import type { Moves } from "#app/enums/moves"; import type { Moves } from "#app/enums/moves";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import { PokemonMove } from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
import type { TextStyle } from "#app/ui/text"; import type { TextStyle } from "#app/ui/text";
import { getTextWithColors } from "#app/ui/text"; import { getTextWithColors } from "#app/ui/text";
import { UiTheme } from "#enums/ui-theme"; import { UiTheme } from "#enums/ui-theme";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import i18next from "i18next"; import i18next from "i18next";
/** /**

View File

@ -1,5 +1,6 @@
import type Battle from "#app/battle"; import type Battle from "#app/battle";
import { BattlerIndex, BattleType } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { BattleType } from "#enums/battle-type";
import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes"; import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes";
import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option"; import type MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option";
import { import {
@ -29,8 +30,8 @@ import type PokemonData from "#app/system/pokemon-data";
import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import type { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler"; import type { PartyOption, PokemonSelectFilter } from "#app/ui/party-ui-handler";
import { PartyUiMode } from "#app/ui/party-ui-handler"; import { PartyUiMode } from "#app/ui/party-ui-handler";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import { isNullOrUndefined, randSeedInt, randomString, randSeedItem } from "#app/utils"; import { isNullOrUndefined, randSeedInt, randomString, randSeedItem } from "#app/utils/common";
import type { BattlerTagType } from "#enums/battler-tag-type"; import type { BattlerTagType } from "#enums/battler-tag-type";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import type { TrainerType } from "#enums/trainer-type"; import type { TrainerType } from "#enums/trainer-type";
@ -557,7 +558,7 @@ export function selectPokemonForOption(
// Open party screen to choose pokemon // Open party screen to choose pokemon
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.PARTY, UiMode.PARTY,
PartyUiMode.SELECT, PartyUiMode.SELECT,
-1, -1,
(slotIndex: number, _option: PartyOption) => { (slotIndex: number, _option: PartyOption) => {
@ -575,7 +576,7 @@ export function selectPokemonForOption(
} }
// There is a second option to choose after selecting the Pokemon // There is a second option to choose after selecting the Pokemon
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
const displayOptions = () => { const displayOptions = () => {
// Always appends a cancel option to bottom of options // Always appends a cancel option to bottom of options
const fullOptions = secondaryOptions const fullOptions = secondaryOptions
@ -617,7 +618,7 @@ export function selectPokemonForOption(
if (fullOptions[0].onHover) { if (fullOptions[0].onHover) {
fullOptions[0].onHover(); fullOptions[0].onHover();
} }
globalScene.ui.setModeWithoutClear(Mode.OPTION_SELECT, config, null, true); globalScene.ui.setModeWithoutClear(UiMode.OPTION_SELECT, config, null, true);
}; };
const textPromptKey = const textPromptKey =
@ -667,20 +668,20 @@ export function selectOptionThenPokemon(
const modeToSetOnExit = globalScene.ui.getMode(); const modeToSetOnExit = globalScene.ui.getMode();
const displayOptions = (config: OptionSelectConfig) => { const displayOptions = (config: OptionSelectConfig) => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
if (!optionSelectPromptKey) { if (!optionSelectPromptKey) {
// Do hover over the starting selection option // Do hover over the starting selection option
if (fullOptions[0].onHover) { if (fullOptions[0].onHover) {
fullOptions[0].onHover(); fullOptions[0].onHover();
} }
globalScene.ui.setMode(Mode.OPTION_SELECT, config); globalScene.ui.setMode(UiMode.OPTION_SELECT, config);
} else { } else {
showEncounterText(optionSelectPromptKey).then(() => { showEncounterText(optionSelectPromptKey).then(() => {
// Do hover over the starting selection option // Do hover over the starting selection option
if (fullOptions[0].onHover) { if (fullOptions[0].onHover) {
fullOptions[0].onHover(); fullOptions[0].onHover();
} }
globalScene.ui.setMode(Mode.OPTION_SELECT, config); globalScene.ui.setMode(UiMode.OPTION_SELECT, config);
}); });
} }
}); });
@ -689,7 +690,7 @@ export function selectOptionThenPokemon(
const selectPokemonAfterOption = (selectedOptionIndex: number) => { const selectPokemonAfterOption = (selectedOptionIndex: number) => {
// Open party screen to choose a Pokemon // Open party screen to choose a Pokemon
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.PARTY, UiMode.PARTY,
PartyUiMode.SELECT, PartyUiMode.SELECT,
-1, -1,
(slotIndex: number, _option: PartyOption) => { (slotIndex: number, _option: PartyOption) => {

View File

@ -1,6 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import i18next from "i18next"; import i18next from "i18next";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils/common";
import { PokemonHeldItemModifier } from "#app/modifier/modifier"; import { PokemonHeldItemModifier } from "#app/modifier/modifier";
import type { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import type { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
@ -14,7 +14,7 @@ import { PlayerGender } from "#enums/player-gender";
import { addPokeballCaptureStars, addPokeballOpenParticles } from "#app/field/anims"; import { addPokeballCaptureStars, addPokeballOpenParticles } from "#app/field/anims";
import { getStatusEffectCatchRateMultiplier } from "#app/data/status-effect"; import { getStatusEffectCatchRateMultiplier } from "#app/data/status-effect";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import type { PartyOption } from "#app/ui/party-ui-handler"; import type { PartyOption } from "#app/ui/party-ui-handler";
import { PartyUiMode } from "#app/ui/party-ui-handler"; import { PartyUiMode } from "#app/ui/party-ui-handler";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
@ -714,7 +714,7 @@ export async function catchPokemon(
() => { () => {
globalScene.pokemonInfoContainer.makeRoomForConfirmUi(1, true); globalScene.pokemonInfoContainer.makeRoomForConfirmUi(1, true);
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.CONFIRM, UiMode.CONFIRM,
() => { () => {
const newPokemon = globalScene.addPlayerPokemon( const newPokemon = globalScene.addPlayerPokemon(
pokemon.species, pokemon.species,
@ -729,12 +729,12 @@ export async function catchPokemon(
pokemon, pokemon,
); );
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.SUMMARY, UiMode.SUMMARY,
newPokemon, newPokemon,
0, 0,
SummaryUiMode.DEFAULT, SummaryUiMode.DEFAULT,
() => { () => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
promptRelease(); promptRelease();
}); });
}, },
@ -749,13 +749,13 @@ export async function catchPokemon(
female: pokemon.gender === Gender.FEMALE, female: pokemon.gender === Gender.FEMALE,
}; };
globalScene.ui.setOverlayMode( globalScene.ui.setOverlayMode(
Mode.POKEDEX_PAGE, UiMode.POKEDEX_PAGE,
pokemon.species, pokemon.species,
pokemon.formIndex, pokemon.formIndex,
attributes, attributes,
null, null,
() => { () => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
promptRelease(); promptRelease();
}); });
}, },
@ -763,11 +763,11 @@ export async function catchPokemon(
}, },
() => { () => {
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.PARTY, UiMode.PARTY,
PartyUiMode.RELEASE, PartyUiMode.RELEASE,
0, 0,
(slotIndex: number, _option: PartyOption) => { (slotIndex: number, _option: PartyOption) => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
if (slotIndex < 6) { if (slotIndex < 6) {
addToParty(slotIndex); addToParty(slotIndex);
} else { } else {
@ -778,7 +778,7 @@ export async function catchPokemon(
); );
}, },
() => { () => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
removePokemon(); removePokemon();
end(); end();
}); });

View File

@ -1,5 +1,5 @@
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import { getFrameMs } from "#app/utils"; import { getFrameMs } from "#app/utils/common";
import { cos, sin } from "#app/field/anims"; import { cos, sin } from "#app/field/anims";
import { getTypeRgb } from "#app/data/type"; import { getTypeRgb } from "#app/data/type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -1,4 +1,4 @@
import { toReadableString } from "#app/utils"; import { toReadableString } from "#app/utils/common";
import { TextStyle, getBBCodeFrag } from "../ui/text"; import { TextStyle, getBBCodeFrag } from "../ui/text";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { UiTheme } from "#enums/ui-theme"; import { UiTheme } from "#enums/ui-theme";

View File

@ -1,6 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { CriticalCatchChanceBoosterModifier } from "#app/modifier/modifier"; import { CriticalCatchChanceBoosterModifier } from "#app/modifier/modifier";
import { NumberHolder } from "#app/utils"; import { NumberHolder } from "#app/utils/common";
import { PokeballType } from "#enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -3,7 +3,7 @@ import type Pokemon from "../field/pokemon";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { allMoves } from "./moves/move"; import { allMoves } from "./moves/move";
import { MoveCategory } from "#enums/MoveCategory"; import { MoveCategory } from "#enums/MoveCategory";
import type { Constructor, nil } from "#app/utils"; import type { Constructor, nil } from "#app/utils/common";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";

View File

@ -8,7 +8,7 @@ import type { AnySound } from "#app/battle-scene";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type { GameMode } from "#app/game-mode"; import type { GameMode } from "#app/game-mode";
import { DexAttr, type StarterMoveset } from "#app/system/game-data"; import { DexAttr, type StarterMoveset } from "#app/system/game-data";
import { isNullOrUndefined, capitalizeString, randSeedInt, randSeedGauss, randSeedItem } from "#app/utils"; import { isNullOrUndefined, capitalizeString, randSeedInt, randSeedGauss, randSeedItem } from "#app/utils/common";
import { uncatchableSpecies } from "#app/data/balance/biomes"; import { uncatchableSpecies } from "#app/data/balance/biomes";
import { speciesEggMoves } from "#app/data/balance/egg-moves"; import { speciesEggMoves } from "#app/data/balance/egg-moves";
import { GrowthRate } from "#app/data/exp"; import { GrowthRate } from "#app/data/exp";
@ -27,11 +27,12 @@ import {
} from "#app/data/balance/pokemon-level-moves"; } from "#app/data/balance/pokemon-level-moves";
import type { Stat } from "#enums/stat"; import type { Stat } from "#enums/stat";
import type { Variant, VariantSet } from "#app/sprites/variant"; import type { Variant, VariantSet } from "#app/sprites/variant";
import { variantData } from "#app/sprites/variant"; import { populateVariantColorCache, variantData } from "#app/sprites/variant";
import { speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters"; import { speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters";
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
import { starterPassiveAbilities } from "#app/data/balance/passives"; import { starterPassiveAbilities } from "#app/data/balance/passives";
import { loadPokemonVariantAssets } from "#app/sprites/pokemon-sprite"; import { loadPokemonVariantAssets } from "#app/sprites/pokemon-sprite";
import { hasExpSprite } from "#app/sprites/sprite-utils";
export enum Region { export enum Region {
NORMAL, NORMAL,
@ -388,8 +389,7 @@ export abstract class PokemonSpeciesForm {
return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`; return `${/_[1-3]$/.test(spriteId) ? "variant/" : ""}${spriteId}`;
} }
/** Compute the sprite ID of the pokemon form. */ getBaseSpriteKey(female: boolean, formIndex?: number): string {
getSpriteId(female: boolean, formIndex?: number, shiny?: boolean, variant = 0, back?: boolean): string {
if (formIndex === undefined || this instanceof PokemonForm) { if (formIndex === undefined || this instanceof PokemonForm) {
formIndex = this.formIndex; formIndex = this.formIndex;
} }
@ -400,7 +400,12 @@ export abstract class PokemonSpeciesForm {
female && female &&
![SpeciesFormKey.MEGA, SpeciesFormKey.GIGANTAMAX].includes(formSpriteKey as SpeciesFormKey); ![SpeciesFormKey.MEGA, SpeciesFormKey.GIGANTAMAX].includes(formSpriteKey as SpeciesFormKey);
const baseSpriteKey = `${showGenderDiffs ? "female__" : ""}${this.speciesId}${formSpriteKey ? `-${formSpriteKey}` : ""}`; return `${showGenderDiffs ? "female__" : ""}${this.speciesId}${formSpriteKey ? `-${formSpriteKey}` : ""}`;
}
/** Compute the sprite ID of the pokemon form. */
getSpriteId(female: boolean, formIndex?: number, shiny?: boolean, variant = 0, back?: boolean): string {
const baseSpriteKey = this.getBaseSpriteKey(female, formIndex);
let config = variantData; let config = variantData;
`${back ? "back__" : ""}${baseSpriteKey}`.split("__").map(p => (config ? (config = config[p]) : null)); `${back ? "back__" : ""}${baseSpriteKey}`.split("__").map(p => (config ? (config = config[p]) : null));
@ -597,10 +602,19 @@ export abstract class PokemonSpeciesForm {
startLoad = false, startLoad = false,
back = false, back = false,
): Promise<void> { ): Promise<void> {
// We need to populate the color cache for this species' variant
const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant, back); const spriteKey = this.getSpriteKey(female, formIndex, shiny, variant, back);
globalScene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant, back)); globalScene.loadPokemonAtlas(spriteKey, this.getSpriteAtlasPath(female, formIndex, shiny, variant, back));
globalScene.load.audio(this.getCryKey(formIndex), `audio/${this.getCryKey(formIndex)}.m4a`); globalScene.load.audio(this.getCryKey(formIndex), `audio/${this.getCryKey(formIndex)}.m4a`);
const baseSpriteKey = this.getBaseSpriteKey(female, formIndex);
// Force the variant color cache to be loaded for the form
await populateVariantColorCache(
"pkmn__" + baseSpriteKey,
globalScene.experimentalSprites && hasExpSprite(spriteKey),
baseSpriteKey,
);
return new Promise<void>(resolve => { return new Promise<void>(resolve => {
globalScene.load.once(Phaser.Loader.Events.COMPLETE, () => { globalScene.load.once(Phaser.Loader.Events.COMPLETE, () => {
const originalWarn = console.warn; const originalWarn = console.warn;

View File

@ -1,4 +1,4 @@
import { randIntRange } from "#app/utils"; import { randIntRange } from "#app/utils/common";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import type { ParseKeys } from "i18next"; import type { ParseKeys } from "i18next";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -59,7 +59,7 @@ export class Terrain {
// Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain // Cancels move if the move has positive priority and targets a Pokemon grounded on the Psychic Terrain
return ( return (
move.getPriority(user) > 0 && move.getPriority(user) > 0 &&
user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()) user.getOpponents(true).some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded())
); );
} }
} }

View File

@ -1,5 +1,5 @@
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { toReadableString } from "#app/utils"; import { toReadableString } from "#app/utils/common";
class TrainerNameConfig { class TrainerNameConfig {
public urls: string[]; public urls: string[];

View File

@ -1,4 +1,4 @@
import { startingWave } from "#app/battle-scene"; import { startingWave } from "#app/starting-wave";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { PartyMemberStrength } from "#enums/party-member-strength"; import { PartyMemberStrength } from "#enums/party-member-strength";

View File

@ -1,7 +1,7 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { PokemonMove } from "#app/field/pokemon"; import { PokemonMove } from "#app/field/pokemon";
import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt } from "#app/utils"; import { toReadableString, isNullOrUndefined, randSeedItem, randSeedInt } from "#app/utils/common";
import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { tmSpecies } from "#app/data/balance/tms"; import { tmSpecies } from "#app/data/balance/tms";
@ -2579,252 +2579,252 @@ export const trainerConfigs: TrainerConfigs = {
), ),
[TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK)) [TrainerType.BROCK]: new TrainerConfig((t = TrainerType.BROCK))
.initForGymLeader(signatureSpecies["BROCK"], true, PokemonType.ROCK) .initForGymLeader(signatureSpecies["BROCK"], true, PokemonType.ROCK, false, -1)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.MISTY]: new TrainerConfig(++t) [TrainerType.MISTY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["MISTY"], false, PokemonType.WATER) .initForGymLeader(signatureSpecies["MISTY"], false, PokemonType.WATER, false, -1)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.LT_SURGE]: new TrainerConfig(++t) [TrainerType.LT_SURGE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["LT_SURGE"], true, PokemonType.ELECTRIC) .initForGymLeader(signatureSpecies["LT_SURGE"], true, PokemonType.ELECTRIC, false, -1)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.ERIKA]: new TrainerConfig(++t) [TrainerType.ERIKA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["ERIKA"], false, PokemonType.GRASS) .initForGymLeader(signatureSpecies["ERIKA"], false, PokemonType.GRASS, false, -1)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.JANINE]: new TrainerConfig(++t) [TrainerType.JANINE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["JANINE"], false, PokemonType.POISON) .initForGymLeader(signatureSpecies["JANINE"], false, PokemonType.POISON, false, -1)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.SABRINA]: new TrainerConfig(++t) [TrainerType.SABRINA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["SABRINA"], false, PokemonType.PSYCHIC) .initForGymLeader(signatureSpecies["SABRINA"], false, PokemonType.PSYCHIC, false, -1)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.BLAINE]: new TrainerConfig(++t) [TrainerType.BLAINE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["BLAINE"], true, PokemonType.FIRE) .initForGymLeader(signatureSpecies["BLAINE"], true, PokemonType.FIRE, false, -1)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.GIOVANNI]: new TrainerConfig(++t) [TrainerType.GIOVANNI]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["GIOVANNI"], true, PokemonType.DARK) .initForGymLeader(signatureSpecies["GIOVANNI"], true, PokemonType.GROUND, false, -2)
.setBattleBgm("battle_kanto_gym") .setBattleBgm("battle_kanto_gym")
.setMixedBattleBgm("battle_kanto_gym"), .setMixedBattleBgm("battle_kanto_gym"),
[TrainerType.FALKNER]: new TrainerConfig(++t) [TrainerType.FALKNER]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["FALKNER"], true, PokemonType.FLYING) .initForGymLeader(signatureSpecies["FALKNER"], true, PokemonType.FLYING, false, -1)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.BUGSY]: new TrainerConfig(++t) [TrainerType.BUGSY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["BUGSY"], true, PokemonType.BUG) .initForGymLeader(signatureSpecies["BUGSY"], true, PokemonType.BUG, false, -1)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.WHITNEY]: new TrainerConfig(++t) [TrainerType.WHITNEY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["WHITNEY"], false, PokemonType.NORMAL) .initForGymLeader(signatureSpecies["WHITNEY"], false, PokemonType.NORMAL, false, -1)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.MORTY]: new TrainerConfig(++t) [TrainerType.MORTY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["MORTY"], true, PokemonType.GHOST) .initForGymLeader(signatureSpecies["MORTY"], true, PokemonType.GHOST, false, -1)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.CHUCK]: new TrainerConfig(++t) [TrainerType.CHUCK]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CHUCK"], true, PokemonType.FIGHTING) .initForGymLeader(signatureSpecies["CHUCK"], true, PokemonType.FIGHTING, false, -1)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.JASMINE]: new TrainerConfig(++t) [TrainerType.JASMINE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["JASMINE"], false, PokemonType.STEEL) .initForGymLeader(signatureSpecies["JASMINE"], false, PokemonType.STEEL, false, -1)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.PRYCE]: new TrainerConfig(++t) [TrainerType.PRYCE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["PRYCE"], true, PokemonType.ICE) .initForGymLeader(signatureSpecies["PRYCE"], true, PokemonType.ICE, false, -1)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.CLAIR]: new TrainerConfig(++t) [TrainerType.CLAIR]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CLAIR"], false, PokemonType.DRAGON) .initForGymLeader(signatureSpecies["CLAIR"], false, PokemonType.DRAGON, false, -3)
.setBattleBgm("battle_johto_gym") .setBattleBgm("battle_johto_gym")
.setMixedBattleBgm("battle_johto_gym"), .setMixedBattleBgm("battle_johto_gym"),
[TrainerType.ROXANNE]: new TrainerConfig(++t) [TrainerType.ROXANNE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["ROXANNE"], false, PokemonType.ROCK) .initForGymLeader(signatureSpecies["ROXANNE"], false, PokemonType.ROCK, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym"), .setMixedBattleBgm("battle_hoenn_gym"),
[TrainerType.BRAWLY]: new TrainerConfig(++t) [TrainerType.BRAWLY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["BRAWLY"], true, PokemonType.FIGHTING) .initForGymLeader(signatureSpecies["BRAWLY"], true, PokemonType.FIGHTING, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym"), .setMixedBattleBgm("battle_hoenn_gym"),
[TrainerType.WATTSON]: new TrainerConfig(++t) [TrainerType.WATTSON]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["WATTSON"], true, PokemonType.ELECTRIC) .initForGymLeader(signatureSpecies["WATTSON"], true, PokemonType.ELECTRIC, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym"), .setMixedBattleBgm("battle_hoenn_gym"),
[TrainerType.FLANNERY]: new TrainerConfig(++t) [TrainerType.FLANNERY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["FLANNERY"], false, PokemonType.FIRE) .initForGymLeader(signatureSpecies["FLANNERY"], false, PokemonType.FIRE, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym"), .setMixedBattleBgm("battle_hoenn_gym"),
[TrainerType.NORMAN]: new TrainerConfig(++t) [TrainerType.NORMAN]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["NORMAN"], true, PokemonType.NORMAL) .initForGymLeader(signatureSpecies["NORMAN"], true, PokemonType.NORMAL, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym"), .setMixedBattleBgm("battle_hoenn_gym"),
[TrainerType.WINONA]: new TrainerConfig(++t) [TrainerType.WINONA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["WINONA"], false, PokemonType.FLYING) .initForGymLeader(signatureSpecies["WINONA"], false, PokemonType.FLYING, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym"), .setMixedBattleBgm("battle_hoenn_gym"),
[TrainerType.TATE]: new TrainerConfig(++t) [TrainerType.TATE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["TATE"], true, PokemonType.PSYCHIC) .initForGymLeader(signatureSpecies["TATE"], true, PokemonType.PSYCHIC, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym") .setMixedBattleBgm("battle_hoenn_gym")
.setHasDouble("tate_liza_double") .setHasDouble("tate_liza_double")
.setDoubleTrainerType(TrainerType.LIZA) .setDoubleTrainerType(TrainerType.LIZA)
.setDoubleTitle("gym_leader_double"), .setDoubleTitle("gym_leader_double"),
[TrainerType.LIZA]: new TrainerConfig(++t) [TrainerType.LIZA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["LIZA"], false, PokemonType.PSYCHIC) .initForGymLeader(signatureSpecies["LIZA"], false, PokemonType.PSYCHIC, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym") .setMixedBattleBgm("battle_hoenn_gym")
.setHasDouble("liza_tate_double") .setHasDouble("liza_tate_double")
.setDoubleTrainerType(TrainerType.TATE) .setDoubleTrainerType(TrainerType.TATE)
.setDoubleTitle("gym_leader_double"), .setDoubleTitle("gym_leader_double"),
[TrainerType.JUAN]: new TrainerConfig(++t) [TrainerType.JUAN]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["JUAN"], true, PokemonType.WATER) .initForGymLeader(signatureSpecies["JUAN"], true, PokemonType.WATER, false, -1)
.setBattleBgm("battle_hoenn_gym") .setBattleBgm("battle_hoenn_gym")
.setMixedBattleBgm("battle_hoenn_gym"), .setMixedBattleBgm("battle_hoenn_gym"),
[TrainerType.ROARK]: new TrainerConfig(++t) [TrainerType.ROARK]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["ROARK"], true, PokemonType.ROCK) .initForGymLeader(signatureSpecies["ROARK"], true, PokemonType.ROCK, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.GARDENIA]: new TrainerConfig(++t) [TrainerType.GARDENIA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["GARDENIA"], false, PokemonType.GRASS) .initForGymLeader(signatureSpecies["GARDENIA"], false, PokemonType.GRASS, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.MAYLENE]: new TrainerConfig(++t) [TrainerType.MAYLENE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["MAYLENE"], false, PokemonType.FIGHTING) .initForGymLeader(signatureSpecies["MAYLENE"], false, PokemonType.FIGHTING, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.CRASHER_WAKE]: new TrainerConfig(++t) [TrainerType.CRASHER_WAKE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CRASHER_WAKE"], true, PokemonType.WATER) .initForGymLeader(signatureSpecies["CRASHER_WAKE"], true, PokemonType.WATER, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.FANTINA]: new TrainerConfig(++t) [TrainerType.FANTINA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["FANTINA"], false, PokemonType.GHOST) .initForGymLeader(signatureSpecies["FANTINA"], false, PokemonType.GHOST, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.BYRON]: new TrainerConfig(++t) [TrainerType.BYRON]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["BYRON"], true, PokemonType.STEEL) .initForGymLeader(signatureSpecies["BYRON"], true, PokemonType.STEEL, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.CANDICE]: new TrainerConfig(++t) [TrainerType.CANDICE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CANDICE"], false, PokemonType.ICE) .initForGymLeader(signatureSpecies["CANDICE"], false, PokemonType.ICE, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.VOLKNER]: new TrainerConfig(++t) [TrainerType.VOLKNER]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["VOLKNER"], true, PokemonType.ELECTRIC) .initForGymLeader(signatureSpecies["VOLKNER"], true, PokemonType.ELECTRIC, false, -1)
.setBattleBgm("battle_sinnoh_gym") .setBattleBgm("battle_sinnoh_gym")
.setMixedBattleBgm("battle_sinnoh_gym"), .setMixedBattleBgm("battle_sinnoh_gym"),
[TrainerType.CILAN]: new TrainerConfig(++t) [TrainerType.CILAN]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CILAN"], true, PokemonType.GRASS) .initForGymLeader(signatureSpecies["CILAN"], true, PokemonType.GRASS, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.CHILI]: new TrainerConfig(++t) [TrainerType.CHILI]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CHILI"], true, PokemonType.FIRE) .initForGymLeader(signatureSpecies["CHILI"], true, PokemonType.FIRE, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.CRESS]: new TrainerConfig(++t) [TrainerType.CRESS]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CRESS"], true, PokemonType.WATER) .initForGymLeader(signatureSpecies["CRESS"], true, PokemonType.WATER, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.CHEREN]: new TrainerConfig(++t) [TrainerType.CHEREN]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CHEREN"], true, PokemonType.NORMAL) .initForGymLeader(signatureSpecies["CHEREN"], true, PokemonType.NORMAL, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.LENORA]: new TrainerConfig(++t) [TrainerType.LENORA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["LENORA"], false, PokemonType.NORMAL) .initForGymLeader(signatureSpecies["LENORA"], false, PokemonType.NORMAL, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.ROXIE]: new TrainerConfig(++t) [TrainerType.ROXIE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["ROXIE"], false, PokemonType.POISON) .initForGymLeader(signatureSpecies["ROXIE"], false, PokemonType.POISON, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.BURGH]: new TrainerConfig(++t) [TrainerType.BURGH]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["BURGH"], true, PokemonType.BUG) .initForGymLeader(signatureSpecies["BURGH"], true, PokemonType.BUG, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.ELESA]: new TrainerConfig(++t) [TrainerType.ELESA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["ELESA"], false, PokemonType.ELECTRIC) .initForGymLeader(signatureSpecies["ELESA"], false, PokemonType.ELECTRIC, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.CLAY]: new TrainerConfig(++t) [TrainerType.CLAY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CLAY"], true, PokemonType.GROUND) .initForGymLeader(signatureSpecies["CLAY"], true, PokemonType.GROUND, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.SKYLA]: new TrainerConfig(++t) [TrainerType.SKYLA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["SKYLA"], false, PokemonType.FLYING) .initForGymLeader(signatureSpecies["SKYLA"], false, PokemonType.FLYING, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.BRYCEN]: new TrainerConfig(++t) [TrainerType.BRYCEN]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["BRYCEN"], true, PokemonType.ICE) .initForGymLeader(signatureSpecies["BRYCEN"], true, PokemonType.ICE, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.DRAYDEN]: new TrainerConfig(++t) [TrainerType.DRAYDEN]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["DRAYDEN"], true, PokemonType.DRAGON) .initForGymLeader(signatureSpecies["DRAYDEN"], true, PokemonType.DRAGON, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.MARLON]: new TrainerConfig(++t) [TrainerType.MARLON]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["MARLON"], true, PokemonType.WATER) .initForGymLeader(signatureSpecies["MARLON"], true, PokemonType.WATER, false, -1)
.setMixedBattleBgm("battle_unova_gym"), .setMixedBattleBgm("battle_unova_gym"),
[TrainerType.VIOLA]: new TrainerConfig(++t) [TrainerType.VIOLA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["VIOLA"], false, PokemonType.BUG) .initForGymLeader(signatureSpecies["VIOLA"], false, PokemonType.BUG, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.GRANT]: new TrainerConfig(++t) [TrainerType.GRANT]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["GRANT"], true, PokemonType.ROCK) .initForGymLeader(signatureSpecies["GRANT"], true, PokemonType.ROCK, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.KORRINA]: new TrainerConfig(++t) [TrainerType.KORRINA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["KORRINA"], false, PokemonType.FIGHTING) .initForGymLeader(signatureSpecies["KORRINA"], false, PokemonType.FIGHTING, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.RAMOS]: new TrainerConfig(++t) [TrainerType.RAMOS]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["RAMOS"], true, PokemonType.GRASS) .initForGymLeader(signatureSpecies["RAMOS"], true, PokemonType.GRASS, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.CLEMONT]: new TrainerConfig(++t) [TrainerType.CLEMONT]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["CLEMONT"], true, PokemonType.ELECTRIC) .initForGymLeader(signatureSpecies["CLEMONT"], true, PokemonType.ELECTRIC, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.VALERIE]: new TrainerConfig(++t) [TrainerType.VALERIE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["VALERIE"], false, PokemonType.FAIRY) .initForGymLeader(signatureSpecies["VALERIE"], false, PokemonType.FAIRY, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.OLYMPIA]: new TrainerConfig(++t) [TrainerType.OLYMPIA]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["OLYMPIA"], false, PokemonType.PSYCHIC) .initForGymLeader(signatureSpecies["OLYMPIA"], false, PokemonType.PSYCHIC, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.WULFRIC]: new TrainerConfig(++t) [TrainerType.WULFRIC]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["WULFRIC"], true, PokemonType.ICE) .initForGymLeader(signatureSpecies["WULFRIC"], true, PokemonType.ICE, false, -1)
.setMixedBattleBgm("battle_kalos_gym"), .setMixedBattleBgm("battle_kalos_gym"),
[TrainerType.MILO]: new TrainerConfig(++t) [TrainerType.MILO]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["MILO"], true, PokemonType.GRASS) .initForGymLeader(signatureSpecies["MILO"], true, PokemonType.GRASS, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.NESSA]: new TrainerConfig(++t) [TrainerType.NESSA]: new TrainerConfig(++t)
.setName("Nessa") .setName("Nessa")
.initForGymLeader(signatureSpecies["NESSA"], false, PokemonType.WATER) .initForGymLeader(signatureSpecies["NESSA"], false, PokemonType.WATER, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.KABU]: new TrainerConfig(++t) [TrainerType.KABU]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["KABU"], true, PokemonType.FIRE) .initForGymLeader(signatureSpecies["KABU"], true, PokemonType.FIRE, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.BEA]: new TrainerConfig(++t) [TrainerType.BEA]: new TrainerConfig(++t)
.setName("Bea") .setName("Bea")
.initForGymLeader(signatureSpecies["BEA"], false, PokemonType.FIGHTING) .initForGymLeader(signatureSpecies["BEA"], false, PokemonType.FIGHTING, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.ALLISTER]: new TrainerConfig(++t) [TrainerType.ALLISTER]: new TrainerConfig(++t)
.setName("Allister") .setName("Allister")
.initForGymLeader(signatureSpecies["ALLISTER"], true, PokemonType.GHOST) .initForGymLeader(signatureSpecies["ALLISTER"], true, PokemonType.GHOST, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.OPAL]: new TrainerConfig(++t) [TrainerType.OPAL]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["OPAL"], false, PokemonType.FAIRY) .initForGymLeader(signatureSpecies["OPAL"], false, PokemonType.FAIRY, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.BEDE]: new TrainerConfig(++t) [TrainerType.BEDE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["BEDE"], true, PokemonType.FAIRY) .initForGymLeader(signatureSpecies["BEDE"], true, PokemonType.FAIRY, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.GORDIE]: new TrainerConfig(++t) [TrainerType.GORDIE]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["GORDIE"], true, PokemonType.ROCK) .initForGymLeader(signatureSpecies["GORDIE"], true, PokemonType.ROCK, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.MELONY]: new TrainerConfig(++t) [TrainerType.MELONY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["MELONY"], false, PokemonType.ICE) .initForGymLeader(signatureSpecies["MELONY"], false, PokemonType.ICE, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.PIERS]: new TrainerConfig(++t) [TrainerType.PIERS]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["PIERS"], true, PokemonType.DARK) .initForGymLeader(signatureSpecies["PIERS"], true, PokemonType.DARK, false, -3)
.setHasDouble("piers_marnie_double") .setHasDouble("piers_marnie_double")
.setDoubleTrainerType(TrainerType.MARNIE) .setDoubleTrainerType(TrainerType.MARNIE)
.setDoubleTitle("gym_leader_double") .setDoubleTitle("gym_leader_double")
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.MARNIE]: new TrainerConfig(++t) [TrainerType.MARNIE]: new TrainerConfig(++t)
.setName("Marnie") .setName("Marnie")
.initForGymLeader(signatureSpecies["MARNIE"], false, PokemonType.DARK) .initForGymLeader(signatureSpecies["MARNIE"], false, PokemonType.DARK, false, -4)
.setHasDouble("marnie_piers_double") .setHasDouble("marnie_piers_double")
.setDoubleTrainerType(TrainerType.PIERS) .setDoubleTrainerType(TrainerType.PIERS)
.setDoubleTitle("gym_leader_double") .setDoubleTitle("gym_leader_double")
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.RAIHAN]: new TrainerConfig(++t) [TrainerType.RAIHAN]: new TrainerConfig(++t)
.setName("Raihan") .setName("Raihan")
.initForGymLeader(signatureSpecies["RAIHAN"], true, PokemonType.DRAGON) .initForGymLeader(signatureSpecies["RAIHAN"], true, PokemonType.DRAGON, false, -1)
.setMixedBattleBgm("battle_galar_gym"), .setMixedBattleBgm("battle_galar_gym"),
[TrainerType.KATY]: new TrainerConfig(++t) [TrainerType.KATY]: new TrainerConfig(++t)
.initForGymLeader(signatureSpecies["KATY"], false, PokemonType.BUG, true, -1) .initForGymLeader(signatureSpecies["KATY"], false, PokemonType.BUG, true, -1)

View File

@ -5,7 +5,7 @@ import type Pokemon from "../field/pokemon";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
import type Move from "./moves/move"; import type Move from "./moves/move";
import { AttackMove } from "./moves/move"; import { AttackMove } from "./moves/move";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils/common";
import { SuppressWeatherEffectAbAttr } from "./abilities/ability"; import { SuppressWeatherEffectAbAttr } from "./abilities/ability";
import { TerrainType, getTerrainName } from "./terrain"; import { TerrainType, getTerrainName } from "./terrain";
import i18next from "i18next"; import i18next from "i18next";

6
src/enums/battle-type.ts Normal file
View File

@ -0,0 +1,6 @@
export enum BattleType {
WILD,
TRAINER,
CLEAR,
MYSTERY_ENCOUNTER
}

47
src/enums/ui-mode.ts Normal file
View File

@ -0,0 +1,47 @@
export enum UiMode {
MESSAGE,
TITLE,
COMMAND,
FIGHT,
BALL,
TARGET_SELECT,
MODIFIER_SELECT,
SAVE_SLOT,
PARTY,
SUMMARY,
STARTER_SELECT,
EVOLUTION_SCENE,
EGG_HATCH_SCENE,
EGG_HATCH_SUMMARY,
CONFIRM,
OPTION_SELECT,
MENU,
MENU_OPTION_SELECT,
SETTINGS,
SETTINGS_DISPLAY,
SETTINGS_AUDIO,
SETTINGS_GAMEPAD,
GAMEPAD_BINDING,
SETTINGS_KEYBOARD,
KEYBOARD_BINDING,
ACHIEVEMENTS,
GAME_STATS,
EGG_LIST,
EGG_GACHA,
POKEDEX,
POKEDEX_SCAN,
POKEDEX_PAGE,
LOGIN_FORM,
REGISTRATION_FORM,
LOADING,
SESSION_RELOAD,
UNAVAILABLE,
CHALLENGE_SELECT,
RENAME_POKEMON,
RUN_HISTORY,
RUN_INFO,
TEST_DIALOGUE,
AUTO_COMPLETE,
ADMIN,
MYSTERY_ENCOUNTER
}

View File

@ -1,7 +1,7 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { PokeballType } from "#enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import type { Variant } from "#app/sprites/variant"; import type { Variant } from "#app/sprites/variant";
import { getFrameMs, randGauss } from "#app/utils"; import { getFrameMs, randGauss } from "#app/utils/common";
export function addPokeballOpenParticles(x: number, y: number, pokeballType: PokeballType): void { export function addPokeballOpenParticles(x: number, y: number, pokeballType: PokeballType): void {
switch (pokeballType) { switch (pokeballType) {

View File

@ -1,7 +1,7 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type { BiomeTierTrainerPools, PokemonPools } from "#app/data/balance/biomes"; import type { BiomeTierTrainerPools, PokemonPools } from "#app/data/balance/biomes";
import { biomePokemonPools, BiomePoolTier, biomeTrainerPools } from "#app/data/balance/biomes"; import { biomePokemonPools, BiomePoolTier, biomeTrainerPools } from "#app/data/balance/biomes";
import { randSeedInt, NumberHolder, isNullOrUndefined, type Constructor } from "#app/utils"; import { randSeedInt, NumberHolder, isNullOrUndefined, type Constructor } from "#app/utils/common";
import type PokemonSpecies from "#app/data/pokemon-species"; import type PokemonSpecies from "#app/data/pokemon-species";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { import {

View File

@ -2,7 +2,7 @@ import { TextStyle, addTextObject } from "../ui/text";
import type { DamageResult } from "./pokemon"; import type { DamageResult } from "./pokemon";
import type Pokemon from "./pokemon"; import type Pokemon from "./pokemon";
import { HitResult } from "./pokemon"; import { HitResult } from "./pokemon";
import { formatStat, fixedInt } from "#app/utils"; import { formatStat, fixedInt } from "#app/utils/common";
import type { BattlerIndex } from "../battle"; import type { BattlerIndex } from "../battle";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -2,7 +2,7 @@ import type { GameObjects } from "phaser";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import type MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter";
import type { Species } from "#enums/species"; import type { Species } from "#enums/species";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils";
import type { Variant } from "#app/sprites/variant"; import type { Variant } from "#app/sprites/variant";
import { doShinySparkleAnim } from "#app/field/anims"; import { doShinySparkleAnim } from "#app/field/anims";

View File

@ -1,6 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import Pokemon from "./pokemon"; import Pokemon from "./pokemon";
import { fixedInt, randInt } from "#app/utils"; import { fixedInt, randInt } from "#app/utils/common";
export default class PokemonSpriteSparkleHandler { export default class PokemonSpriteSparkleHandler {
private sprites: Set<Phaser.GameObjects.Sprite>; private sprites: Set<Phaser.GameObjects.Sprite>;

View File

@ -55,7 +55,7 @@ import {
getStarterValueFriendshipCap, getStarterValueFriendshipCap,
speciesStarterCosts, speciesStarterCosts,
} from "#app/data/balance/starters"; } from "#app/data/balance/starters";
import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor } from "#app/utils"; import { NumberHolder, randSeedInt, getIvsFromId, BooleanHolder, randSeedItem, isNullOrUndefined, getEnumValues, toDmgValue, fixedInt, rgbaToInt, rgbHexToRgba, rgbToHsv, deltaRgb, isBetween, type nil, type Constructor } from "#app/utils/common";
import type { TypeDamageMultiplier } from "#app/data/type"; import type { TypeDamageMultiplier } from "#app/data/type";
import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type"; import { getTypeDamageMultiplier, getTypeRgb } from "#app/data/type";
import { PokemonType } from "#enums/pokemon-type"; import { PokemonType } from "#enums/pokemon-type";
@ -129,6 +129,7 @@ import {
AutotomizedTag, AutotomizedTag,
PowerTrickTag, PowerTrickTag,
loadBattlerTag, loadBattlerTag,
type GrudgeTag,
} from "../data/battler-tags"; } from "../data/battler-tags";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { import {
@ -193,7 +194,7 @@ import {
import { allAbilities } from "#app/data/data-lists"; import { allAbilities } from "#app/data/data-lists";
import type PokemonData from "#app/system/pokemon-data"; import type PokemonData from "#app/system/pokemon-data";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import type { PartyOption } from "#app/ui/party-ui-handler"; import type { PartyOption } from "#app/ui/party-ui-handler";
import PartyUiHandler, { PartyUiMode } from "#app/ui/party-ui-handler"; import PartyUiHandler, { PartyUiMode } from "#app/ui/party-ui-handler";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
@ -857,12 +858,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
await Promise.allSettled(loadPromises); await Promise.allSettled(loadPromises);
// Wait for the assets we queued to load to finish loading, then... // This must be initiated before we queue loading, otherwise the load could have finished before
// we reach the line of code that adds the listener, causing a deadlock.
const waitOnLoadPromise = new Promise<void>(resolve => globalScene.load.once(Phaser.Loader.Events.COMPLETE, resolve));
if (!globalScene.load.isLoading()) { if (!globalScene.load.isLoading()) {
globalScene.load.start(); globalScene.load.start();
} }
// Wait for the assets we queued to load to finish loading, then...
// See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#creating_a_promise_around_an_old_callback_api // See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises#creating_a_promise_around_an_old_callback_api
await new Promise(resolve => globalScene.load.once(Phaser.Loader.Events.COMPLETE, resolve)); await waitOnLoadPromise;
// With the sprites loaded, generate the animation frame information // With the sprites loaded, generate the animation frame information
if (this.isPlayer()) { if (this.isPlayer()) {
@ -1119,9 +1125,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @param useIllusion - `true` to use the speciesForm of the illusion; default `false`. * @param useIllusion - `true` to use the speciesForm of the illusion; default `false`.
*/ */
getSpeciesForm(ignoreOverride: boolean = false, useIllusion: boolean = false): PokemonSpeciesForm { getSpeciesForm(ignoreOverride: boolean = false, useIllusion: boolean = false): PokemonSpeciesForm {
const species: PokemonSpecies = useIllusion && !!this.summonData.illusion ? getPokemonSpecies(this.summonData.illusion.species) : this.species; const species: PokemonSpecies = useIllusion && this.summonData.illusion ? getPokemonSpecies(this.summonData.illusion.species) : this.species;
const formIndex: integer = useIllusion && this.summonData.illusion ? this.summonData.illusion.formIndex : this.formIndex;
const formIndex: integer = useIllusion && !!this.summonData.illusion ? this.summonData.illusion.formIndex : this.formIndex;
if (!ignoreOverride && this.summonData.speciesForm) { if (!ignoreOverride && this.summonData.speciesForm) {
return this.summonData.speciesForm; return this.summonData.speciesForm;
@ -3867,12 +3872,17 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return null; return null;
} }
getOpponents(): Pokemon[] { /**
* Returns the pokemon that oppose this one and are active
*
* @param onField - whether to also check if the pokemon is currently on the field (defaults to true)
*/
getOpponents(onField = true): Pokemon[] {
return ( return (
(this.isPlayer() (this.isPlayer()
? globalScene.getEnemyField() ? globalScene.getEnemyField()
: globalScene.getPlayerField()) as Pokemon[] : globalScene.getPlayerField()) as Pokemon[]
).filter(p => p.isActive()); ).filter(p => p.isActive(onField));
} }
getOpponentDescriptor(): string { getOpponentDescriptor(): string {
@ -4171,6 +4181,62 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return baseDamage; return baseDamage;
} }
/** Determine the STAB multiplier for a move used against this pokemon.
*
* @param source - The attacking {@linkcode Pokemon}
* @param move - The {@linkcode Move} used in the attack
* @param ignoreSourceAbility - If `true`, ignores the attacking Pokemon's ability effects
* @param simulated - If `true`, suppresses changes to game state during the calculation
*
* @returns The STAB multiplier for the move used against this Pokemon
*/
calculateStabMultiplier(source: Pokemon, move: Move, ignoreSourceAbility: boolean, simulated: boolean): number {
// If the move has the Typeless attribute, it doesn't get STAB (e.g. struggle)
if (move.hasAttr(TypelessAttr)) {
return 1;
}
const sourceTypes = source.getTypes();
const sourceTeraType = source.getTeraType();
const moveType = source.getMoveType(move);
const matchesSourceType = sourceTypes.includes(source.getMoveType(move));
const stabMultiplier = new NumberHolder(1);
if (matchesSourceType && moveType !== PokemonType.STELLAR) {
stabMultiplier.value += 0.5;
}
applyMoveAttrs(
CombinedPledgeStabBoostAttr,
source,
this,
move,
stabMultiplier,
);
if (!ignoreSourceAbility) {
applyAbAttrs(StabBoostAbAttr, source, null, simulated, stabMultiplier);
}
if (
source.isTerastallized &&
sourceTeraType === moveType &&
moveType !== PokemonType.STELLAR
) {
stabMultiplier.value += 0.5;
}
if (
source.isTerastallized &&
source.getTeraType() === PokemonType.STELLAR &&
(!source.stellarTypesBoosted.includes(moveType) ||
source.hasSpecies(Species.TERAPAGOS))
) {
stabMultiplier.value += matchesSourceType ? 0.5 : 0.2;
}
return Math.min(stabMultiplier.value, 2.25);
}
/** /**
* Calculates the damage of an attack made by another Pokemon against this Pokemon * Calculates the damage of an attack made by another Pokemon against this Pokemon
* @param source {@linkcode Pokemon} the attacking Pokemon * @param source {@linkcode Pokemon} the attacking Pokemon
@ -4353,70 +4419,29 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
? 1 ? 1
: this.randSeedIntRange(85, 100) / 100; : this.randSeedIntRange(85, 100) / 100;
const sourceTypes = source.getTypes();
const sourceTeraType = source.getTeraType();
const matchesSourceType = sourceTypes.includes(moveType);
/** A damage multiplier for when the attack is of the attacker's type and/or Tera type. */ /** A damage multiplier for when the attack is of the attacker's type and/or Tera type. */
const stabMultiplier = new NumberHolder(1); const stabMultiplier = this.calculateStabMultiplier(source, move, ignoreSourceAbility, simulated);
if (matchesSourceType && moveType !== PokemonType.STELLAR) {
stabMultiplier.value += 0.5;
}
if (!ignoreSourceAbility) {
applyAbAttrs(StabBoostAbAttr, source, null, simulated, stabMultiplier);
}
applyMoveAttrs(
CombinedPledgeStabBoostAttr,
source,
this,
move,
stabMultiplier,
);
if (
source.isTerastallized &&
sourceTeraType === moveType &&
moveType !== PokemonType.STELLAR
) {
stabMultiplier.value += 0.5;
}
if (
source.isTerastallized &&
source.getTeraType() === PokemonType.STELLAR &&
(!source.stellarTypesBoosted.includes(moveType) ||
source.hasSpecies(Species.TERAPAGOS))
) {
if (matchesSourceType) {
stabMultiplier.value += 0.5;
} else {
stabMultiplier.value += 0.2;
}
}
stabMultiplier.value = Math.min(stabMultiplier.value, 2.25);
/** Halves damage if the attacker is using a physical attack while burned */ /** Halves damage if the attacker is using a physical attack while burned */
const burnMultiplier = new NumberHolder(1); let burnMultiplier = 1;
if ( if (
isPhysical && isPhysical &&
source.status && source.status &&
source.status.effect === StatusEffect.BURN source.status.effect === StatusEffect.BURN &&
!move.hasAttr(BypassBurnDamageReductionAttr)
) { ) {
if (!move.hasAttr(BypassBurnDamageReductionAttr)) { const burnDamageReductionCancelled = new BooleanHolder(false);
const burnDamageReductionCancelled = new BooleanHolder(false); if (!ignoreSourceAbility) {
if (!ignoreSourceAbility) { applyAbAttrs(
applyAbAttrs( BypassBurnDamageReductionAbAttr,
BypassBurnDamageReductionAbAttr, source,
source, burnDamageReductionCancelled,
burnDamageReductionCancelled, simulated,
simulated, );
); }
} if (!burnDamageReductionCancelled.value) {
if (!burnDamageReductionCancelled.value) { burnMultiplier = 0.5;
burnMultiplier.value = 0.5;
}
} }
} }
@ -4467,9 +4492,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
glaiveRushMultiplier.value * glaiveRushMultiplier.value *
criticalMultiplier.value * criticalMultiplier.value *
randomMultiplier * randomMultiplier *
stabMultiplier.value * stabMultiplier *
typeMultiplier * typeMultiplier *
burnMultiplier.value * burnMultiplier *
screenMultiplier.value * screenMultiplier.value *
hitsTagMultiplier.value * hitsTagMultiplier.value *
mistyTerrainMultiplier, mistyTerrainMultiplier,
@ -4754,15 +4779,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
new FaintPhase( new FaintPhase(
this.getBattlerIndex(), this.getBattlerIndex(),
false, false,
destinyTag,
grudgeTag,
source, source,
), ),
); );
this.destroySubstitute(); this.destroySubstitute();
this.lapseTag(BattlerTagType.COMMANDED); this.lapseTag(BattlerTagType.COMMANDED);
this.resetSummonData();
} }
return result; return result;
@ -4825,7 +4847,6 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
); );
this.destroySubstitute(); this.destroySubstitute();
this.lapseTag(BattlerTagType.COMMANDED); this.lapseTag(BattlerTagType.COMMANDED);
this.resetSummonData();
} }
return damage; return damage;
} }
@ -4993,6 +5014,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return false; return false;
} }
/**@overload */
getTag(tagType: BattlerTagType.GRUDGE): GrudgeTag | nil;
/** @overload */ /** @overload */
getTag(tagType: BattlerTagType): BattlerTag | undefined; getTag(tagType: BattlerTagType): BattlerTag | undefined;
@ -5284,13 +5308,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
sceneOverride?: BattleScene, sceneOverride?: BattleScene,
): AnySound { ): AnySound {
const scene = sceneOverride ?? globalScene; // TODO: is `sceneOverride` needed? const scene = sceneOverride ?? globalScene; // TODO: is `sceneOverride` needed?
const cry = this.getSpeciesForm().cry(soundConfig); const cry = this.getSpeciesForm(undefined, true).cry(soundConfig);
let duration = cry.totalDuration * 1000; let duration = cry.totalDuration * 1000;
if ( if (
this.fusionSpecies && this.fusionSpecies &&
this.getSpeciesForm() !== this.getFusionSpeciesForm() this.getSpeciesForm(undefined, true) !== this.getFusionSpeciesForm(undefined, true)
) { ) {
let fusionCry = this.getFusionSpeciesForm().cry(soundConfig, true); let fusionCry = this.getFusionSpeciesForm(undefined, true).cry(soundConfig, true);
duration = Math.min(duration, fusionCry.totalDuration * 1000); duration = Math.min(duration, fusionCry.totalDuration * 1000);
fusionCry.destroy(); fusionCry.destroy();
scene.time.delayedCall(fixedInt(Math.ceil(duration * 0.4)), () => { scene.time.delayedCall(fixedInt(Math.ceil(duration * 0.4)), () => {
@ -5300,7 +5324,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
cry, cry,
fixedInt(Math.ceil(duration * 0.2)), fixedInt(Math.ceil(duration * 0.2)),
); );
fusionCry = this.getFusionSpeciesForm().cry( fusionCry = this.getFusionSpeciesForm(undefined, true).cry(
Object.assign( Object.assign(
{ seek: Math.max(fusionCry.totalDuration * 0.4, 0) }, { seek: Math.max(fusionCry.totalDuration * 0.4, 0) },
soundConfig, soundConfig,
@ -6606,7 +6630,7 @@ export class PlayerPokemon extends Pokemon {
this.leaveField(switchType === SwitchType.SWITCH); this.leaveField(switchType === SwitchType.SWITCH);
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.PARTY, UiMode.PARTY,
PartyUiMode.FAINT_SWITCH, PartyUiMode.FAINT_SWITCH,
this.getFieldIndex(), this.getFieldIndex(),
(slotIndex: number, option: PartyOption) => { (slotIndex: number, option: PartyOption) => {
@ -6624,7 +6648,7 @@ export class PlayerPokemon extends Pokemon {
MoveEndPhase, MoveEndPhase,
); );
} }
globalScene.ui.setMode(Mode.MESSAGE).then(resolve); globalScene.ui.setMode(UiMode.MESSAGE).then(resolve);
}, },
PartyUiHandler.FilterNonFainted, PartyUiHandler.FilterNonFainted,
); );
@ -7184,8 +7208,8 @@ export class EnemyPokemon extends Pokemon {
initBattleInfo(): void { initBattleInfo(): void {
if (!this.battleInfo) { if (!this.battleInfo) {
this.battleInfo = new EnemyBattleInfo(); this.battleInfo = new EnemyBattleInfo();
this.battleInfo.updateBossSegments(this);
this.battleInfo.initInfo(this); this.battleInfo.initInfo(this);
this.battleInfo.updateBossSegments(this);
} else { } else {
this.battleInfo.updateBossSegments(this); this.battleInfo.updateBossSegments(this);
} }

View File

@ -11,7 +11,7 @@ import { TrainerSlot } from "#enums/trainer-slot";
import { TrainerPoolTier } from "#enums/trainer-pool-tier"; import { TrainerPoolTier } from "#enums/trainer-pool-tier";
import { TeraAIMode } from "#enums/tera-ai-mode"; import { TeraAIMode } from "#enums/tera-ai-mode";
import type { EnemyPokemon } from "#app/field/pokemon"; import type { EnemyPokemon } from "#app/field/pokemon";
import { randSeedWeightedItem, randSeedItem, randSeedInt } from "#app/utils"; import { randSeedWeightedItem, randSeedItem, randSeedInt } from "#app/utils/common";
import type { PersistentModifier } from "#app/modifier/modifier"; import type { PersistentModifier } from "#app/modifier/modifier";
import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag";
import { getIsInitialized, initI18n } from "#app/plugins/i18n"; import { getIsInitialized, initI18n } from "#app/plugins/i18n";
@ -223,6 +223,13 @@ export default class Trainer extends Phaser.GameObjects.Container {
return this.config.doubleOnly || this.variant === TrainerVariant.DOUBLE; return this.config.doubleOnly || this.variant === TrainerVariant.DOUBLE;
} }
/**
* Return whether the trainer is a duo, like Tate & Liza
*/
isPartner(): boolean {
return this.variant === TrainerVariant.DOUBLE;
}
getMixedBattleBgm(): string { getMixedBattleBgm(): string {
return this.config.mixedBattleBgm; return this.config.mixedBattleBgm;
} }

View File

@ -7,7 +7,7 @@ import type PokemonSpecies from "./data/pokemon-species";
import { allSpecies } from "./data/pokemon-species"; import { allSpecies } from "./data/pokemon-species";
import type { Arena } from "./field/arena"; import type { Arena } from "./field/arena";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { randSeedInt, randSeedItem } from "#app/utils"; import { randSeedInt, randSeedItem } from "#app/utils/common";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { Challenges } from "./enums/challenges"; import { Challenges } from "./enums/challenges";

View File

@ -0,0 +1 @@
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";

View File

@ -0,0 +1,4 @@
export const starterColors: StarterColors = {};
interface StarterColors {
[key: string]: [string, string];
}

View File

@ -1,11 +1,11 @@
import Phaser from "phaser"; import Phaser from "phaser";
import { deepCopy, getEnumValues } from "#app/utils"; import { deepCopy, getEnumValues } from "#app/utils/common";
import pad_generic from "./configs/inputs/pad_generic"; import pad_generic from "./configs/inputs/pad_generic";
import pad_unlicensedSNES from "./configs/inputs/pad_unlicensedSNES"; import pad_unlicensedSNES from "./configs/inputs/pad_unlicensedSNES";
import pad_xbox360 from "./configs/inputs/pad_xbox360"; import pad_xbox360 from "./configs/inputs/pad_xbox360";
import pad_dualshock from "./configs/inputs/pad_dualshock"; import pad_dualshock from "./configs/inputs/pad_dualshock";
import pad_procon from "./configs/inputs/pad_procon"; import pad_procon from "./configs/inputs/pad_procon";
import { Mode } from "./ui/ui"; import { UiMode } from "#enums/ui-mode";
import type SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler"; import type SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler";
import type SettingsKeyboardUiHandler from "./ui/settings/settings-keyboard-ui-handler"; import type SettingsKeyboardUiHandler from "./ui/settings/settings-keyboard-ui-handler";
import cfg_keyboard_qwerty from "./configs/inputs/cfg_keyboard_qwerty"; import cfg_keyboard_qwerty from "./configs/inputs/cfg_keyboard_qwerty";
@ -235,7 +235,7 @@ export class InputsController {
if (gamepadName) { if (gamepadName) {
this.selectedDevice[Device.GAMEPAD] = gamepadName.toLowerCase(); this.selectedDevice[Device.GAMEPAD] = gamepadName.toLowerCase();
} }
const handler = globalScene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler; const handler = globalScene.ui?.handlers[UiMode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler;
handler?.updateChosenGamepadDisplay(); handler?.updateChosenGamepadDisplay();
} }
@ -248,7 +248,7 @@ export class InputsController {
if (layoutKeyboard) { if (layoutKeyboard) {
this.selectedDevice[Device.KEYBOARD] = layoutKeyboard.toLowerCase(); this.selectedDevice[Device.KEYBOARD] = layoutKeyboard.toLowerCase();
} }
const handler = globalScene.ui?.handlers[Mode.SETTINGS_KEYBOARD] as SettingsKeyboardUiHandler; const handler = globalScene.ui?.handlers[UiMode.SETTINGS_KEYBOARD] as SettingsKeyboardUiHandler;
handler?.updateChosenKeyboardDisplay(); handler?.updateChosenKeyboardDisplay();
} }
@ -296,7 +296,7 @@ export class InputsController {
globalScene.gameData?.saveMappingConfigs(gamepadID, this.configs[gamepadID]); globalScene.gameData?.saveMappingConfigs(gamepadID, this.configs[gamepadID]);
} }
this.lastSource = "gamepad"; this.lastSource = "gamepad";
const handler = globalScene.ui?.handlers[Mode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler; const handler = globalScene.ui?.handlers[UiMode.SETTINGS_GAMEPAD] as SettingsGamepadUiHandler;
handler?.updateChosenGamepadDisplay(); handler?.updateChosenGamepadDisplay();
} }
@ -406,7 +406,7 @@ export class InputsController {
this.lastSource = "gamepad"; this.lastSource = "gamepad";
if ( if (
!this.selectedDevice[Device.GAMEPAD] || !this.selectedDevice[Device.GAMEPAD] ||
(globalScene.ui.getMode() !== Mode.GAMEPAD_BINDING && (globalScene.ui.getMode() !== UiMode.GAMEPAD_BINDING &&
this.selectedDevice[Device.GAMEPAD] !== pad.id.toLowerCase()) this.selectedDevice[Device.GAMEPAD] !== pad.id.toLowerCase())
) { ) {
this.setChosenGamepad(pad.id); this.setChosenGamepad(pad.id);

View File

@ -4,7 +4,7 @@ import CacheBustedLoaderPlugin from "#app/plugins/cache-busted-loader-plugin";
import { SceneBase } from "#app/scene-base"; import { SceneBase } from "#app/scene-base";
import { WindowVariant, getWindowVariantSuffix } from "#app/ui/ui-theme"; import { WindowVariant, getWindowVariantSuffix } from "#app/ui/ui-theme";
import { isMobile } from "#app/touch-controls"; import { isMobile } from "#app/touch-controls";
import { localPing, getEnumValues, hasAllLocalizedSprites, getEnumKeys } from "#app/utils"; import { localPing, getEnumValues, hasAllLocalizedSprites, getEnumKeys } from "#app/utils/common";
import { initPokemonPrevolutions, initPokemonStarters } from "#app/data/balance/pokemon-evolutions"; import { initPokemonPrevolutions, initPokemonStarters } from "#app/data/balance/pokemon-evolutions";
import { initBiomes } from "#app/data/balance/biomes"; import { initBiomes } from "#app/data/balance/biomes";
import { initEggMoves } from "#app/data/balance/egg-moves"; import { initEggMoves } from "#app/data/balance/egg-moves";

View File

@ -114,7 +114,7 @@ import {
NumberHolder, NumberHolder,
padInt, padInt,
randSeedInt, randSeedInt,
} from "#app/utils"; } from "#app/utils/common";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";

View File

@ -15,7 +15,7 @@ import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
import type { VoucherType } from "#app/system/voucher"; import type { VoucherType } from "#app/system/voucher";
import { Command } from "#app/ui/command-ui-handler"; import { Command } from "#app/ui/command-ui-handler";
import { addTextObject, TextStyle } from "#app/ui/text"; import { addTextObject, TextStyle } from "#app/ui/text";
import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, toDmgValue } from "#app/utils"; import { BooleanHolder, hslToHex, isNullOrUndefined, NumberHolder, toDmgValue } from "#app/utils/common";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";
import type { Moves } from "#enums/moves"; import type { Moves } from "#enums/moves";

View File

@ -2,10 +2,11 @@ import { type PokeballCounts } from "#app/battle-scene";
import { EvolutionItem } from "#app/data/balance/pokemon-evolutions"; import { EvolutionItem } from "#app/data/balance/pokemon-evolutions";
import { Gender } from "#app/data/gender"; import { Gender } from "#app/data/gender";
import { FormChangeItem } from "#app/data/pokemon-forms"; import { FormChangeItem } from "#app/data/pokemon-forms";
import { Variant } from "#app/sprites/variant";
import { type ModifierOverride } from "#app/modifier/modifier-type"; import { type ModifierOverride } from "#app/modifier/modifier-type";
import { Variant } from "#app/sprites/variant";
import { Unlockables } from "#app/system/unlockables"; import { Unlockables } from "#app/system/unlockables";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { BattleType } from "#enums/battle-type";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { EggTier } from "#enums/egg-type"; import { EggTier } from "#enums/egg-type";
@ -18,6 +19,7 @@ import { Species } from "#enums/species";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { TimeOfDay } from "#enums/time-of-day"; import { TimeOfDay } from "#enums/time-of-day";
import { TrainerType } from "#enums/trainer-type";
import { VariantTier } from "#enums/variant-tier"; import { VariantTier } from "#enums/variant-tier";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
@ -41,7 +43,7 @@ import { WeatherType } from "#enums/weather-type";
* } * }
* ``` * ```
*/ */
const overrides = {} satisfies Partial<InstanceType<typeof DefaultOverrides>>; const overrides = {} satisfies Partial<InstanceType<OverridesType>>;
/** /**
* If you need to add Overrides values for local testing do that inside {@linkcode overrides} * If you need to add Overrides values for local testing do that inside {@linkcode overrides}
@ -69,7 +71,7 @@ class DefaultOverrides {
* *
* If `"odd-doubles"`, follow the `"double"` rule on odd wave numbers, and follow the `"single"` rule on even wave numbers. * If `"odd-doubles"`, follow the `"double"` rule on odd wave numbers, and follow the `"single"` rule on even wave numbers.
*/ */
readonly BATTLE_TYPE_OVERRIDE: BattleStyle | null = null; readonly BATTLE_STYLE_OVERRIDE: BattleStyle | null = null;
readonly STARTING_WAVE_OVERRIDE: number = 0; readonly STARTING_WAVE_OVERRIDE: number = 0;
readonly STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN; readonly STARTING_BIOME_OVERRIDE: Biome = Biome.TOWN;
readonly ARENA_TINT_OVERRIDE: TimeOfDay | null = null; readonly ARENA_TINT_OVERRIDE: TimeOfDay | null = null;
@ -267,6 +269,16 @@ class DefaultOverrides {
* If `true`, disable all non-scripted opponent trainer encounters. * If `true`, disable all non-scripted opponent trainer encounters.
*/ */
readonly DISABLE_STANDARD_TRAINERS_OVERRIDE: boolean = false; readonly DISABLE_STANDARD_TRAINERS_OVERRIDE: boolean = false;
/**
* Set all non-scripted waves to use the selected battle type.
*
* Ignored if set to {@linkcode BattleType.TRAINER} and `DISABLE_STANDARD_TRAINERS_OVERRIDE` is `true`.
*/
readonly BATTLE_TYPE_OVERRIDE: Exclude<BattleType, BattleType.CLEAR> | null = null;
/** Force all random trainer types to be the provided type. */
readonly RANDOM_TRAINER_OVERRIDE: RandomTrainerOverride | null = null;
} }
export const defaultOverrides = new DefaultOverrides(); export const defaultOverrides = new DefaultOverrides();
@ -277,3 +289,13 @@ export default {
} satisfies InstanceType<typeof DefaultOverrides>; } satisfies InstanceType<typeof DefaultOverrides>;
export type BattleStyle = "double" | "single" | "even-doubles" | "odd-doubles"; export type BattleStyle = "double" | "single" | "even-doubles" | "odd-doubles";
export type RandomTrainerOverride = {
/** The Type of trainer to force */
trainerType: Exclude<TrainerType, TrainerType.UNKNOWN>,
/* If the selected trainer type has a double version, it will always use its double version. */
alwaysDouble?: boolean
}
/** The type of the {@linkcode DefaultOverrides} class */
export type OverridesType = typeof DefaultOverrides;

View File

@ -19,7 +19,7 @@ import { achvs } from "#app/system/achv";
import type { PartyOption } from "#app/ui/party-ui-handler"; import type { PartyOption } from "#app/ui/party-ui-handler";
import { PartyUiMode } from "#app/ui/party-ui-handler"; import { PartyUiMode } from "#app/ui/party-ui-handler";
import { SummaryUiMode } from "#app/ui/summary-ui-handler"; import { SummaryUiMode } from "#app/ui/summary-ui-handler";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import type { PokeballType } from "#enums/pokeball"; import type { PokeballType } from "#enums/pokeball";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import i18next from "i18next"; import i18next from "i18next";
@ -295,7 +295,7 @@ export class AttemptCapturePhase extends PokemonPhase {
() => { () => {
globalScene.pokemonInfoContainer.makeRoomForConfirmUi(1, true); globalScene.pokemonInfoContainer.makeRoomForConfirmUi(1, true);
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.CONFIRM, UiMode.CONFIRM,
() => { () => {
const newPokemon = globalScene.addPlayerPokemon( const newPokemon = globalScene.addPlayerPokemon(
pokemon.species, pokemon.species,
@ -310,12 +310,12 @@ export class AttemptCapturePhase extends PokemonPhase {
pokemon, pokemon,
); );
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.SUMMARY, UiMode.SUMMARY,
newPokemon, newPokemon,
0, 0,
SummaryUiMode.DEFAULT, SummaryUiMode.DEFAULT,
() => { () => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
promptRelease(); promptRelease();
}); });
}, },
@ -329,19 +329,26 @@ export class AttemptCapturePhase extends PokemonPhase {
form: pokemon.formIndex, form: pokemon.formIndex,
female: pokemon.gender === Gender.FEMALE, female: pokemon.gender === Gender.FEMALE,
}; };
globalScene.ui.setOverlayMode(Mode.POKEDEX_PAGE, pokemon.species, attributes, null, null, () => { globalScene.ui.setOverlayMode(
globalScene.ui.setMode(Mode.MESSAGE).then(() => { UiMode.POKEDEX_PAGE,
promptRelease(); pokemon.species,
}); attributes,
}); null,
null,
() => {
globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
promptRelease();
});
},
);
}, },
() => { () => {
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.PARTY, UiMode.PARTY,
PartyUiMode.RELEASE, PartyUiMode.RELEASE,
this.fieldIndex, this.fieldIndex,
(slotIndex: number, _option: PartyOption) => { (slotIndex: number, _option: PartyOption) => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
if (slotIndex < 6) { if (slotIndex < 6) {
addToParty(slotIndex); addToParty(slotIndex);
} else { } else {
@ -352,7 +359,7 @@ export class AttemptCapturePhase extends PokemonPhase {
); );
}, },
() => { () => {
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
removePokemon(); removePokemon();
end(); end();
}); });

View File

@ -9,7 +9,7 @@ import { StatusEffect } from "#enums/status-effect";
import type { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon"; import type { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
import { NumberHolder } from "#app/utils"; import { NumberHolder } from "#app/utils/common";
import { BattleEndPhase } from "./battle-end-phase"; import { BattleEndPhase } from "./battle-end-phase";
import { NewBattlePhase } from "./new-battle-phase"; import { NewBattlePhase } from "./new-battle-phase";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "./pokemon-phase";

View File

@ -9,7 +9,7 @@ import { BerryUsedEvent } from "#app/events/battle-scene";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { BerryModifier } from "#app/modifier/modifier"; import { BerryModifier } from "#app/modifier/modifier";
import i18next from "i18next"; import i18next from "i18next";
import { BooleanHolder } from "#app/utils"; import { BooleanHolder } from "#app/utils/common";
import { FieldPhase } from "./field-phase"; import { FieldPhase } from "./field-phase";
import { CommonAnimPhase } from "./common-anim-phase"; import { CommonAnimPhase } from "./common-anim-phase";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";

View File

@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
import { BattleStyle } from "#app/enums/battle-style"; import { BattleStyle } from "#app/enums/battle-style";
import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BattlerTagType } from "#app/enums/battler-tag-type";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "./battle-phase";
import { SummonMissingPhase } from "./summon-missing-phase"; import { SummonMissingPhase } from "./summon-missing-phase";
@ -64,14 +64,14 @@ export class CheckSwitchPhase extends BattlePhase {
null, null,
() => { () => {
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.CONFIRM, UiMode.CONFIRM,
() => { () => {
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.unshiftPhase(new SwitchPhase(SwitchType.INITIAL_SWITCH, this.fieldIndex, false, true)); globalScene.unshiftPhase(new SwitchPhase(SwitchType.INITIAL_SWITCH, this.fieldIndex, false, true));
this.end(); this.end();
}, },
() => { () => {
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
this.end(); this.end();
}, },
); );

View File

@ -1,6 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import type { TurnCommand } from "#app/battle"; import type { TurnCommand } from "#app/battle";
import { BattleType } from "#app/battle"; import { BattleType } from "#enums/battle-type";
import type { EncoreTag } from "#app/data/battler-tags"; import type { EncoreTag } from "#app/data/battler-tags";
import { TrappedTag } from "#app/data/battler-tags"; import { TrappedTag } from "#app/data/battler-tags";
import type { MoveTargetSet } from "#app/data/moves/move"; import type { MoveTargetSet } from "#app/data/moves/move";
@ -15,12 +15,12 @@ import type { PlayerPokemon, TurnMove } from "#app/field/pokemon";
import { FieldPosition } from "#app/field/pokemon"; import { FieldPosition } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { Command } from "#app/ui/command-ui-handler"; import { Command } from "#app/ui/command-ui-handler";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import { FieldPhase } from "./field-phase"; import { FieldPhase } from "./field-phase";
import { SelectTargetPhase } from "./select-target-phase"; import { SelectTargetPhase } from "./select-target-phase";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import { ArenaTagSide } from "#app/data/arena-tag"; import { ArenaTagSide } from "#app/data/arena-tag";
import { ArenaTagType } from "#app/enums/arena-tag-type"; import { ArenaTagType } from "#app/enums/arena-tag-type";
@ -38,7 +38,7 @@ export class CommandPhase extends FieldPhase {
globalScene.updateGameInfo(); globalScene.updateGameInfo();
const commandUiHandler = globalScene.ui.handlers[Mode.COMMAND]; const commandUiHandler = globalScene.ui.handlers[UiMode.COMMAND];
// If one of these conditions is true, we always reset the cursor to Command.FIGHT // If one of these conditions is true, we always reset the cursor to Command.FIGHT
const cursorResetEvent = const cursorResetEvent =
@ -127,7 +127,7 @@ export class CommandPhase extends FieldPhase {
) { ) {
this.handleCommand(Command.FIGHT, moveIndex, queuedMove.ignorePP, queuedMove); this.handleCommand(Command.FIGHT, moveIndex, queuedMove.ignorePP, queuedMove);
} else { } else {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
} }
} }
} else { } else {
@ -136,9 +136,9 @@ export class CommandPhase extends FieldPhase {
globalScene.currentBattle.mysteryEncounter?.skipToFightInput globalScene.currentBattle.mysteryEncounter?.skipToFightInput
) { ) {
globalScene.ui.clearText(); globalScene.ui.clearText();
globalScene.ui.setMode(Mode.FIGHT, this.fieldIndex); globalScene.ui.setMode(UiMode.FIGHT, this.fieldIndex);
} else { } else {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
} }
} }
} }
@ -209,7 +209,7 @@ export class CommandPhase extends FieldPhase {
success = true; success = true;
} else if (cursor < playerPokemon.getMoveset().length) { } else if (cursor < playerPokemon.getMoveset().length) {
const move = playerPokemon.getMoveset()[cursor]; const move = playerPokemon.getMoveset()[cursor];
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
// Decides between a Disabled, Not Implemented, or No PP translation message // Decides between a Disabled, Not Implemented, or No PP translation message
const errorMessage = playerPokemon.isMoveRestricted(move.moveId, playerPokemon) const errorMessage = playerPokemon.isMoveRestricted(move.moveId, playerPokemon)
@ -226,7 +226,7 @@ export class CommandPhase extends FieldPhase {
null, null,
() => { () => {
globalScene.ui.clearText(); globalScene.ui.clearText();
globalScene.ui.setMode(Mode.FIGHT, this.fieldIndex); globalScene.ui.setMode(UiMode.FIGHT, this.fieldIndex);
}, },
null, null,
true, true,
@ -244,27 +244,27 @@ export class CommandPhase extends FieldPhase {
globalScene.arena.biomeType === Biome.END && globalScene.arena.biomeType === Biome.END &&
(!globalScene.gameMode.isClassic || globalScene.gameMode.isFreshStartChallenge() || notInDex) (!globalScene.gameMode.isClassic || globalScene.gameMode.isFreshStartChallenge() || notInDex)
) { ) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:noPokeballForce"), i18next.t("battle:noPokeballForce"),
null, null,
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
}, },
null, null,
true, true,
); );
} else if (globalScene.currentBattle.battleType === BattleType.TRAINER) { } else if (globalScene.currentBattle.battleType === BattleType.TRAINER) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:noPokeballTrainer"), i18next.t("battle:noPokeballTrainer"),
null, null,
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
}, },
null, null,
true, true,
@ -273,14 +273,14 @@ export class CommandPhase extends FieldPhase {
globalScene.currentBattle.isBattleMysteryEncounter() && globalScene.currentBattle.isBattleMysteryEncounter() &&
!globalScene.currentBattle.mysteryEncounter!.catchAllowed !globalScene.currentBattle.mysteryEncounter!.catchAllowed
) { ) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:noPokeballMysteryEncounter"), i18next.t("battle:noPokeballMysteryEncounter"),
null, null,
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
}, },
null, null,
true, true,
@ -291,14 +291,14 @@ export class CommandPhase extends FieldPhase {
.filter(p => p.isActive(true)) .filter(p => p.isActive(true))
.map(p => p.getBattlerIndex()); .map(p => p.getBattlerIndex());
if (targets.length > 1) { if (targets.length > 1) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:noPokeballMulti"), i18next.t("battle:noPokeballMulti"),
null, null,
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
}, },
null, null,
true, true,
@ -311,14 +311,14 @@ export class CommandPhase extends FieldPhase {
!targetPokemon?.hasAbility(Abilities.WONDER_GUARD, false, true) && !targetPokemon?.hasAbility(Abilities.WONDER_GUARD, false, true) &&
cursor < PokeballType.MASTER_BALL cursor < PokeballType.MASTER_BALL
) { ) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:noPokeballStrong"), i18next.t("battle:noPokeballStrong"),
null, null,
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
}, },
null, null,
true, true,
@ -347,14 +347,14 @@ export class CommandPhase extends FieldPhase {
(arena.biomeType === Biome.END || (arena.biomeType === Biome.END ||
(!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed)) (!isNullOrUndefined(mysteryEncounterFleeAllowed) && !mysteryEncounterFleeAllowed))
) { ) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:noEscapeForce"), i18next.t("battle:noEscapeForce"),
null, null,
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
}, },
null, null,
true, true,
@ -364,14 +364,14 @@ export class CommandPhase extends FieldPhase {
(currentBattle.battleType === BattleType.TRAINER || (currentBattle.battleType === BattleType.TRAINER ||
currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE) currentBattle.mysteryEncounter?.encounterMode === MysteryEncounterMode.TRAINER_BATTLE)
) { ) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:noEscapeTrainer"), i18next.t("battle:noEscapeTrainer"),
null, null,
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
}, },
null, null,
true, true,
@ -389,7 +389,7 @@ export class CommandPhase extends FieldPhase {
} }
} else if (trappedAbMessages.length > 0) { } else if (trappedAbMessages.length > 0) {
if (!isSwitch) { if (!isSwitch) {
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
} }
globalScene.ui.showText( globalScene.ui.showText(
trappedAbMessages[0], trappedAbMessages[0],
@ -397,7 +397,7 @@ export class CommandPhase extends FieldPhase {
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
if (!isSwitch) { if (!isSwitch) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
} }
}, },
null, null,
@ -412,8 +412,8 @@ export class CommandPhase extends FieldPhase {
break; break;
} }
if (!isSwitch) { if (!isSwitch) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
} }
const showNoEscapeText = (tag: any) => { const showNoEscapeText = (tag: any) => {
globalScene.ui.showText( globalScene.ui.showText(
@ -429,7 +429,7 @@ export class CommandPhase extends FieldPhase {
() => { () => {
globalScene.ui.showText("", 0); globalScene.ui.showText("", 0);
if (!isSwitch) { if (!isSwitch) {
globalScene.ui.setMode(Mode.COMMAND, this.fieldIndex); globalScene.ui.setMode(UiMode.COMMAND, this.fieldIndex);
} }
}, },
null, null,
@ -471,6 +471,6 @@ export class CommandPhase extends FieldPhase {
} }
end() { end() {
globalScene.ui.setMode(Mode.MESSAGE).then(() => super.end()); globalScene.ui.setMode(UiMode.MESSAGE).then(() => super.end());
} }
} }

View File

@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
import type { BattlerIndex } from "#app/battle"; import type { BattlerIndex } from "#app/battle";
import { BattleSpec } from "#enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { type DamageResult, HitResult } from "#app/field/pokemon"; import { type DamageResult, HitResult } from "#app/field/pokemon";
import { fixedInt } from "#app/utils"; import { fixedInt } from "#app/utils/common";
import { PokemonPhase } from "#app/phases/pokemon-phase"; import { PokemonPhase } from "#app/phases/pokemon-phase";
export class DamageAnimPhase extends PokemonPhase { export class DamageAnimPhase extends PokemonPhase {

View File

@ -8,10 +8,10 @@ import { achvs } from "#app/system/achv";
import EggCounterContainer from "#app/ui/egg-counter-container"; import EggCounterContainer from "#app/ui/egg-counter-container";
import type EggHatchSceneHandler from "#app/ui/egg-hatch-scene-handler"; import type EggHatchSceneHandler from "#app/ui/egg-hatch-scene-handler";
import PokemonInfoContainer from "#app/ui/pokemon-info-container"; import PokemonInfoContainer from "#app/ui/pokemon-info-container";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import { fixedInt, getFrameMs, randInt } from "#app/utils"; import { fixedInt, getFrameMs, randInt } from "#app/utils/common";
import type { EggLapsePhase } from "./egg-lapse-phase"; import type { EggLapsePhase } from "./egg-lapse-phase";
import type { EggHatchData } from "#app/data/egg-hatch-data"; import type { EggHatchData } from "#app/data/egg-hatch-data";
import { doShinySparkleAnim } from "#app/field/anims"; import { doShinySparkleAnim } from "#app/field/anims";
@ -76,7 +76,7 @@ export class EggHatchPhase extends Phase {
start() { start() {
super.start(); super.start();
globalScene.ui.setModeForceTransition(Mode.EGG_HATCH_SCENE).then(() => { globalScene.ui.setModeForceTransition(UiMode.EGG_HATCH_SCENE).then(() => {
if (!this.egg) { if (!this.egg) {
return this.end(); return this.end();
} }

View File

@ -5,7 +5,7 @@ import { Phase } from "#app/phase";
import i18next from "i18next"; import i18next from "i18next";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { EggHatchPhase } from "./egg-hatch-phase"; import { EggHatchPhase } from "./egg-hatch-phase";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import { EggSummaryPhase } from "./egg-summary-phase"; import { EggSummaryPhase } from "./egg-summary-phase";
@ -41,7 +41,7 @@ export class EggLapsePhase extends Phase {
0, 0,
); );
globalScene.ui.setModeWithoutClear( globalScene.ui.setModeWithoutClear(
Mode.CONFIRM, UiMode.CONFIRM,
() => { () => {
this.hatchEggsSkipped(eggsToHatch); this.hatchEggsSkipped(eggsToHatch);
this.showSummary(); this.showSummary();

View File

@ -1,6 +1,6 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import type { EggHatchData } from "#app/data/egg-hatch-data"; import type { EggHatchData } from "#app/data/egg-hatch-data";
/** /**
@ -22,7 +22,7 @@ export class EggSummaryPhase extends Phase {
// updates next pokemon once the current update has been completed // updates next pokemon once the current update has been completed
const updateNextPokemon = (i: number) => { const updateNextPokemon = (i: number) => {
if (i >= this.eggHatchData.length) { if (i >= this.eggHatchData.length) {
globalScene.ui.setModeForceTransition(Mode.EGG_HATCH_SUMMARY, this.eggHatchData).then(() => { globalScene.ui.setModeForceTransition(UiMode.EGG_HATCH_SUMMARY, this.eggHatchData).then(() => {
globalScene.fadeOutBgm(undefined, false); globalScene.fadeOutBgm(undefined, false);
}); });
} else { } else {
@ -39,7 +39,7 @@ export class EggSummaryPhase extends Phase {
end() { end() {
globalScene.time.delayedCall(250, () => globalScene.setModifiersVisible(true)); globalScene.time.delayedCall(250, () => globalScene.setModifiersVisible(true));
globalScene.ui.setModeForceTransition(Mode.MESSAGE).then(() => { globalScene.ui.setModeForceTransition(UiMode.MESSAGE).then(() => {
super.end(); super.end();
}); });
} }

View File

@ -1,4 +1,5 @@
import { BattlerIndex, BattleType } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { BattleType } from "#enums/battle-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { import {
@ -33,8 +34,8 @@ import { SummonPhase } from "#app/phases/summon-phase";
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase"; import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import { handleTutorial, Tutorial } from "#app/tutorial"; import { handleTutorial, Tutorial } from "#app/tutorial";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import { randSeedInt, randSeedItem } from "#app/utils"; import { randSeedInt, randSeedItem } from "#app/utils/common";
import { BattleSpec } from "#enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
@ -295,7 +296,7 @@ export class EncounterPhase extends BattlePhase {
globalScene.currentBattle.trainer!.genAI(globalScene.getEnemyParty()); globalScene.currentBattle.trainer!.genAI(globalScene.getEnemyParty());
} }
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
if (!this.loaded) { if (!this.loaded) {
this.trySetWeatherIfNewBiome(); // Set weather before session gets saved this.trySetWeatherIfNewBiome(); // Set weather before session gets saved
// Game syncs to server on waves X1 and X6 (As of 1.2.0) // Game syncs to server on waves X1 and X6 (As of 1.2.0)

View File

@ -1,11 +1,11 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
export class EndEvolutionPhase extends Phase { export class EndEvolutionPhase extends Phase {
start() { start() {
super.start(); super.start();
globalScene.ui.setModeForceTransition(Mode.MESSAGE).then(() => this.end()); globalScene.ui.setModeForceTransition(UiMode.MESSAGE).then(() => this.end());
} }
} }

View File

@ -5,8 +5,8 @@ import { globalScene } from "#app/global-scene";
import type { SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions"; import type { SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
import { FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions"; import { FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions";
import type EvolutionSceneHandler from "#app/ui/evolution-scene-handler"; import type EvolutionSceneHandler from "#app/ui/evolution-scene-handler";
import { fixedInt, getFrameMs, randInt } from "#app/utils"; import { fixedInt, getFrameMs, randInt } from "#app/utils/common";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import { cos, sin } from "#app/field/anims"; import { cos, sin } from "#app/field/anims";
import type { PlayerPokemon } from "#app/field/pokemon"; import type { PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
@ -53,7 +53,7 @@ export class EvolutionPhase extends Phase {
} }
setMode(): Promise<void> { setMode(): Promise<void> {
return globalScene.ui.setModeForceTransition(Mode.EVOLUTION_SCENE); return globalScene.ui.setModeForceTransition(UiMode.EVOLUTION_SCENE);
} }
start() { start() {
@ -280,7 +280,7 @@ export class EvolutionPhase extends Phase {
this.end(); this.end();
}; };
globalScene.ui.setOverlayMode( globalScene.ui.setOverlayMode(
Mode.CONFIRM, UiMode.CONFIRM,
() => { () => {
globalScene.ui.revertMode(); globalScene.ui.revertMode();
this.pokemon.pauseEvolutions = true; this.pokemon.pauseEvolutions = true;

View File

@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { ExpBoosterModifier } from "#app/modifier/modifier"; import { ExpBoosterModifier } from "#app/modifier/modifier";
import i18next from "i18next"; import i18next from "i18next";
import { NumberHolder } from "#app/utils"; import { NumberHolder } from "#app/utils/common";
import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase"; import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase";
import { LevelUpPhase } from "./level-up-phase"; import { LevelUpPhase } from "./level-up-phase";

View File

@ -1,5 +1,5 @@
import type { BattlerIndex } from "#app/battle"; import type { BattlerIndex } from "#app/battle";
import { BattleType } from "#app/battle"; import { BattleType } from "#enums/battle-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { import {
applyPostFaintAbAttrs, applyPostFaintAbAttrs,
@ -9,7 +9,6 @@ import {
PostKnockOutAbAttr, PostKnockOutAbAttr,
PostVictoryAbAttr, PostVictoryAbAttr,
} from "#app/data/abilities/ability"; } from "#app/data/abilities/ability";
import type { DestinyBondTag, GrudgeTag } from "#app/data/battler-tags";
import { BattlerTagLapseType } from "#app/data/battler-tags"; import { BattlerTagLapseType } from "#app/data/battler-tags";
import { battleSpecDialogue } from "#app/data/dialogue"; import { battleSpecDialogue } from "#app/data/dialogue";
import { allMoves, PostVictoryStatStageChangeAttr } from "#app/data/moves/move"; import { allMoves, PostVictoryStatStageChangeAttr } from "#app/data/moves/move";
@ -30,8 +29,9 @@ import { SwitchPhase } from "./switch-phase";
import { SwitchSummonPhase } from "./switch-summon-phase"; import { SwitchSummonPhase } from "./switch-summon-phase";
import { ToggleDoublePositionPhase } from "./toggle-double-position-phase"; import { ToggleDoublePositionPhase } from "./toggle-double-position-phase";
import { VictoryPhase } from "./victory-phase"; import { VictoryPhase } from "./victory-phase";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils/common";
import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters"; import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters";
import { BattlerTagType } from "#enums/battler-tag-type";
export class FaintPhase extends PokemonPhase { export class FaintPhase extends PokemonPhase {
/** /**
@ -39,33 +39,15 @@ export class FaintPhase extends PokemonPhase {
*/ */
private preventEndure: boolean; private preventEndure: boolean;
/**
* Destiny Bond tag belonging to the currently fainting Pokemon, if applicable
*/
private destinyTag?: DestinyBondTag | null;
/**
* Grudge tag belonging to the currently fainting Pokemon, if applicable
*/
private grudgeTag?: GrudgeTag | null;
/** /**
* The source Pokemon that dealt fatal damage * The source Pokemon that dealt fatal damage
*/ */
private source?: Pokemon; private source?: Pokemon;
constructor( constructor(battlerIndex: BattlerIndex, preventEndure = false, source?: Pokemon) {
battlerIndex: BattlerIndex,
preventEndure = false,
destinyTag?: DestinyBondTag | null,
grudgeTag?: GrudgeTag | null,
source?: Pokemon,
) {
super(battlerIndex); super(battlerIndex);
this.preventEndure = preventEndure; this.preventEndure = preventEndure;
this.destinyTag = destinyTag;
this.grudgeTag = grudgeTag;
this.source = source; this.source = source;
} }
@ -74,13 +56,12 @@ export class FaintPhase extends PokemonPhase {
const faintPokemon = this.getPokemon(); const faintPokemon = this.getPokemon();
if (!isNullOrUndefined(this.destinyTag) && !isNullOrUndefined(this.source)) { if (this.source) {
this.destinyTag.lapse(this.source, BattlerTagLapseType.CUSTOM); faintPokemon.getTag(BattlerTagType.DESTINY_BOND)?.lapse(this.source, BattlerTagLapseType.CUSTOM);
faintPokemon.getTag(BattlerTagType.GRUDGE)?.lapse(faintPokemon, BattlerTagLapseType.CUSTOM, this.source);
} }
if (!isNullOrUndefined(this.grudgeTag) && !isNullOrUndefined(this.source)) { faintPokemon.resetSummonData();
this.grudgeTag.lapse(faintPokemon, BattlerTagLapseType.CUSTOM, this.source);
}
if (!this.preventEndure) { if (!this.preventEndure) {
const instantReviveModifier = globalScene.applyModifier( const instantReviveModifier = globalScene.applyModifier(

View File

@ -1,10 +1,10 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { fixedInt } from "#app/utils"; import { fixedInt } from "#app/utils/common";
import { achvs } from "../system/achv"; import { achvs } from "../system/achv";
import type { SpeciesFormChange } from "../data/pokemon-forms"; import type { SpeciesFormChange } from "../data/pokemon-forms";
import { getSpeciesFormChangeMessage } from "../data/pokemon-forms"; import { getSpeciesFormChangeMessage } from "../data/pokemon-forms";
import type { PlayerPokemon } from "../field/pokemon"; import type { PlayerPokemon } from "../field/pokemon";
import { Mode } from "../ui/ui"; import { UiMode } from "#enums/ui-mode";
import type PartyUiHandler from "../ui/party-ui-handler"; import type PartyUiHandler from "../ui/party-ui-handler";
import { getPokemonNameWithAffix } from "../messages"; import { getPokemonNameWithAffix } from "../messages";
import { EndEvolutionPhase } from "./end-evolution-phase"; import { EndEvolutionPhase } from "./end-evolution-phase";
@ -31,7 +31,7 @@ export class FormChangePhase extends EvolutionPhase {
if (!this.modal) { if (!this.modal) {
return super.setMode(); return super.setMode();
} }
return globalScene.ui.setOverlayMode(Mode.EVOLUTION_SCENE); return globalScene.ui.setOverlayMode(UiMode.EVOLUTION_SCENE);
} }
doEvolution(): void { doEvolution(): void {
@ -181,7 +181,7 @@ export class FormChangePhase extends EvolutionPhase {
this.pokemon.findAndRemoveTags(t => t.tagType === BattlerTagType.AUTOTOMIZED); this.pokemon.findAndRemoveTags(t => t.tagType === BattlerTagType.AUTOTOMIZED);
if (this.modal) { if (this.modal) {
globalScene.ui.revertMode().then(() => { globalScene.ui.revertMode().then(() => {
if (globalScene.ui.getMode() === Mode.PARTY) { if (globalScene.ui.getMode() === UiMode.PARTY) {
const partyUiHandler = globalScene.ui.getHandler() as PartyUiHandler; const partyUiHandler = globalScene.ui.getHandler() as PartyUiHandler;
partyUiHandler.clearPartySlots(); partyUiHandler.clearPartySlots();
partyUiHandler.populatePartySlots(); partyUiHandler.populatePartySlots();

View File

@ -1,5 +1,5 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import { ModifierRewardPhase } from "./modifier-reward-phase"; import { ModifierRewardPhase } from "./modifier-reward-phase";
@ -10,7 +10,7 @@ export class GameOverModifierRewardPhase extends ModifierRewardPhase {
globalScene.addModifier(newModifier); globalScene.addModifier(newModifier);
// Sound loaded into game as is // Sound loaded into game as is
globalScene.playSound("level_up_fanfare"); globalScene.playSound("level_up_fanfare");
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.fadeIn(250).then(() => { globalScene.ui.fadeIn(250).then(() => {
globalScene.ui.showText( globalScene.ui.showText(
i18next.t("battle:rewardGain", { i18next.t("battle:rewardGain", {

View File

@ -1,5 +1,5 @@
import { clientSessionId } from "#app/account"; import { clientSessionId } from "#app/account";
import { BattleType } from "#app/battle"; import { BattleType } from "#enums/battle-type";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions";
import { getCharVariantFromDialogue } from "#app/data/dialogue"; import { getCharVariantFromDialogue } from "#app/data/dialogue";
@ -19,8 +19,8 @@ import { SummonPhase } from "#app/phases/summon-phase";
import { UnlockPhase } from "#app/phases/unlock-phase"; import { UnlockPhase } from "#app/phases/unlock-phase";
import { achvs, ChallengeAchv } from "#app/system/achv"; import { achvs, ChallengeAchv } from "#app/system/achv";
import { Unlockables } from "#app/system/unlockables"; import { Unlockables } from "#app/system/unlockables";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import { isLocal, isLocalServerConnected } from "#app/utils"; import { isLocal, isLocalServerConnected } from "#app/utils/common";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import i18next from "i18next"; import i18next from "i18next";
@ -78,7 +78,7 @@ export class GameOverPhase extends BattlePhase {
} else { } else {
globalScene.ui.showText(i18next.t("battle:retryBattle"), null, () => { globalScene.ui.showText(i18next.t("battle:retryBattle"), null, () => {
globalScene.ui.setMode( globalScene.ui.setMode(
Mode.CONFIRM, UiMode.CONFIRM,
() => { () => {
globalScene.ui.fadeOut(1250).then(() => { globalScene.ui.fadeOut(1250).then(() => {
globalScene.reset(); globalScene.reset();

View File

@ -8,7 +8,7 @@ import { getPokemonNameWithAffix } from "#app/messages";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import EvolutionSceneHandler from "#app/ui/evolution-scene-handler"; import EvolutionSceneHandler from "#app/ui/evolution-scene-handler";
import { SummaryUiMode } from "#app/ui/summary-ui-handler"; import { SummaryUiMode } from "#app/ui/summary-ui-handler";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase"; import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
@ -25,7 +25,7 @@ export enum LearnMoveType {
export class LearnMovePhase extends PlayerPartyMemberPokemonPhase { export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
private moveId: Moves; private moveId: Moves;
private messageMode: Mode; private messageMode: UiMode;
private learnMoveType: LearnMoveType; private learnMoveType: LearnMoveType;
private cost: number; private cost: number;
@ -55,7 +55,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
} }
this.messageMode = this.messageMode =
globalScene.ui.getHandler() instanceof EvolutionSceneHandler ? Mode.EVOLUTION_SCENE : Mode.MESSAGE; globalScene.ui.getHandler() instanceof EvolutionSceneHandler ? UiMode.EVOLUTION_SCENE : UiMode.MESSAGE;
globalScene.ui.setMode(this.messageMode); globalScene.ui.setMode(this.messageMode);
// If the Pokemon has less than 4 moves, the new move is added to the largest empty moveset index // If the Pokemon has less than 4 moves, the new move is added to the largest empty moveset index
// If it has 4 moves, the phase then checks if the player wants to replace the move itself. // If it has 4 moves, the phase then checks if the player wants to replace the move itself.
@ -90,7 +90,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
await globalScene.ui.showTextPromise(preQText); await globalScene.ui.showTextPromise(preQText);
await globalScene.ui.showTextPromise(shouldReplaceQ, undefined, false); await globalScene.ui.showTextPromise(shouldReplaceQ, undefined, false);
await globalScene.ui.setModeWithoutClear( await globalScene.ui.setModeWithoutClear(
Mode.CONFIRM, UiMode.CONFIRM,
() => this.forgetMoveProcess(move, pokemon), // Yes () => this.forgetMoveProcess(move, pokemon), // Yes
() => { () => {
// No // No
@ -115,7 +115,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
globalScene.ui.setMode(this.messageMode); globalScene.ui.setMode(this.messageMode);
await globalScene.ui.showTextPromise(i18next.t("battle:learnMoveForgetQuestion"), undefined, true); await globalScene.ui.showTextPromise(i18next.t("battle:learnMoveForgetQuestion"), undefined, true);
await globalScene.ui.setModeWithoutClear( await globalScene.ui.setModeWithoutClear(
Mode.SUMMARY, UiMode.SUMMARY,
pokemon, pokemon,
SummaryUiMode.LEARN_MOVE, SummaryUiMode.LEARN_MOVE,
move, move,
@ -153,7 +153,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
false, false,
); );
globalScene.ui.setModeWithoutClear( globalScene.ui.setModeWithoutClear(
Mode.CONFIRM, UiMode.CONFIRM,
() => { () => {
globalScene.ui.setMode(this.messageMode); globalScene.ui.setMode(this.messageMode);
globalScene.ui globalScene.ui
@ -228,7 +228,7 @@ export class LearnMovePhase extends PlayerPartyMemberPokemonPhase {
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true); globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeMoveLearnedTrigger, true);
this.end(); this.end();
}, },
this.messageMode === Mode.EVOLUTION_SCENE ? 1000 : undefined, this.messageMode === UiMode.EVOLUTION_SCENE ? 1000 : undefined,
true, true,
); );
} }

View File

@ -1,5 +1,5 @@
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next from "i18next"; import i18next from "i18next";
import { FieldPhase } from "./field-phase"; import { FieldPhase } from "./field-phase";
@ -7,7 +7,7 @@ export class LevelCapPhase extends FieldPhase {
start(): void { start(): void {
super.start(); super.start();
globalScene.ui.setMode(Mode.MESSAGE).then(() => { globalScene.ui.setMode(UiMode.MESSAGE).then(() => {
// Sound loaded into game as is // Sound loaded into game as is
globalScene.playSound("level_up_fanfare"); globalScene.playSound("level_up_fanfare");
globalScene.ui.showText( globalScene.ui.showText(

View File

@ -6,7 +6,7 @@ import { EvolutionPhase } from "#app/phases/evolution-phase";
import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { LearnMovePhase } from "#app/phases/learn-move-phase";
import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase"; import { PlayerPartyMemberPokemonPhase } from "#app/phases/player-party-member-pokemon-phase";
import { LevelAchv } from "#app/system/achv"; import { LevelAchv } from "#app/system/achv";
import { NumberHolder } from "#app/utils"; import { NumberHolder } from "#app/utils/common";
import i18next from "i18next"; import i18next from "i18next";
export class LevelUpPhase extends PlayerPartyMemberPokemonPhase { export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
@ -71,7 +71,7 @@ export class LevelUpPhase extends PlayerPartyMemberPokemonPhase {
if (!this.pokemon.pauseEvolutions) { if (!this.pokemon.pauseEvolutions) {
const evolution = this.pokemon.getEvolution(); const evolution = this.pokemon.getEvolution();
if (evolution) { if (evolution) {
this.pokemon.breakIllusion() this.pokemon.breakIllusion();
globalScene.unshiftPhase(new EvolutionPhase(this.pokemon, evolution, this.lastLevel)); globalScene.unshiftPhase(new EvolutionPhase(this.pokemon, evolution, this.lastLevel));
} }
} }

View File

@ -1,11 +1,12 @@
import { updateUserInfo } from "#app/account"; import { updateUserInfo } from "#app/account";
import { bypassLogin } from "#app/battle-scene"; import { bypassLogin } from "#app/global-vars/bypass-login";
import { globalScene } from "#app/global-scene"; import { globalScene } from "#app/global-scene";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import { handleTutorial, Tutorial } from "#app/tutorial"; import { handleTutorial, Tutorial } from "#app/tutorial";
import { Mode } from "#app/ui/ui"; import { UiMode } from "#enums/ui-mode";
import i18next, { t } from "i18next"; import i18next, { t } from "i18next";
import { getCookie, sessionIdKey, executeIf, removeCookie } from "#app/utils"; import { sessionIdKey, executeIf } from "#app/utils/common";
import { getCookie, removeCookie } from "#app/utils/cookies";
import { SelectGenderPhase } from "./select-gender-phase"; import { SelectGenderPhase } from "./select-gender-phase";
import { UnavailablePhase } from "./unavailable-phase"; import { UnavailablePhase } from "./unavailable-phase";
@ -23,7 +24,7 @@ export class LoginPhase extends Phase {
const hasSession = !!getCookie(sessionIdKey); const hasSession = !!getCookie(sessionIdKey);
globalScene.ui.setMode(Mode.LOADING, { buttonActions: [] }); globalScene.ui.setMode(UiMode.LOADING, { buttonActions: [] });
executeIf(bypassLogin || hasSession, updateUserInfo).then(response => { executeIf(bypassLogin || hasSession, updateUserInfo).then(response => {
const success = response ? response[0] : false; const success = response ? response[0] : false;
const statusCode = response ? response[1] : null; const statusCode = response ? response[1] : null;
@ -46,7 +47,7 @@ export class LoginPhase extends Phase {
}); });
}; };
globalScene.ui.setMode(Mode.LOGIN_FORM, { globalScene.ui.setMode(UiMode.LOGIN_FORM, {
buttonActions: [ buttonActions: [
() => { () => {
globalScene.ui.playSelect(); globalScene.ui.playSelect();
@ -54,7 +55,7 @@ export class LoginPhase extends Phase {
}, },
() => { () => {
globalScene.playSound("menu_open"); globalScene.playSound("menu_open");
globalScene.ui.setMode(Mode.REGISTRATION_FORM, { globalScene.ui.setMode(UiMode.REGISTRATION_FORM, {
buttonActions: [ buttonActions: [
() => { () => {
globalScene.ui.playSelect(); globalScene.ui.playSelect();
@ -101,7 +102,7 @@ export class LoginPhase extends Phase {
if (success || bypassLogin) { if (success || bypassLogin) {
this.end(); this.end();
} else { } else {
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
globalScene.ui.showText(t("menu:failedToLoadSaveData")); globalScene.ui.showText(t("menu:failedToLoadSaveData"));
} }
}); });
@ -109,7 +110,7 @@ export class LoginPhase extends Phase {
} }
end(): void { end(): void {
globalScene.ui.setMode(Mode.MESSAGE); globalScene.ui.setMode(UiMode.MESSAGE);
if (!globalScene.gameData.gender) { if (!globalScene.gameData.gender) {
globalScene.unshiftPhase(new SelectGenderPhase()); globalScene.unshiftPhase(new SelectGenderPhase());

View File

@ -2,7 +2,7 @@ import { globalScene } from "#app/global-scene";
import { ArenaTagType } from "#app/enums/arena-tag-type"; import { ArenaTagType } from "#app/enums/arena-tag-type";
import { MoneyMultiplierModifier } from "#app/modifier/modifier"; import { MoneyMultiplierModifier } from "#app/modifier/modifier";
import i18next from "i18next"; import i18next from "i18next";
import { NumberHolder } from "#app/utils"; import { NumberHolder } from "#app/utils/common";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "./battle-phase";
export class MoneyRewardPhase extends BattlePhase { export class MoneyRewardPhase extends BattlePhase {

Some files were not shown because too many files have changed in this diff Show More