Convert overly long import lines to multi-line imports

This should hopefully prevent most merge conflicts with imports

- Replace `* as Utils` with `{ ... }`

- Replace instances of `IntegerHolder` with `NumberHolder`

- Add `#phases`, `#mystery-encounters`, `#balance` import mappings

- Replace many instances of relative with absolute imports
This commit is contained in:
NightKev 2024-10-21 19:57:46 -07:00
parent 7066a15ceb
commit 0f5e007a3c
434 changed files with 3506 additions and 2755 deletions

View File

@ -1,5 +1,5 @@
import { bypassLogin } from "./battle-scene"; import { bypassLogin } from "./battle-scene";
import * as Utils from "./utils"; import { randomString, apiFetch } from "#app/utils";
export interface UserInfo { export interface UserInfo {
username: string; username: string;
@ -11,7 +11,7 @@ export interface UserInfo {
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
export const clientSessionId = Utils.randomString(32); export const clientSessionId = randomString(32);
export function initLoggedInUser(): void { export function initLoggedInUser(): void {
loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false }; loggedInUser = { username: "Guest", lastSessionSlot: -1, discordId: "", googleId: "", hasAdminRole: false };
@ -43,7 +43,7 @@ export function updateUserInfo(): Promise<[boolean, integer]> {
}); });
return resolve([ true, 200 ]); return resolve([ true, 200 ]);
} }
Utils.apiFetch("account/info", true).then(response => { apiFetch("account/info", true).then(response => {
if (!response.ok) { if (!response.ok) {
resolve([ false, response.status ]); resolve([ false, response.status ]);
return; return;

View File

@ -2,20 +2,79 @@ import Phaser from "phaser";
import UI from "#app/ui/ui"; import UI from "#app/ui/ui";
import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species"; import PokemonSpecies, { allSpecies, getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species";
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils"; import {
import * as Utils from "#app/utils"; Constructor,
import { ConsumableModifier, ConsumablePokemonModifier, DoubleBattleChanceBoosterModifier, ExpBalanceModifier, ExpShareModifier, FusePokemonModifier, HealingBoosterModifier, Modifier, ModifierBar, ModifierPredicate, MultipleParticipantExpBonusModifier, overrideHeldItems, overrideModifiers, PersistentModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, RememberMoveModifier, TerastallizeModifier, TurnHeldItemTransferModifier } from "./modifier/modifier"; fixedInt,
getIvsFromId,
randSeedInt,
getEnumValues,
randomString,
shiftCharCodes,
formatMoney,
isNullOrUndefined,
BooleanHolder,
executeIf,
NumberHolder,
} from "#app/utils";
import {
ConsumableModifier,
ConsumablePokemonModifier,
DoubleBattleChanceBoosterModifier,
ExpBalanceModifier,
ExpShareModifier,
FusePokemonModifier,
HealingBoosterModifier,
Modifier,
ModifierBar,
ModifierPredicate,
MultipleParticipantExpBonusModifier,
overrideHeldItems,
overrideModifiers,
PersistentModifier,
PokemonExpBoosterModifier,
PokemonFormChangeItemModifier,
PokemonHeldItemModifier,
PokemonHpRestoreModifier,
PokemonIncrementingStatModifier,
RememberMoveModifier,
TerastallizeModifier,
TurnHeldItemTransferModifier,
} from "#app/modifier/modifier";
import { PokeballType } from "#app/data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import { initCommonAnims, initMoveAnim, loadCommonAnimAssets, loadMoveAnimAssets, populateAnims } from "#app/data/battle-anims"; import {
initCommonAnims,
initMoveAnim,
loadCommonAnimAssets,
loadMoveAnimAssets,
populateAnims,
} from "#app/data/battle-anims";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import { initGameSpeed } from "#app/system/game-speed"; import { initGameSpeed } from "#app/system/game-speed";
import { Arena, ArenaBase } from "#app/field/arena"; import { Arena, ArenaBase } from "#app/field/arena";
import { GameData } from "#app/system/game-data"; import { GameData } from "#app/system/game-data";
import { addTextObject, getTextColor, TextStyle } from "#app/ui/text"; import { addTextObject, getTextColor, TextStyle } from "#app/ui/text";
import { allMoves } from "#app/data/move"; import { allMoves } from "#app/data/move";
import { getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getModifierType, getPartyLuckValue, ModifierPoolType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import {
getDefaultModifierTypeForTier,
getEnemyModifierTypesForWave,
getLuckString,
getLuckTextTint,
getModifierPoolForType,
getModifierType,
getPartyLuckValue,
ModifierPoolType,
modifierTypes,
PokemonHeldItemModifierType,
} from "#app/modifier/modifier-type";
import AbilityBar from "#app/ui/ability-bar"; import AbilityBar from "#app/ui/ability-bar";
import { allAbilities, applyAbAttrs, applyPostBattleInitAbAttrs, BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, PostBattleInitAbAttr } from "#app/data/ability"; import {
allAbilities,
applyAbAttrs,
applyPostBattleInitAbAttrs,
BlockItemTheftAbAttr,
DoubleBattleChanceAbAttr,
PostBattleInitAbAttr,
} from "#app/data/ability";
import Battle, { BattleType, FixedBattleConfig } from "#app/battle"; import Battle, { BattleType, FixedBattleConfig } from "#app/battle";
import { GameMode, GameModes, getGameMode } from "#app/game-mode"; import { GameMode, GameModes, getGameMode } from "#app/game-mode";
import FieldSpritePipeline from "#app/pipelines/field-sprite"; import FieldSpritePipeline from "#app/pipelines/field-sprite";
@ -25,7 +84,7 @@ import { trainerConfigs, TrainerSlot } from "#app/data/trainer-config";
import Trainer, { TrainerVariant } from "#app/field/trainer"; import Trainer, { TrainerVariant } from "#app/field/trainer";
import TrainerData from "#app/system/trainer-data"; import TrainerData from "#app/system/trainer-data";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonPrevolutions } from "#balance/pokemon-evolutions";
import PokeballTray from "#app/ui/pokeball-tray"; import PokeballTray from "#app/ui/pokeball-tray";
import InvertPostFX from "#app/pipelines/invert"; import InvertPostFX from "#app/pipelines/invert";
import { Achv, achvs, ModifierAchv, MoneyAchv } from "#app/system/achv"; import { Achv, achvs, ModifierAchv, MoneyAchv } from "#app/system/achv";
@ -35,14 +94,21 @@ import UIPlugin from "phaser3-rex-plugins/templates/ui/ui-plugin";
import { addUiThemeOverrides } from "#app/ui/ui-theme"; import { addUiThemeOverrides } from "#app/ui/ui-theme";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { Nature } from "#app/data/nature"; import { Nature } from "#app/data/nature";
import { FormChangeItem, pokemonFormChanges, SpeciesFormChange, SpeciesFormChangeManualTrigger, SpeciesFormChangeTimeOfDayTrigger, SpeciesFormChangeTrigger } from "#app/data/pokemon-forms"; import {
import { FormChangePhase } from "#app/phases/form-change-phase"; FormChangeItem,
pokemonFormChanges,
SpeciesFormChange,
SpeciesFormChangeManualTrigger,
SpeciesFormChangeTimeOfDayTrigger,
SpeciesFormChangeTrigger,
} from "#app/data/pokemon-forms";
import { FormChangePhase } from "#phases/form-change-phase";
import { getTypeRgb } from "#app/data/type"; import { getTypeRgb } from "#app/data/type";
import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler"; import PokemonSpriteSparkleHandler from "#app/field/pokemon-sprite-sparkle-handler";
import CharSprite from "#app/ui/char-sprite"; import CharSprite from "#app/ui/char-sprite";
import DamageNumberHandler from "#app/field/damage-number-handler"; import DamageNumberHandler from "#app/field/damage-number-handler";
import PokemonInfoContainer from "#app/ui/pokemon-info-container"; import PokemonInfoContainer from "#app/ui/pokemon-info-container";
import { biomeDepths, getBiomeName } from "#app/data/balance/biomes"; import { biomeDepths, getBiomeName } from "#balance/biomes";
import { SceneBase } from "#app/scene-base"; import { SceneBase } from "#app/scene-base";
import CandyBar from "#app/ui/candy-bar"; import CandyBar from "#app/ui/candy-bar";
import { Variant, variantData } from "#app/data/variant"; import { Variant, variantData } from "#app/data/variant";
@ -68,34 +134,41 @@ import i18next from "i18next";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { battleSpecDialogue } from "#app/data/dialogue"; import { battleSpecDialogue } from "#app/data/dialogue";
import { LoadingScene } from "#app/loading-scene"; import { LoadingScene } from "#app/loading-scene";
import { LevelCapPhase } from "#app/phases/level-cap-phase"; import { LevelCapPhase } from "#phases/level-cap-phase";
import { LoginPhase } from "#app/phases/login-phase"; import { LoginPhase } from "#phases/login-phase";
import { MessagePhase } from "#app/phases/message-phase"; import { MessagePhase } from "#phases/message-phase";
import { MovePhase } from "#app/phases/move-phase"; import { MovePhase } from "#phases/move-phase";
import { NewBiomeEncounterPhase } from "#app/phases/new-biome-encounter-phase"; import { NewBiomeEncounterPhase } from "#phases/new-biome-encounter-phase";
import { NextEncounterPhase } from "#app/phases/next-encounter-phase"; import { NextEncounterPhase } from "#phases/next-encounter-phase";
import { PokemonAnimPhase } from "#app/phases/pokemon-anim-phase"; import { PokemonAnimPhase } from "#phases/pokemon-anim-phase";
import { QuietFormChangePhase } from "#app/phases/quiet-form-change-phase"; import { QuietFormChangePhase } from "#phases/quiet-form-change-phase";
import { ReturnPhase } from "#app/phases/return-phase"; import { ReturnPhase } from "#phases/return-phase";
import { SelectBiomePhase } from "#app/phases/select-biome-phase"; import { SelectBiomePhase } from "#phases/select-biome-phase";
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase"; import { ShowTrainerPhase } from "#phases/show-trainer-phase";
import { SummonPhase } from "#app/phases/summon-phase"; import { SummonPhase } from "#phases/summon-phase";
import { SwitchPhase } from "#app/phases/switch-phase"; import { SwitchPhase } from "#phases/switch-phase";
import { TitlePhase } from "#app/phases/title-phase"; import { TitlePhase } from "#phases/title-phase";
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase"; import { ToggleDoublePositionPhase } from "#phases/toggle-double-position-phase";
import { TurnInitPhase } from "#app/phases/turn-init-phase"; import { TurnInitPhase } from "#phases/turn-init-phase";
import { ShopCursorTarget } from "#app/enums/shop-cursor-target"; import { ShopCursorTarget } from "#enums/shop-cursor-target";
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter from "#mystery-encounters/mystery-encounter";
import { allMysteryEncounters, ANTI_VARIANCE_WEIGHT_MODIFIER, AVERAGE_ENCOUNTERS_PER_RUN_TARGET, BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT, MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT, mysteryEncountersByBiome } from "#app/data/mystery-encounters/mystery-encounters"; import {
import { MysteryEncounterSaveData } from "#app/data/mystery-encounters/mystery-encounter-save-data"; allMysteryEncounters,
ANTI_VARIANCE_WEIGHT_MODIFIER,
AVERAGE_ENCOUNTERS_PER_RUN_TARGET,
BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT,
MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT,
mysteryEncountersByBiome,
} from "#mystery-encounters/mystery-encounters";
import { MysteryEncounterSaveData } from "#mystery-encounters/mystery-encounter-save-data";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import HeldModifierConfig from "#app/interfaces/held-modifier-config";
import { ExpPhase } from "#app/phases/exp-phase"; import { ExpPhase } from "#phases/exp-phase";
import { ShowPartyExpBarPhase } from "#app/phases/show-party-exp-bar-phase"; import { ShowPartyExpBarPhase } from "#phases/show-party-exp-bar-phase";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { ExpGainsSpeed } from "#enums/exp-gains-speed"; import { ExpGainsSpeed } from "#enums/exp-gains-speed";
import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#app/data/balance/starters"; import { FRIENDSHIP_GAIN_FROM_BATTLE } from "#balance/starters";
export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1"; export const bypassLogin = import.meta.env.VITE_BYPASS_LOGIN === "1";
@ -628,7 +701,7 @@ export default class BattleScene extends SceneBase {
} }
this.playTimeTimer = this.time.addEvent({ this.playTimeTimer = this.time.addEvent({
delay: Utils.fixedInt(1000), delay: fixedInt(1000),
repeat: -1, repeat: -1,
callback: () => { callback: () => {
if (this.gameData) { if (this.gameData) {
@ -897,7 +970,7 @@ export default class BattleScene extends SceneBase {
overrideModifiers(this, false); overrideModifiers(this, false);
overrideHeldItems(this, pokemon, false); overrideHeldItems(this, pokemon, false);
if (boss && !dataSource) { if (boss && !dataSource) {
const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967296)); const secondaryIvs = getIvsFromId(randSeedInt(4294967296));
for (let s = 0; s < pokemon.ivs.length; s++) { for (let s = 0; s < pokemon.ivs.length; s++) {
pokemon.ivs[s] = Math.round(Phaser.Math.Linear(Math.min(pokemon.ivs[s], secondaryIvs[s]), Math.max(pokemon.ivs[s], secondaryIvs[s]), 0.75)); pokemon.ivs[s] = Math.round(Phaser.Math.Linear(Math.min(pokemon.ivs[s], secondaryIvs[s]), Math.max(pokemon.ivs[s], secondaryIvs[s]), 0.75));
@ -1027,7 +1100,7 @@ export default class BattleScene extends SceneBase {
* Generates a random number using the current battle's seed * Generates a random number using the current battle's seed
* *
* This calls {@linkcode Battle.randSeedInt}(`scene`, {@linkcode range}, {@linkcode min}) in `src/battle.ts` * This calls {@linkcode Battle.randSeedInt}(`scene`, {@linkcode range}, {@linkcode min}) in `src/battle.ts`
* which calls {@linkcode Utils.randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts` * which calls {@linkcode randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts`
* *
* @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min} * @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min}
* @param min The minimum integer to pick, default `0` * @param min The minimum integer to pick, default `0`
@ -1051,7 +1124,7 @@ export default class BattleScene extends SceneBase {
this.lockModifierTiers = false; this.lockModifierTiers = false;
this.pokeballCounts = Object.fromEntries(Utils.getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ])); this.pokeballCounts = Object.fromEntries(getEnumValues(PokeballType).filter(p => p <= PokeballType.MASTER_BALL).map(t => [ t, 0 ]));
this.pokeballCounts[PokeballType.POKEBALL] += 5; this.pokeballCounts[PokeballType.POKEBALL] += 5;
if (Overrides.POKEBALL_OVERRIDE.active) { if (Overrides.POKEBALL_OVERRIDE.active) {
this.pokeballCounts = Overrides.POKEBALL_OVERRIDE.pokeballs; this.pokeballCounts = Overrides.POKEBALL_OVERRIDE.pokeballs;
@ -1080,7 +1153,7 @@ export default class BattleScene extends SceneBase {
// Reset RNG after end of game or save & quit. // Reset RNG after end of game or save & quit.
// This needs to happen after clearing this.currentBattle or the seed will be affected by the last wave played // This needs to happen after clearing this.currentBattle or the seed will be affected by the last wave played
this.setSeed(Overrides.SEED_OVERRIDE || Utils.randomString(24)); this.setSeed(Overrides.SEED_OVERRIDE || randomString(24));
console.log("Seed:", this.seed); console.log("Seed:", this.seed);
this.resetSeed(); this.resetSeed();
@ -1120,7 +1193,7 @@ export default class BattleScene extends SceneBase {
...allSpecies, ...allSpecies,
...allMoves, ...allMoves,
...allAbilities, ...allAbilities,
...Utils.getEnumValues(ModifierPoolType).map(mpt => getModifierPoolForType(mpt)).map(mp => Object.values(mp).flat().map(mt => mt.modifierType).filter(mt => "localize" in mt).map(lpb => lpb as unknown as Localizable)).flat() ...getEnumValues(ModifierPoolType).map(mpt => getModifierPoolForType(mpt)).map(mp => Object.values(mp).flat().map(mt => mt.modifierType).filter(mt => "localize" in mt).map(lpb => lpb as unknown as Localizable)).flat()
]; ];
for (const item of localizable) { for (const item of localizable) {
item.localize(); item.localize();
@ -1149,7 +1222,7 @@ export default class BattleScene extends SceneBase {
} }
getDoubleBattleChance(newWaveIndex: number, playerField: PlayerPokemon[]) { getDoubleBattleChance(newWaveIndex: number, playerField: PlayerPokemon[]) {
const doubleChance = new Utils.IntegerHolder(newWaveIndex % 10 === 0 ? 32 : 8); const doubleChance = new NumberHolder(newWaveIndex % 10 === 0 ? 32 : 8);
this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance); this.applyModifiers(DoubleBattleChanceBoosterModifier, true, doubleChance);
playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance)); playerField.forEach(p => applyAbAttrs(DoubleBattleChanceAbAttr, p, null, false, doubleChance));
return Math.max(doubleChance.value, 1); return Math.max(doubleChance.value, 1);
@ -1191,13 +1264,13 @@ export default class BattleScene extends SceneBase {
if (trainerConfigs[trainerType].doubleOnly) { if (trainerConfigs[trainerType].doubleOnly) {
doubleTrainer = true; doubleTrainer = true;
} else if (trainerConfigs[trainerType].hasDouble) { } else if (trainerConfigs[trainerType].hasDouble) {
doubleTrainer = !Utils.randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField)); doubleTrainer = !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 (trainerConfigs[trainerType].trainerTypeDouble && ![ TrainerType.TATE, TrainerType.LIZA ].includes(trainerType)) { if (trainerConfigs[trainerType].trainerTypeDouble && ![ TrainerType.TATE, TrainerType.LIZA ].includes(trainerType)) {
doubleTrainer = false; doubleTrainer = false;
} }
} }
const variant = doubleTrainer ? TrainerVariant.DOUBLE : (Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT); const variant = doubleTrainer ? TrainerVariant.DOUBLE : (randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT);
newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, variant); newTrainer = trainerData !== undefined ? trainerData.toTrainer(this) : new Trainer(this, trainerType, variant);
this.field.add(newTrainer); this.field.add(newTrainer);
} }
@ -1213,7 +1286,7 @@ 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 = !Utils.randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField)); newDouble = !randSeedInt(this.getDoubleBattleChance(newWaveIndex, playerField));
} else if (newBattleType === BattleType.TRAINER) { } else if (newBattleType === BattleType.TRAINER) {
newDouble = newTrainer?.variant === TrainerVariant.DOUBLE; newDouble = newTrainer?.variant === TrainerVariant.DOUBLE;
} }
@ -1341,7 +1414,7 @@ export default class BattleScene extends SceneBase {
scale: scale, scale: scale,
x: (defaultWidth - scaledWidth) / 2, x: (defaultWidth - scaledWidth) / 2,
y: defaultHeight - scaledHeight, y: defaultHeight - scaledHeight,
duration: !instant ? Utils.fixedInt(Math.abs(this.field.scale - scale) * 200) : 0, duration: !instant ? fixedInt(Math.abs(this.field.scale - scale) * 200) : 0,
ease: "Sine.easeInOut", ease: "Sine.easeInOut",
onComplete: () => resolve() onComplete: () => resolve()
}); });
@ -1377,19 +1450,19 @@ export default class BattleScene extends SceneBase {
case Species.SQUAWKABILLY: case Species.SQUAWKABILLY:
case Species.TATSUGIRI: case Species.TATSUGIRI:
case Species.PALDEA_TAUROS: case Species.PALDEA_TAUROS:
return Utils.randSeedInt(species.forms.length); return randSeedInt(species.forms.length);
case Species.PIKACHU: case Species.PIKACHU:
return Utils.randSeedInt(8); return randSeedInt(8);
case Species.EEVEE: case Species.EEVEE:
return Utils.randSeedInt(2); return randSeedInt(2);
case Species.GRENINJA: case Species.GRENINJA:
return Utils.randSeedInt(2); return randSeedInt(2);
case Species.ZYGARDE: case Species.ZYGARDE:
return Utils.randSeedInt(4); return randSeedInt(4);
case Species.MINIOR: case Species.MINIOR:
return Utils.randSeedInt(6); return randSeedInt(6);
case Species.ALCREMIE: case Species.ALCREMIE:
return Utils.randSeedInt(9); return randSeedInt(9);
case Species.MEOWSTIC: case Species.MEOWSTIC:
case Species.INDEEDEE: case Species.INDEEDEE:
case Species.BASCULEGION: case Species.BASCULEGION:
@ -1406,7 +1479,7 @@ export default class BattleScene extends SceneBase {
if (this.gameMode.hasMysteryEncounters) { if (this.gameMode.hasMysteryEncounters) {
return 1; // Wandering form return 1; // Wandering form
} else { } else {
return Utils.randSeedInt(species.forms.length); return randSeedInt(species.forms.length);
} }
} }
@ -1416,7 +1489,7 @@ export default class BattleScene extends SceneBase {
case Species.WORMADAM: case Species.WORMADAM:
case Species.ROTOM: case Species.ROTOM:
case Species.LYCANROC: case Species.LYCANROC:
return Utils.randSeedInt(species.forms.length); return randSeedInt(species.forms.length);
} }
return 0; return 0;
} }
@ -1427,7 +1500,7 @@ export default class BattleScene extends SceneBase {
private getGeneratedOffsetGym(): boolean { private getGeneratedOffsetGym(): boolean {
let ret = false; let ret = false;
this.executeWithSeedOffset(() => { this.executeWithSeedOffset(() => {
ret = !Utils.randSeedInt(2); ret = !randSeedInt(2);
}, 0, this.seed.toString()); }, 0, this.seed.toString());
return ret; return ret;
} }
@ -1435,7 +1508,7 @@ export default class BattleScene extends SceneBase {
private getGeneratedWaveCycleOffset(): integer { private getGeneratedWaveCycleOffset(): integer {
let ret = 0; let ret = 0;
this.executeWithSeedOffset(() => { this.executeWithSeedOffset(() => {
ret = Utils.randSeedInt(8) * 5; ret = randSeedInt(8) * 5;
}, 0, this.seed.toString()); }, 0, this.seed.toString());
return ret; return ret;
} }
@ -1457,7 +1530,7 @@ export default class BattleScene extends SceneBase {
isBoss = true; isBoss = true;
} else { } else {
this.executeWithSeedOffset(() => { this.executeWithSeedOffset(() => {
isBoss = waveIndex % 10 === 0 || (this.gameMode.hasRandomBosses && Utils.randSeedInt(100) < Math.min(Math.max(Math.ceil((waveIndex - 250) / 50), 0) * 2, 30)); isBoss = waveIndex % 10 === 0 || (this.gameMode.hasRandomBosses && randSeedInt(100) < Math.min(Math.max(Math.ceil((waveIndex - 250) / 50), 0) * 2, 30));
}, waveIndex << 2); }, waveIndex << 2);
} }
if (!isBoss) { if (!isBoss) {
@ -1484,7 +1557,7 @@ export default class BattleScene extends SceneBase {
const infectedIndexes: integer[] = []; const infectedIndexes: integer[] = [];
const spread = (index: number, spreadTo: number) => { const spread = (index: number, spreadTo: number) => {
const partyMember = party[index + spreadTo]; const partyMember = party[index + spreadTo];
if (!partyMember.pokerus && !Utils.randSeedInt(10)) { if (!partyMember.pokerus && !randSeedInt(10)) {
partyMember.pokerus = true; partyMember.pokerus = true;
infectedIndexes.push(index + spreadTo); infectedIndexes.push(index + spreadTo);
} }
@ -1507,7 +1580,7 @@ export default class BattleScene extends SceneBase {
resetSeed(waveIndex?: integer): void { resetSeed(waveIndex?: integer): void {
const wave = waveIndex || this.currentBattle?.waveIndex || 0; const wave = waveIndex || this.currentBattle?.waveIndex || 0;
this.waveSeed = Utils.shiftCharCodes(this.seed, wave); this.waveSeed = shiftCharCodes(this.seed, wave);
Phaser.Math.RND.sow([ this.waveSeed ]); Phaser.Math.RND.sow([ this.waveSeed ]);
console.log("Wave Seed:", this.waveSeed, wave); console.log("Wave Seed:", this.waveSeed, wave);
this.rngCounter = 0; this.rngCounter = 0;
@ -1521,7 +1594,7 @@ export default class BattleScene extends SceneBase {
const tempRngOffset = this.rngOffset; const tempRngOffset = this.rngOffset;
const tempRngSeedOverride = this.rngSeedOverride; const tempRngSeedOverride = this.rngSeedOverride;
const state = Phaser.Math.RND.state(); const state = Phaser.Math.RND.state();
Phaser.Math.RND.sow([ Utils.shiftCharCodes(seedOverride || this.seed, offset) ]); Phaser.Math.RND.sow([ shiftCharCodes(seedOverride || this.seed, offset) ]);
this.rngCounter = 0; this.rngCounter = 0;
this.rngOffset = offset; this.rngOffset = offset;
this.rngSeedOverride = seedOverride || ""; this.rngSeedOverride = seedOverride || "";
@ -1641,7 +1714,7 @@ export default class BattleScene extends SceneBase {
if (this.money === undefined) { if (this.money === undefined) {
return; return;
} }
const formattedMoney = Utils.formatMoney(this.moneyFormat, this.money); const formattedMoney = formatMoney(this.moneyFormat, this.money);
this.moneyText.setText(i18next.t("battleScene:moneyOwned", { formattedMoney })); this.moneyText.setText(i18next.t("battleScene:moneyOwned", { formattedMoney }));
this.fieldUI.moveAbove(this.moneyText, this.luckText); this.fieldUI.moveAbove(this.moneyText, this.luckText);
if (forceVisible) { if (forceVisible) {
@ -1765,12 +1838,12 @@ export default class BattleScene extends SceneBase {
} }
return s; return s;
})) ] : allSpecies.filter(s => s.isCatchable()); })) ] : allSpecies.filter(s => s.isCatchable());
return filteredSpecies[Utils.randSeedInt(filteredSpecies.length)]; return filteredSpecies[randSeedInt(filteredSpecies.length)];
} }
generateRandomBiome(waveIndex: integer): Biome { generateRandomBiome(waveIndex: integer): Biome {
const relWave = waveIndex % 250; const relWave = waveIndex % 250;
const biomes = Utils.getEnumValues(Biome).slice(1, Utils.getEnumValues(Biome).filter(b => b >= 40).length * -1); const biomes = getEnumValues(Biome).slice(1, getEnumValues(Biome).filter(b => b >= 40).length * -1);
const maxDepth = biomeDepths[Biome.END][0] - 2; const maxDepth = biomeDepths[Biome.END][0] - 2;
const depthWeights = new Array(maxDepth + 1).fill(null) const depthWeights = new Array(maxDepth + 1).fill(null)
.map((_, i: integer) => ((1 - Math.min(Math.abs((i / (maxDepth - 1)) - (relWave / 250)) + 0.25, 1)) / 0.75) * 250); .map((_, i: integer) => ((1 - Math.min(Math.abs((i / (maxDepth - 1)) - (relWave / 250)) + 0.25, 1)) / 0.75) * 250);
@ -1781,7 +1854,7 @@ export default class BattleScene extends SceneBase {
biomeThresholds.push(totalWeight); biomeThresholds.push(totalWeight);
} }
const randInt = Utils.randSeedInt(totalWeight); const randInt = randSeedInt(totalWeight);
for (const biome of biomes) { for (const biome of biomes) {
if (randInt < biomeThresholds[biome]) { if (randInt < biomeThresholds[biome]) {
@ -1789,7 +1862,7 @@ export default class BattleScene extends SceneBase {
} }
} }
return biomes[Utils.randSeedInt(biomes.length)]; return biomes[randSeedInt(biomes.length)];
} }
isBgmPlaying(): boolean { isBgmPlaying(): boolean {
@ -1974,7 +2047,7 @@ export default class BattleScene extends SceneBase {
this.bgmResumeTimer.destroy(); this.bgmResumeTimer.destroy();
} }
if (resumeBgm) { if (resumeBgm) {
this.bgmResumeTimer = this.time.delayedCall((pauseDuration || Utils.fixedInt(sound.totalDuration * 1000)), () => { this.bgmResumeTimer = this.time.delayedCall((pauseDuration || fixedInt(sound.totalDuration * 1000)), () => {
this.resumeBgm(); this.resumeBgm();
this.bgmResumeTimer = null; this.bgmResumeTimer = null;
}); });
@ -2483,7 +2556,7 @@ export default class BattleScene extends SceneBase {
const args: unknown[] = []; const args: unknown[] = [];
if (modifier instanceof PokemonHpRestoreModifier) { if (modifier instanceof PokemonHpRestoreModifier) {
if (!(modifier as PokemonHpRestoreModifier).fainted) { if (!(modifier as PokemonHpRestoreModifier).fainted) {
const hpRestoreMultiplier = new Utils.IntegerHolder(1); const hpRestoreMultiplier = new NumberHolder(1);
this.applyModifiers(HealingBoosterModifier, true, hpRestoreMultiplier); this.applyModifiers(HealingBoosterModifier, true, hpRestoreMultiplier);
args.push(hpRestoreMultiplier.value); args.push(hpRestoreMultiplier.value);
} else { } else {
@ -2491,7 +2564,7 @@ export default class BattleScene extends SceneBase {
} }
} else if (modifier instanceof FusePokemonModifier) { } else if (modifier instanceof FusePokemonModifier) {
args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon); args.push(this.getPokemonById(modifier.fusePokemonId) as PlayerPokemon);
} else if (modifier instanceof RememberMoveModifier && !Utils.isNullOrUndefined(cost)) { } else if (modifier instanceof RememberMoveModifier && !isNullOrUndefined(cost)) {
args.push(cost); args.push(cost);
} }
@ -2564,8 +2637,8 @@ export default class BattleScene extends SceneBase {
tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, playSound: boolean, transferQuantity: integer = 1, instant?: boolean, ignoreUpdate?: boolean): Promise<boolean> { tryTransferHeldItemModifier(itemModifier: PokemonHeldItemModifier, target: Pokemon, playSound: boolean, transferQuantity: integer = 1, instant?: boolean, ignoreUpdate?: boolean): Promise<boolean> {
return new Promise(resolve => { return new Promise(resolve => {
const source = itemModifier.pokemonId ? itemModifier.getPokemon(target.scene) : null; const source = itemModifier.pokemonId ? itemModifier.getPokemon(target.scene) : null;
const cancelled = new Utils.BooleanHolder(false); const cancelled = new BooleanHolder(false);
Utils.executeIf(!!source && source.isPlayer() !== target.isPlayer(), () => applyAbAttrs(BlockItemTheftAbAttr, source! /* checked in condition*/, cancelled)).then(() => { executeIf(!!source && source.isPlayer() !== target.isPlayer(), () => applyAbAttrs(BlockItemTheftAbAttr, source! /* checked in condition*/, cancelled)).then(() => {
if (cancelled.value) { if (cancelled.value) {
return resolve(false); return resolve(false);
} }
@ -2674,7 +2747,7 @@ export default class BattleScene extends SceneBase {
pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line pokemonModifierChance = Math.ceil(pokemonModifierChance * this.currentBattle.trainer.getPartyMemberModifierChanceMultiplier(i)); // eslint-disable-line
let count = 0; let count = 0;
for (let c = 0; c < chances; c++) { for (let c = 0; c < chances; c++) {
if (!Utils.randSeedInt(modifierChance)) { if (!randSeedInt(modifierChance)) {
count++; count++;
} }
} }
@ -2825,7 +2898,7 @@ export default class BattleScene extends SceneBase {
if (mods.length < 1) { if (mods.length < 1) {
return mods; return mods;
} }
const rand = Utils.randSeedInt(mods.length); const rand = randSeedInt(mods.length);
return [ mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand)) ]; return [ mods[rand], ...shuffleModifiers(mods.filter((_, i) => i !== rand)) ];
}; };
modifiers = shuffleModifiers(modifiers); modifiers = shuffleModifiers(modifiers);
@ -3007,7 +3080,7 @@ export default class BattleScene extends SceneBase {
*/ */
initFinalBossPhaseTwo(pokemon: Pokemon): void { initFinalBossPhaseTwo(pokemon: Pokemon): void {
if (pokemon instanceof EnemyPokemon && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) { if (pokemon instanceof EnemyPokemon && pokemon.isBoss() && !pokemon.formIndex && pokemon.bossSegmentIndex < 1) {
this.fadeOutBgm(Utils.fixedInt(2000), false); this.fadeOutBgm(fixedInt(2000), false);
this.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin, pokemon.species.name, undefined, () => { this.ui.showDialogue(battleSpecDialogue[BattleSpec.FINAL_BOSS].firstStageWin, pokemon.species.name, undefined, () => {
const finalBossMBH = getModifierType(modifierTypes.MINI_BLACK_HOLE).newModifier(pokemon) as TurnHeldItemTransferModifier; const finalBossMBH = getModifierType(modifierTypes.MINI_BLACK_HOLE).newModifier(pokemon) as TurnHeldItemTransferModifier;
finalBossMBH.setTransferrableFalse(); finalBossMBH.setTransferrableFalse();
@ -3093,7 +3166,7 @@ export default class BattleScene extends SceneBase {
if (Overrides.XP_MULTIPLIER_OVERRIDE !== null) { if (Overrides.XP_MULTIPLIER_OVERRIDE !== null) {
expMultiplier = Overrides.XP_MULTIPLIER_OVERRIDE; expMultiplier = Overrides.XP_MULTIPLIER_OVERRIDE;
} }
const pokemonExp = new Utils.NumberHolder(expValue * expMultiplier); const pokemonExp = new NumberHolder(expValue * expMultiplier);
this.applyModifiers(PokemonExpBoosterModifier, true, partyMember, pokemonExp); this.applyModifiers(PokemonExpBoosterModifier, true, partyMember, pokemonExp);
partyMemberExp.push(Math.floor(pokemonExp.value)); partyMemberExp.push(Math.floor(pokemonExp.value));
} }
@ -3209,7 +3282,7 @@ export default class BattleScene extends SceneBase {
while (i < this.mysteryEncounterSaveData.queuedEncounters.length && !!encounter) { while (i < this.mysteryEncounterSaveData.queuedEncounters.length && !!encounter) {
const candidate = this.mysteryEncounterSaveData.queuedEncounters[i]; const candidate = this.mysteryEncounterSaveData.queuedEncounters[i];
const forcedChance = candidate.spawnPercent; const forcedChance = candidate.spawnPercent;
if (Utils.randSeedInt(100) < forcedChance) { if (randSeedInt(100) < forcedChance) {
encounter = allMysteryEncounters[candidate.type]; encounter = allMysteryEncounters[candidate.type];
} }
@ -3236,7 +3309,7 @@ export default class BattleScene extends SceneBase {
}); });
const totalWeight = tierWeights.reduce((a, b) => a + b); const totalWeight = tierWeights.reduce((a, b) => a + b);
const tierValue = Utils.randSeedInt(totalWeight); const tierValue = randSeedInt(totalWeight);
const commonThreshold = totalWeight - tierWeights[0]; const commonThreshold = totalWeight - tierWeights[0];
const greatThreshold = totalWeight - tierWeights[0] - tierWeights[1]; const greatThreshold = totalWeight - tierWeights[0] - tierWeights[1];
const ultraThreshold = totalWeight - tierWeights[0] - tierWeights[1] - tierWeights[2]; const ultraThreshold = totalWeight - tierWeights[0] - tierWeights[1] - tierWeights[2];
@ -3303,7 +3376,7 @@ export default class BattleScene extends SceneBase {
console.log("No Mystery Encounters found, falling back to Mysterious Challengers."); console.log("No Mystery Encounters found, falling back to Mysterious Challengers.");
return allMysteryEncounters[MysteryEncounterType.MYSTERIOUS_CHALLENGERS]; return allMysteryEncounters[MysteryEncounterType.MYSTERIOUS_CHALLENGERS];
} }
encounter = availableEncounters[Utils.randSeedInt(availableEncounters.length)]; encounter = availableEncounters[randSeedInt(availableEncounters.length)];
// New encounter object to not dirty flags // New encounter object to not dirty flags
encounter = new MysteryEncounter(encounter); encounter = new MysteryEncounter(encounter);
encounter.populateDialogueTokensFromRequirements(this); encounter.populateDialogueTokensFromRequirements(this);

View File

@ -1,10 +1,18 @@
import BattleScene from "./battle-scene"; import BattleScene from "./battle-scene";
import { Command } from "./ui/command-ui-handler"; import { Command } from "#app/ui/command-ui-handler";
import * as Utils from "./utils"; import {
randomString,
getEnumValues,
NumberHolder,
randSeedInt,
shiftCharCodes,
randSeedItem,
randInt,
} from "#app/utils";
import Trainer, { TrainerVariant } from "./field/trainer"; import Trainer, { TrainerVariant } from "./field/trainer";
import { GameMode } from "./game-mode"; import { GameMode } from "#app/game-mode";
import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "./modifier/modifier"; import { MoneyMultiplierModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
import { PokeballType } from "./data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import { trainerConfigs } from "#app/data/trainer-config"; import { trainerConfigs } from "#app/data/trainer-config";
import Pokemon, { EnemyPokemon, PlayerPokemon, QueuedMove } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PlayerPokemon, QueuedMove } from "#app/field/pokemon";
import { ArenaTagType } from "#enums/arena-tag-type"; import { ArenaTagType } from "#enums/arena-tag-type";
@ -14,7 +22,7 @@ import { PlayerGender } from "#enums/player-gender";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import i18next from "#app/plugins/i18n"; import i18next from "#app/plugins/i18n";
import MysteryEncounter from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { CustomModifierSettings } from "#app/modifier/modifier-type"; import { CustomModifierSettings } from "#app/modifier/modifier-type";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
@ -78,7 +86,7 @@ export default class Battle {
public postBattleLoot: PokemonHeldItemModifier[] = []; public postBattleLoot: PokemonHeldItemModifier[] = [];
public escapeAttempts: number = 0; public escapeAttempts: number = 0;
public lastMove: Moves; public lastMove: Moves;
public battleSeed: string = Utils.randomString(16, true); public battleSeed: string = randomString(16, true);
private battleSeedState: string | null = null; private battleSeedState: string | null = null;
public moneyScattered: number = 0; public moneyScattered: number = 0;
public lastUsedPokeball: PokeballType | null = null; public lastUsedPokeball: PokeballType | null = null;
@ -154,7 +162,7 @@ export default class Battle {
incrementTurn(scene: BattleScene): void { incrementTurn(scene: BattleScene): void {
this.turn++; this.turn++;
this.turnCommands = Object.fromEntries(Utils.getEnumValues(BattlerIndex).map(bt => [ bt, null ])); this.turnCommands = Object.fromEntries(getEnumValues(BattlerIndex).map(bt => [ bt, null ]));
this.battleSeedState = null; this.battleSeedState = null;
} }
@ -176,7 +184,7 @@ export default class Battle {
} }
pickUpScatteredMoney(scene: BattleScene): void { pickUpScatteredMoney(scene: BattleScene): void {
const moneyAmount = new Utils.IntegerHolder(scene.currentBattle.moneyScattered); const moneyAmount = new NumberHolder(scene.currentBattle.moneyScattered);
scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount); scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
if (scene.arena.getTag(ArenaTagType.HAPPY_HOUR)) { if (scene.arena.getTag(ArenaTagType.HAPPY_HOUR)) {
@ -382,7 +390,7 @@ export default class Battle {
} }
/** /**
* Generates a random number using the current battle's seed. Calls {@linkcode Utils.randSeedInt} * Generates a random number using the current battle's seed. Calls {@linkcode randSeedInt}
* @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min} * @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min}
* @param min The minimum integer to pick, default `0` * @param min The minimum integer to pick, default `0`
* @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1) * @returns A random integer between {@linkcode min} and ({@linkcode min} + {@linkcode range} - 1)
@ -397,12 +405,12 @@ export default class Battle {
if (this.battleSeedState) { if (this.battleSeedState) {
Phaser.Math.RND.state(this.battleSeedState); Phaser.Math.RND.state(this.battleSeedState);
} else { } else {
Phaser.Math.RND.sow([ Utils.shiftCharCodes(this.battleSeed, this.turn << 6) ]); Phaser.Math.RND.sow([ shiftCharCodes(this.battleSeed, this.turn << 6) ]);
console.log("Battle Seed:", this.battleSeed); console.log("Battle Seed:", this.battleSeed);
} }
scene.rngCounter = this.rngCounter++; scene.rngCounter = this.rngCounter++;
scene.rngSeedOverride = this.battleSeed; scene.rngSeedOverride = this.battleSeed;
const ret = Utils.randSeedInt(range, min); const ret = randSeedInt(range, min);
this.battleSeedState = Phaser.Math.RND.state(); this.battleSeedState = Phaser.Math.RND.state();
Phaser.Math.RND.state(state); Phaser.Math.RND.state(state);
scene.rngCounter = tempRngCounter; scene.rngCounter = tempRngCounter;
@ -479,13 +487,13 @@ export class FixedBattleConfig {
*/ */
function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], randomGender: boolean = false, seedOffset: number = 0): GetTrainerFunc { function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], randomGender: boolean = false, seedOffset: number = 0): GetTrainerFunc {
return (scene: BattleScene) => { return (scene: BattleScene) => {
const rand = Utils.randSeedInt(trainerPool.length); const rand = randSeedInt(trainerPool.length);
const trainerTypes: TrainerType[] = []; const trainerTypes: TrainerType[] = [];
scene.executeWithSeedOffset(() => { scene.executeWithSeedOffset(() => {
for (const trainerPoolEntry of trainerPool) { for (const trainerPoolEntry of trainerPool) {
const trainerType = Array.isArray(trainerPoolEntry) const trainerType = Array.isArray(trainerPoolEntry)
? Utils.randSeedItem(trainerPoolEntry) ? randSeedItem(trainerPoolEntry)
: trainerPoolEntry; : trainerPoolEntry;
trainerTypes.push(trainerType); trainerTypes.push(trainerType);
} }
@ -493,7 +501,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand
let trainerGender = TrainerVariant.DEFAULT; let trainerGender = TrainerVariant.DEFAULT;
if (randomGender) { if (randomGender) {
trainerGender = (Utils.randInt(2) === 0) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT; trainerGender = (randInt(2) === 0) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT;
} }
/* 1/3 chance for evil team grunts to be double battles */ /* 1/3 chance for evil team grunts to be double battles */
@ -501,7 +509,7 @@ function getRandomTrainerFunc(trainerPool: (TrainerType | TrainerType[])[], rand
const isEvilTeamGrunt = evilTeamGrunts.includes(trainerTypes[rand]); const isEvilTeamGrunt = evilTeamGrunts.includes(trainerTypes[rand]);
if (trainerConfigs[trainerTypes[rand]].hasDouble && isEvilTeamGrunt) { if (trainerConfigs[trainerTypes[rand]].hasDouble && isEvilTeamGrunt) {
return new Trainer(scene, trainerTypes[rand], (Utils.randInt(3) === 0) ? TrainerVariant.DOUBLE : trainerGender); return new Trainer(scene, trainerTypes[rand], (randInt(3) === 0) ? TrainerVariant.DOUBLE : trainerGender);
} }
return new Trainer(scene, trainerTypes[rand], trainerGender); return new Trainer(scene, trainerTypes[rand], trainerGender);
@ -522,7 +530,7 @@ export interface FixedBattleConfigs {
*/ */
export const classicFixedBattles: FixedBattleConfigs = { export const classicFixedBattles: FixedBattleConfigs = {
[5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [5]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, Utils.randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.YOUNGSTER, randSeedInt(2) ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
[8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [8]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)
.setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)), .setGetTrainerFunc(scene => new Trainer(scene, TrainerType.RIVAL, scene.gameData.gender === PlayerGender.MALE ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT)),
[25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER) [25]: new FixedBattleConfig().setBattleType(BattleType.TRAINER)

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,13 @@ import { getPokemonNameWithAffix } from "#app/messages";
import Pokemon, { HitResult, PokemonMove } from "#app/field/pokemon"; import Pokemon, { HitResult, PokemonMove } from "#app/field/pokemon";
import { StatusEffect } from "#app/data/status-effect"; import { StatusEffect } from "#app/data/status-effect";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { BlockNonDirectDamageAbAttr, ChangeMovePriorityAbAttr, InfiltratorAbAttr, ProtectStatAbAttr, applyAbAttrs } from "#app/data/ability"; import {
BlockNonDirectDamageAbAttr,
ChangeMovePriorityAbAttr,
InfiltratorAbAttr,
ProtectStatAbAttr,
applyAbAttrs,
} from "#app/data/ability";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims"; import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims";
import i18next from "i18next"; import i18next from "i18next";
@ -15,11 +21,11 @@ import { Abilities } from "#enums/abilities";
import { ArenaTagType } from "#enums/arena-tag-type"; import { ArenaTagType } from "#enums/arena-tag-type";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEffectPhase } from "#phases/move-effect-phase";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { PokemonHealPhase } from "#phases/pokemon-heal-phase";
import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { ShowAbilityPhase } from "#phases/show-ability-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase";
import { CommonAnimPhase } from "#app/phases/common-anim-phase"; import { CommonAnimPhase } from "#phases/common-anim-phase";
export enum ArenaTagSide { export enum ArenaTagSide {
BOTH, BOTH,

View File

@ -1,12 +1,11 @@
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import * as Utils from "#app/utils"; import { randInt, getEnumValues } from "#app/utils";
import { pokemonEvolutions, SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions"; import { pokemonEvolutions, SpeciesFormEvolution } from "#balance/pokemon-evolutions";
import i18next from "i18next"; import i18next from "i18next";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { TimeOfDay } from "#enums/time-of-day"; import { TimeOfDay } from "#enums/time-of-day";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
// import beautify from "json-beautify";
export function getBiomeName(biome: Biome | -1) { export function getBiomeName(biome: Biome | -1) {
if (biome === -1) { if (biome === -1) {
@ -7666,7 +7665,7 @@ export function initBiomes() {
if (biome === Biome.END) { if (biome === Biome.END) {
const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key))); const biomeList = Object.keys(Biome).filter(key => !isNaN(Number(key)));
biomeList.pop(); // Removes Biome.END from the list biomeList.pop(); // Removes Biome.END from the list
const randIndex = Utils.randInt(biomeList.length, 1); // Will never be Biome.TOWN const randIndex = randInt(biomeList.length, 1); // Will never be Biome.TOWN
biome = Biome[biomeList[randIndex]]; biome = Biome[biomeList[randIndex]];
} }
const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome]) const linkedBiomes: (Biome | [ Biome, integer ])[] = Array.isArray(biomeLinks[biome])
@ -7689,15 +7688,15 @@ export function initBiomes() {
traverseBiome(Biome.TOWN, 0); traverseBiome(Biome.TOWN, 0);
biomeDepths[Biome.END] = [ Object.values(biomeDepths).map(d => d[0]).reduce((max: integer, value: integer) => Math.max(max, value), 0) + 1, 1 ]; biomeDepths[Biome.END] = [ Object.values(biomeDepths).map(d => d[0]).reduce((max: integer, value: integer) => Math.max(max, value), 0) + 1, 1 ];
for (const biome of Utils.getEnumValues(Biome)) { for (const biome of getEnumValues(Biome)) {
biomePokemonPools[biome] = {}; biomePokemonPools[biome] = {};
biomeTrainerPools[biome] = {}; biomeTrainerPools[biome] = {};
for (const tier of Utils.getEnumValues(BiomePoolTier)) { for (const tier of getEnumValues(BiomePoolTier)) {
biomePokemonPools[biome][tier] = {}; biomePokemonPools[biome][tier] = {};
biomeTrainerPools[biome][tier] = []; biomeTrainerPools[biome][tier] = [];
for (const tod of Utils.getEnumValues(TimeOfDay)) { for (const tod of getEnumValues(TimeOfDay)) {
biomePokemonPools[biome][tier][tod] = []; biomePokemonPools[biome][tier][tod] = [];
} }
} }

View File

@ -1,5 +1,5 @@
import { allMoves } from "#app/data/move"; import { allMoves } from "#app/data/move";
import * as Utils from "#app/utils"; import { getEnumKeys, getEnumValues } from "#app/utils";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
@ -579,8 +579,8 @@ export const speciesEggMoves = {
function parseEggMoves(content: string): void { function parseEggMoves(content: string): void {
let output = ""; let output = "";
const speciesNames = Utils.getEnumKeys(Species); const speciesNames = getEnumKeys(Species);
const speciesValues = Utils.getEnumValues(Species); const speciesValues = getEnumValues(Species);
const lines = content.split(/\n/g); const lines = content.split(/\n/g);
lines.forEach((line, l) => { lines.forEach((line, l) => {

View File

@ -1,5 +1,5 @@
import { Abilities } from "#app/enums/abilities"; import { Abilities } from "#enums/abilities";
import { Species } from "#app/enums/species"; import { Species } from "#enums/species";
export const starterPassiveAbilities = { export const starterPassiveAbilities = {
[Species.BULBASAUR]: Abilities.GRASSY_SURGE, [Species.BULBASAUR]: Abilities.GRASSY_SURGE,

View File

@ -3,7 +3,7 @@ import { PokeballType } from "#app/data/pokeball";
import Pokemon from "#app/field/pokemon"; import Pokemon from "#app/field/pokemon";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import * as Utils from "#app/utils"; import { randSeedInt } from "#app/utils";
import { WeatherType } from "#app/data/weather"; import { WeatherType } from "#app/data/weather";
import { Nature } from "#app/data/nature"; import { Nature } from "#app/data/nature";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
@ -1172,7 +1172,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
[Species.TANDEMAUS]: [ [Species.TANDEMAUS]: [
new SpeciesFormEvolution(Species.MAUSHOLD, "", "three", 25, null, new SpeciesEvolutionCondition(p => { new SpeciesFormEvolution(Species.MAUSHOLD, "", "three", 25, null, new SpeciesEvolutionCondition(p => {
let ret = false; let ret = false;
p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); p.scene.executeWithSeedOffset(() => ret = !randSeedInt(4), p.id);
return ret; return ret;
})), })),
new SpeciesEvolution(Species.MAUSHOLD, 25, null, null) new SpeciesEvolution(Species.MAUSHOLD, 25, null, null)
@ -1340,7 +1340,7 @@ export const pokemonEvolutions: PokemonEvolutions = {
new SpeciesFormEvolution(Species.DUDUNSPARCE, "", "three-segment", 32, null, new SpeciesEvolutionCondition(p => { new SpeciesFormEvolution(Species.DUDUNSPARCE, "", "three-segment", 32, null, new SpeciesEvolutionCondition(p => {
let ret = false; let ret = false;
if (p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0) { if (p.moveset.filter(m => m?.moveId === Moves.HYPER_DRILL).length > 0) {
p.scene.executeWithSeedOffset(() => ret = !Utils.randSeedInt(4), p.id); p.scene.executeWithSeedOffset(() => ret = !randSeedInt(4), p.id);
} }
return ret; return ret;
}), SpeciesWildEvolutionDelay.LONG), }), SpeciesWildEvolutionDelay.LONG),

View File

@ -1,13 +1,20 @@
//import { battleAnimRawData } from "./battle-anim-raw-data"; //import { battleAnimRawData } from "./battle-anim-raw-data";
import BattleScene from "../battle-scene"; import BattleScene from "#app/battle-scene";
import { AttackMove, BeakBlastHeaderAttr, ChargeAttr, DelayedAttackAttr, MoveFlags, SelfStatusMove, allMoves } from "./move"; import {
import Pokemon from "../field/pokemon"; AttackMove,
import * as Utils from "../utils"; BeakBlastHeaderAttr,
import { BattlerIndex } from "../battle"; ChargeAttr,
DelayedAttackAttr,
MoveFlags,
SelfStatusMove,
allMoves,
} from "./move";
import Pokemon from "#app/field/pokemon";
import { getFrameMs, getEnumKeys, getEnumValues, animationFileName, isNullOrUndefined } from "#app/utils";
import { BattlerIndex } from "#app/battle";
import { Element } from "json-stable-stringify"; import { Element } from "json-stable-stringify";
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 Phaser from "phaser"; import Phaser from "phaser";
import { EncounterAnim } from "#enums/encounter-anims"; import { EncounterAnim } from "#enums/encounter-anims";
//import fs from 'vite-plugin-fs/browser'; //import fs from 'vite-plugin-fs/browser';
@ -401,7 +408,7 @@ class AnimTimedUpdateBgEvent extends AnimTimedBgEvent {
if (Object.keys(tweenProps).length) { if (Object.keys(tweenProps).length) {
scene.tweens.add(Object.assign({ scene.tweens.add(Object.assign({
targets: moveAnim.bgSprite, targets: moveAnim.bgSprite,
duration: Utils.getFrameMs(this.duration * 3) duration: getFrameMs(this.duration * 3)
}, tweenProps)); }, tweenProps));
} }
return this.duration * 2; return this.duration * 2;
@ -437,7 +444,7 @@ class AnimTimedAddBgEvent extends AnimTimedBgEvent {
scene.tweens.add({ scene.tweens.add({
targets: moveAnim.bgSprite, targets: moveAnim.bgSprite,
duration: Utils.getFrameMs(this.duration * 3) duration: getFrameMs(this.duration * 3)
}); });
return this.duration * 2; return this.duration * 2;
@ -455,8 +462,8 @@ export const encounterAnims = new Map<EncounterAnim, AnimConfig>();
export function initCommonAnims(scene: BattleScene): Promise<void> { export function initCommonAnims(scene: BattleScene): Promise<void> {
return new Promise(resolve => { return new Promise(resolve => {
const commonAnimNames = Utils.getEnumKeys(CommonAnim); const commonAnimNames = getEnumKeys(CommonAnim);
const commonAnimIds = Utils.getEnumValues(CommonAnim); const commonAnimIds = getEnumValues(CommonAnim);
const commonAnimFetches: Promise<Map<CommonAnim, AnimConfig>>[] = []; const commonAnimFetches: Promise<Map<CommonAnim, AnimConfig>>[] = [];
for (let ca = 0; ca < commonAnimIds.length; ca++) { for (let ca = 0; ca < commonAnimIds.length; ca++) {
const commonAnimId = commonAnimIds[ca]; const commonAnimId = commonAnimIds[ca];
@ -490,7 +497,7 @@ export function initMoveAnim(scene: BattleScene, move: Moves): Promise<void> {
const defaultMoveAnim = allMoves[move] instanceof AttackMove ? Moves.TACKLE : allMoves[move] instanceof SelfStatusMove ? Moves.FOCUS_ENERGY : Moves.TAIL_WHIP; const defaultMoveAnim = allMoves[move] instanceof AttackMove ? Moves.TACKLE : allMoves[move] instanceof SelfStatusMove ? Moves.FOCUS_ENERGY : Moves.TAIL_WHIP;
const fetchAnimAndResolve = (move: Moves) => { const fetchAnimAndResolve = (move: Moves) => {
scene.cachedFetch(`./battle-anims/${Utils.animationFileName(move)}.json`) scene.cachedFetch(`./battle-anims/${animationFileName(move)}.json`)
.then(response => { .then(response => {
const contentType = response.headers.get("content-type"); const contentType = response.headers.get("content-type");
if (!response.ok || contentType?.indexOf("application/json") === -1) { if (!response.ok || contentType?.indexOf("application/json") === -1) {
@ -546,7 +553,7 @@ function useDefaultAnim(move: Moves, defaultMoveAnim: Moves) {
* @remarks use {@linkcode useDefaultAnim} to use a default animation * @remarks use {@linkcode useDefaultAnim} to use a default animation
*/ */
function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) { function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) {
const moveName = Utils.animationFileName(move); const moveName = animationFileName(move);
console.warn(`Could not load animation file for move '${moveName}'`, ...optionalParams); console.warn(`Could not load animation file for move '${moveName}'`, ...optionalParams);
} }
@ -557,7 +564,7 @@ function logMissingMoveAnim(move: Moves, ...optionalParams: any[]) {
*/ */
export async function initEncounterAnims(scene: BattleScene, encounterAnim: EncounterAnim | EncounterAnim[]): Promise<void> { export async function initEncounterAnims(scene: BattleScene, encounterAnim: EncounterAnim | EncounterAnim[]): Promise<void> {
const anims = Array.isArray(encounterAnim) ? encounterAnim : [ encounterAnim ]; const anims = Array.isArray(encounterAnim) ? encounterAnim : [ encounterAnim ];
const encounterAnimNames = Utils.getEnumKeys(EncounterAnim); const encounterAnimNames = getEnumKeys(EncounterAnim);
const encounterAnimFetches: Promise<Map<EncounterAnim, AnimConfig>>[] = []; const encounterAnimFetches: Promise<Map<EncounterAnim, AnimConfig>>[] = [];
for (const anim of anims) { for (const anim of anims) {
if (encounterAnims.has(anim) && !isNullOrUndefined(encounterAnims.get(anim))) { if (encounterAnims.has(anim) && !isNullOrUndefined(encounterAnims.get(anim))) {
@ -919,7 +926,7 @@ export abstract class BattleAnim {
let f = 0; let f = 0;
scene.tweens.addCounter({ scene.tweens.addCounter({
duration: Utils.getFrameMs(3), duration: getFrameMs(3),
repeat: anim?.frames.length ?? 0, repeat: anim?.frames.length ?? 0,
onRepeat: () => { onRepeat: () => {
if (!f) { if (!f) {
@ -1053,7 +1060,7 @@ export abstract class BattleAnim {
r = Math.max((anim.frames.length - f) + event.execute(scene, this), r); r = Math.max((anim.frames.length - f) + event.execute(scene, this), r);
} }
} }
const targets = Utils.getEnumValues(AnimFrameTarget); const targets = getEnumValues(AnimFrameTarget);
for (const i of targets) { for (const i of targets) {
const count = i === AnimFrameTarget.GRAPHIC ? g : i === AnimFrameTarget.USER ? u : t; const count = i === AnimFrameTarget.GRAPHIC ? g : i === AnimFrameTarget.USER ? u : t;
if (count < spriteCache[i].length) { if (count < spriteCache[i].length) {
@ -1081,7 +1088,7 @@ export abstract class BattleAnim {
} }
if (r) { if (r) {
scene.tweens.addCounter({ scene.tweens.addCounter({
duration: Utils.getFrameMs(r), duration: getFrameMs(r),
onComplete: () => cleanUpAndComplete() onComplete: () => cleanUpAndComplete()
}); });
} else { } else {
@ -1165,7 +1172,7 @@ export abstract class BattleAnim {
let existingFieldSprites = scene.field.getAll().slice(0); let existingFieldSprites = scene.field.getAll().slice(0);
scene.tweens.addCounter({ scene.tweens.addCounter({
duration: Utils.getFrameMs(3) * frameTimeMult, duration: getFrameMs(3) * frameTimeMult,
repeat: anim!.frames.length, repeat: anim!.frames.length,
onRepeat: () => { onRepeat: () => {
existingFieldSprites = scene.field.getAll().slice(0); existingFieldSprites = scene.field.getAll().slice(0);
@ -1218,7 +1225,7 @@ export abstract class BattleAnim {
totalFrames = Math.max((anim.frames.length - frameCount) + event.execute(scene, this, frameTimedEventPriority), totalFrames); totalFrames = Math.max((anim.frames.length - frameCount) + event.execute(scene, this, frameTimedEventPriority), totalFrames);
} }
} }
const targets = Utils.getEnumValues(AnimFrameTarget); const targets = getEnumValues(AnimFrameTarget);
for (const i of targets) { for (const i of targets) {
const count = graphicFrameCount; const count = graphicFrameCount;
if (count < spriteCache[i].length) { if (count < spriteCache[i].length) {
@ -1243,7 +1250,7 @@ export abstract class BattleAnim {
} }
if (totalFrames) { if (totalFrames) {
scene.tweens.addCounter({ scene.tweens.addCounter({
duration: Utils.getFrameMs(totalFrames), duration: getFrameMs(totalFrames),
onComplete: () => cleanUpAndComplete() onComplete: () => cleanUpAndComplete()
}); });
} else { } else {
@ -1341,15 +1348,15 @@ export class EncounterBattleAnim extends BattleAnim {
} }
export async function populateAnims() { export async function populateAnims() {
const commonAnimNames = Utils.getEnumKeys(CommonAnim).map(k => k.toLowerCase()); const commonAnimNames = getEnumKeys(CommonAnim).map(k => k.toLowerCase());
const commonAnimMatchNames = commonAnimNames.map(k => k.replace(/\_/g, "")); const commonAnimMatchNames = commonAnimNames.map(k => k.replace(/\_/g, ""));
const commonAnimIds = Utils.getEnumValues(CommonAnim) as CommonAnim[]; const commonAnimIds = getEnumValues(CommonAnim) as CommonAnim[];
const chargeAnimNames = Utils.getEnumKeys(ChargeAnim).map(k => k.toLowerCase()); const chargeAnimNames = getEnumKeys(ChargeAnim).map(k => k.toLowerCase());
const chargeAnimMatchNames = chargeAnimNames.map(k => k.replace(/\_/g, " ")); const chargeAnimMatchNames = chargeAnimNames.map(k => k.replace(/\_/g, " "));
const chargeAnimIds = Utils.getEnumValues(ChargeAnim) as ChargeAnim[]; const chargeAnimIds = getEnumValues(ChargeAnim) as ChargeAnim[];
const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/; const commonNamePattern = /name: (?:Common:)?(Opp )?(.*)/;
const moveNameToId = {}; const moveNameToId = {};
for (const move of Utils.getEnumValues(Moves).slice(1)) { for (const move of getEnumValues(Moves).slice(1)) {
const moveName = Moves[move].toUpperCase().replace(/\_/g, ""); const moveName = Moves[move].toUpperCase().replace(/\_/g, "");
moveNameToId[moveName] = move; moveNameToId[moveName] = move;
} }

View File

@ -1,44 +1,44 @@
import BattleScene from "#app/battle-scene"; import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveChargeAnim } from "./battle-anims";
import { getPokemonNameWithAffix } from "#app/messages";
import Pokemon, { MoveResult, HitResult } from "#app/field/pokemon";
import { StatusEffect } from "./status-effect";
import { toDmgValue, BooleanHolder, getFrameMs, NumberHolder } from "#app/utils";
import Move, {
ChargeAttr,
MoveFlags,
allMoves,
MoveCategory,
applyMoveAttrs,
StatusCategoryOnAllyAttr,
HealOnAllyAttr,
ConsecutiveUseDoublePowerAttr,
} from "./move";
import { Type } from "./type";
import { import {
allAbilities,
applyAbAttrs,
BlockNonDirectDamageAbAttr, BlockNonDirectDamageAbAttr,
FlinchEffectAbAttr, FlinchEffectAbAttr,
ReverseDrainAbAttr,
applyAbAttrs,
ProtectStatAbAttr, ProtectStatAbAttr,
ReverseDrainAbAttr } from "./ability";
} from "#app/data/ability"; import { TerrainType } from "./terrain";
import { ChargeAnim, CommonAnim, CommonBattleAnim, MoveChargeAnim } from "#app/data/battle-anims"; import { WeatherType } from "./weather";
import Move, { import { allAbilities } from "./ability";
allMoves, import { SpeciesFormChangeManualTrigger } from "./pokemon-forms";
applyMoveAttrs,
ChargeAttr,
ConsecutiveUseDoublePowerAttr,
HealOnAllyAttr,
MoveCategory,
MoveFlags,
StatusCategoryOnAllyAttr
} from "#app/data/move";
import { SpeciesFormChangeManualTrigger } from "#app/data/pokemon-forms";
import { StatusEffect } from "#app/data/status-effect";
import { TerrainType } from "#app/data/terrain";
import { Type } from "#app/data/type";
import { WeatherType } from "#app/data/weather";
import Pokemon, { HitResult, MoveResult } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages";
import { CommonAnimPhase } from "#app/phases/common-anim-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { MovePhase } from "#app/phases/move-phase";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase";
import { ShowAbilityPhase } from "#app/phases/show-ability-phase";
import { StatStageChangeCallback, StatStageChangePhase } from "#app/phases/stat-stage-change-phase";
import i18next from "#app/plugins/i18n";
import { BooleanHolder, getFrameMs, NumberHolder, toDmgValue } from "#app/utils";
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";
import { PokemonAnimType } from "#enums/pokemon-anim-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { EFFECTIVE_STATS, getStatKey, Stat, type BattleStat, type EffectiveStat } from "#enums/stat"; import i18next from "#app/plugins/i18n";
import { Stat, type BattleStat, type EffectiveStat, EFFECTIVE_STATS, getStatKey } from "#enums/stat";
import { CommonAnimPhase } from "#phases/common-anim-phase";
import { MoveEffectPhase } from "#phases/move-effect-phase";
import { MovePhase } from "#phases/move-phase";
import { PokemonHealPhase } from "#phases/pokemon-heal-phase";
import { ShowAbilityPhase } from "#phases/show-ability-phase";
import { StatStageChangePhase, StatStageChangeCallback } from "#phases/stat-stage-change-phase";
import { PokemonAnimType } from "#enums/pokemon-anim-type";
import BattleScene from "#app/battle-scene";
export enum BattlerTagLapseType { export enum BattlerTagLapseType {
FAINT, FAINT,

View File

@ -1,14 +1,14 @@
import { getPokemonNameWithAffix } from "../messages"; import { getPokemonNameWithAffix } from "#app/messages";
import Pokemon, { HitResult } from "../field/pokemon"; import Pokemon, { HitResult } from "#app/field/pokemon";
import { getStatusEffectHealText } from "./status-effect"; import { getStatusEffectHealText } from "./status-effect";
import * as Utils from "../utils"; import { NumberHolder, toDmgValue, randSeedInt } from "#app/utils";
import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./ability"; import { DoubleBerryEffectAbAttr, ReduceBerryUseThresholdAbAttr, applyAbAttrs } from "./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";
import { Stat, type BattleStat } from "#app/enums/stat"; import { Stat, type BattleStat } from "#enums/stat";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { PokemonHealPhase } from "#phases/pokemon-heal-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase";
export function getBerryName(berryType: BerryType): string { export function getBerryName(berryType: BerryType): string {
return i18next.t(`berry:${BerryType[berryType]}.name`); return i18next.t(`berry:${BerryType[berryType]}.name`);
@ -34,7 +34,7 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
case BerryType.APICOT: case BerryType.APICOT:
case BerryType.SALAC: case BerryType.SALAC:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new NumberHolder(0.25);
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
const stat: BattleStat = berryType - BerryType.ENIGMA; const stat: BattleStat = berryType - BerryType.ENIGMA;
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
@ -42,19 +42,19 @@ export function getBerryPredicate(berryType: BerryType): BerryPredicate {
}; };
case BerryType.LANSAT: case BerryType.LANSAT:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST); return pokemon.getHpRatio() < 0.25 && !pokemon.getTag(BattlerTagType.CRIT_BOOST);
}; };
case BerryType.STARF: case BerryType.STARF:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return pokemon.getHpRatio() < 0.25; return pokemon.getHpRatio() < 0.25;
}; };
case BerryType.LEPPA: case BerryType.LEPPA:
return (pokemon: Pokemon) => { return (pokemon: Pokemon) => {
const threshold = new Utils.NumberHolder(0.25); const threshold = new NumberHolder(0.25);
applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold); applyAbAttrs(ReduceBerryUseThresholdAbAttr, pokemon, null, false, threshold);
return !!pokemon.getMoveset().find(m => !m?.getPpRatio()); return !!pokemon.getMoveset().find(m => !m?.getPpRatio());
}; };
@ -71,7 +71,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
const hpHealed = new Utils.NumberHolder(Utils.toDmgValue(pokemon.getMaxHp() / 4)); const hpHealed = new NumberHolder(toDmgValue(pokemon.getMaxHp() / 4));
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, hpHealed);
pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(), pokemon.scene.unshiftPhase(new PokemonHealPhase(pokemon.scene, pokemon.getBattlerIndex(),
hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true)); hpHealed.value, i18next.t("battle:hpHealBerry", { pokemonNameWithAffix: getPokemonNameWithAffix(pokemon), berryName: getBerryName(berryType) }), true));
@ -98,7 +98,7 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
} }
// Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth // Offset BerryType such that LIECHI -> Stat.ATK = 1, GANLON -> Stat.DEF = 2, so on and so forth
const stat: BattleStat = berryType - BerryType.ENIGMA; const stat: BattleStat = berryType - BerryType.ENIGMA;
const statStages = new Utils.NumberHolder(1); const statStages = new NumberHolder(1);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, statStages);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ stat ], statStages.value));
}; };
@ -114,8 +114,8 @@ export function getBerryEffectFunc(berryType: BerryType): BerryEffectFunc {
if (pokemon.battleData) { if (pokemon.battleData) {
pokemon.battleData.berriesEaten.push(berryType); pokemon.battleData.berriesEaten.push(berryType);
} }
const randStat = Utils.randSeedInt(Stat.SPD, Stat.ATK); const randStat = randSeedInt(Stat.SPD, Stat.ATK);
const stages = new Utils.NumberHolder(2); const stages = new NumberHolder(2);
applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages); applyAbAttrs(DoubleBerryEffectAbAttr, pokemon, null, false, stages);
pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value)); pokemon.scene.unshiftPhase(new StatStageChangePhase(pokemon.scene, pokemon.getBattlerIndex(), true, [ randStat ], stages.value));
}; };

View File

@ -1,8 +1,8 @@
import * as Utils from "#app/utils"; import { BooleanHolder, NumberHolder, randSeedItem } from "#app/utils";
import i18next from "i18next"; import i18next from "i18next";
import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data"; import { defaultStarterSpecies, DexAttrProps, GameData } from "#app/system/game-data";
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 "#balance/starters";
import Pokemon, { PokemonMove } from "#app/field/pokemon"; import Pokemon, { PokemonMove } from "#app/field/pokemon";
import { BattleType, FixedBattleConfig } from "#app/battle"; import { BattleType, FixedBattleConfig } from "#app/battle";
import Trainer, { TrainerVariant } from "#app/field/trainer"; import Trainer, { TrainerVariant } from "#app/field/trainer";
@ -14,7 +14,7 @@ import { TrainerType } from "#enums/trainer-type";
import { Nature } from "#app/data/nature"; import { Nature } from "#app/data/nature";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { TypeColor, TypeShadow } from "#enums/color"; import { TypeColor, TypeShadow } from "#enums/color";
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonEvolutions } from "#balance/pokemon-evolutions";
import { pokemonFormChanges } from "#app/data/pokemon-forms"; import { pokemonFormChanges } from "#app/data/pokemon-forms";
/** A constant for the default max cost of the starting party before a run */ /** A constant for the default max cost of the starting party before a run */
@ -271,31 +271,31 @@ export abstract class Challenge {
/** /**
* An apply function for STARTER_CHOICE challenges. Derived classes should alter this. * An apply function for STARTER_CHOICE challenges. Derived classes should alter this.
* @param pokemon {@link PokemonSpecies} The pokemon to check the validity of. * @param pokemon {@link PokemonSpecies} The pokemon to check the validity of.
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed. * @param valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
* @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon. * @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon.
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon. * @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
return false; return false;
} }
/** /**
* An apply function for STARTER_POINTS challenges. Derived classes should alter this. * An apply function for STARTER_POINTS challenges. Derived classes should alter this.
* @param points {@link Utils.NumberHolder} The amount of points you have available. * @param points {@link NumberHolder} The amount of points you have available.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyStarterPoints(points: Utils.NumberHolder): boolean { applyStarterPoints(points: NumberHolder): boolean {
return false; return false;
} }
/** /**
* An apply function for STARTER_COST challenges. Derived classes should alter this. * An apply function for STARTER_COST challenges. Derived classes should alter this.
* @param species {@link Species} The pokemon to change the cost of. * @param species {@link Species} The pokemon to change the cost of.
* @param cost {@link Utils.NumberHolder} The cost of the starter. * @param cost {@link NumberHolder} The cost of the starter.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyStarterCost(species: Species, cost: Utils.NumberHolder): boolean { applyStarterCost(species: Species, cost: NumberHolder): boolean {
return false; return false;
} }
@ -311,10 +311,10 @@ export abstract class Challenge {
/** /**
* An apply function for POKEMON_IN_BATTLE challenges. Derived classes should alter this. * An apply function for POKEMON_IN_BATTLE challenges. Derived classes should alter this.
* @param pokemon {@link Pokemon} The pokemon to check the validity of. * @param pokemon {@link Pokemon} The pokemon to check the validity of.
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed. * @param valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyPokemonInBattle(pokemon: Pokemon, valid: Utils.BooleanHolder): boolean { applyPokemonInBattle(pokemon: Pokemon, valid: BooleanHolder): boolean {
return false; return false;
} }
@ -330,42 +330,42 @@ export abstract class Challenge {
/** /**
* An apply function for TYPE_EFFECTIVENESS challenges. Derived classes should alter this. * An apply function for TYPE_EFFECTIVENESS challenges. Derived classes should alter this.
* @param effectiveness {@linkcode Utils.NumberHolder} The current effectiveness of the move. * @param effectiveness {@linkcode NumberHolder} The current effectiveness of the move.
* @returns Whether this function did anything. * @returns Whether this function did anything.
*/ */
applyTypeEffectiveness(effectiveness: Utils.NumberHolder): boolean { applyTypeEffectiveness(effectiveness: NumberHolder): boolean {
return false; return false;
} }
/** /**
* An apply function for AI_LEVEL challenges. Derived classes should alter this. * An apply function for AI_LEVEL challenges. Derived classes should alter this.
* @param level {@link Utils.IntegerHolder} The generated level. * @param level {@link NumberHolder} The generated level.
* @param levelCap {@link Number} The current level cap. * @param levelCap {@link Number} The current level cap.
* @param isTrainer {@link Boolean} Whether this is a trainer pokemon. * @param isTrainer {@link Boolean} Whether this is a trainer pokemon.
* @param isBoss {@link Boolean} Whether this is a non-trainer boss pokemon. * @param isBoss {@link Boolean} Whether this is a non-trainer boss pokemon.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyLevelChange(level: Utils.IntegerHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean { applyLevelChange(level: NumberHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean {
return false; return false;
} }
/** /**
* An apply function for AI_MOVE_SLOTS challenges. Derived classes should alter this. * An apply function for AI_MOVE_SLOTS challenges. Derived classes should alter this.
* @param pokemon {@link Pokemon} The pokemon that is being considered. * @param pokemon {@link Pokemon} The pokemon that is being considered.
* @param moveSlots {@link Utils.IntegerHolder} The amount of move slots. * @param moveSlots {@link NumberHolder} The amount of move slots.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyMoveSlot(pokemon: Pokemon, moveSlots: Utils.IntegerHolder): boolean { applyMoveSlot(pokemon: Pokemon, moveSlots: NumberHolder): boolean {
return false; return false;
} }
/** /**
* An apply function for PASSIVE_ACCESS challenges. Derived classes should alter this. * An apply function for PASSIVE_ACCESS challenges. Derived classes should alter this.
* @param pokemon {@link Pokemon} The pokemon to change. * @param pokemon {@link Pokemon} The pokemon to change.
* @param hasPassive {@link Utils.BooleanHolder} Whether it should have its passive. * @param hasPassive {@link BooleanHolder} Whether it should have its passive.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyPassiveAccess(pokemon: Pokemon, hasPassive: Utils.BooleanHolder): boolean { applyPassiveAccess(pokemon: Pokemon, hasPassive: BooleanHolder): boolean {
return false; return false;
} }
@ -383,10 +383,10 @@ export abstract class Challenge {
* @param pokemon {@link Pokemon} What pokemon would learn the move. * @param pokemon {@link Pokemon} What pokemon would learn the move.
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from. * @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
* @param move {@link Moves} The move in question. * @param move {@link Moves} The move in question.
* @param level {@link Utils.IntegerHolder} The level threshold for access. * @param level {@link NumberHolder} The level threshold for access.
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyMoveAccessLevel(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean { applyMoveAccessLevel(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: NumberHolder): boolean {
return false; return false;
} }
@ -395,10 +395,10 @@ export abstract class Challenge {
* @param pokemon {@link Pokemon} What pokemon would learn the move. * @param pokemon {@link Pokemon} What pokemon would learn the move.
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from. * @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
* @param move {@link Moves} The move in question. * @param move {@link Moves} The move in question.
* @param weight {@link Utils.IntegerHolder} The base weight of the move * @param weight {@link NumberHolder} The base weight of the move
* @returns {@link boolean} Whether this function did anything. * @returns {@link boolean} Whether this function did anything.
*/ */
applyMoveWeight(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean { applyMoveWeight(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: NumberHolder): boolean {
return false; return false;
} }
} }
@ -413,7 +413,7 @@ export class SingleGenerationChallenge extends Challenge {
super(Challenges.SINGLE_GENERATION, 9); super(Challenges.SINGLE_GENERATION, 9);
} }
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
const generations = [ pokemon.generation ]; const generations = [ pokemon.generation ];
if (soft) { if (soft) {
const speciesToCheck = [ pokemon.speciesId ]; const speciesToCheck = [ pokemon.speciesId ];
@ -435,7 +435,7 @@ export class SingleGenerationChallenge extends Challenge {
return false; return false;
} }
applyPokemonInBattle(pokemon: Pokemon, valid: Utils.BooleanHolder): boolean { applyPokemonInBattle(pokemon: Pokemon, valid: BooleanHolder): boolean {
const baseGeneration = pokemon.species.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.species.speciesId).generation; const baseGeneration = pokemon.species.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.species.speciesId).generation;
const fusionGeneration = pokemon.isFusion() ? pokemon.fusionSpecies?.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.fusionSpecies!.speciesId).generation : 0; // TODO: is the bang on fusionSpecies correct? const fusionGeneration = pokemon.isFusion() ? pokemon.fusionSpecies?.speciesId === Species.VICTINI ? 5 : getPokemonSpecies(pokemon.fusionSpecies!.speciesId).generation : 0; // TODO: is the bang on fusionSpecies correct?
if (pokemon.isPlayer() && (baseGeneration !== this.value || (pokemon.isFusion() && fusionGeneration !== this.value))) { if (pokemon.isPlayer() && (baseGeneration !== this.value || (pokemon.isFusion() && fusionGeneration !== this.value))) {
@ -449,19 +449,19 @@ export class SingleGenerationChallenge extends Challenge {
let trainerTypes: TrainerType[] = []; let trainerTypes: TrainerType[] = [];
switch (waveIndex) { switch (waveIndex) {
case 182: case 182:
trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, Utils.randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ]; trainerTypes = [ TrainerType.LORELEI, TrainerType.WILL, TrainerType.SIDNEY, TrainerType.AARON, TrainerType.SHAUNTAL, TrainerType.MALVA, randSeedItem([ TrainerType.HALA, TrainerType.MOLAYNE ]), TrainerType.MARNIE_ELITE, TrainerType.RIKA ];
break; break;
case 184: case 184:
trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ]; trainerTypes = [ TrainerType.BRUNO, TrainerType.KOGA, TrainerType.PHOEBE, TrainerType.BERTHA, TrainerType.MARSHAL, TrainerType.SIEBOLD, TrainerType.OLIVIA, TrainerType.NESSA_ELITE, TrainerType.POPPY ];
break; break;
case 186: case 186:
trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, Utils.randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ]; trainerTypes = [ TrainerType.AGATHA, TrainerType.BRUNO, TrainerType.GLACIA, TrainerType.FLINT, TrainerType.GRIMSLEY, TrainerType.WIKSTROM, TrainerType.ACEROLA, randSeedItem([ TrainerType.BEA_ELITE, TrainerType.ALLISTER_ELITE ]), TrainerType.LARRY_ELITE ];
break; break;
case 188: case 188:
trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ]; trainerTypes = [ TrainerType.LANCE, TrainerType.KAREN, TrainerType.DRAKE, TrainerType.LUCIAN, TrainerType.CAITLIN, TrainerType.DRASNA, TrainerType.KAHILI, TrainerType.RAIHAN_ELITE, TrainerType.HASSEL ];
break; break;
case 190: case 190:
trainerTypes = [ TrainerType.BLUE, Utils.randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), Utils.randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, Utils.randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, Utils.randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ]; trainerTypes = [ TrainerType.BLUE, randSeedItem([ TrainerType.RED, TrainerType.LANCE_CHAMPION ]), randSeedItem([ TrainerType.STEVEN, TrainerType.WALLACE ]), TrainerType.CYNTHIA, randSeedItem([ TrainerType.ALDER, TrainerType.IRIS ]), TrainerType.DIANTHA, TrainerType.HAU, TrainerType.LEON, randSeedItem([ TrainerType.GEETA, TrainerType.NEMONA ]) ];
break; break;
} }
if (trainerTypes.length === 0) { if (trainerTypes.length === 0) {
@ -537,7 +537,7 @@ export class SingleTypeChallenge extends Challenge {
super(Challenges.SINGLE_TYPE, 18); super(Challenges.SINGLE_TYPE, 18);
} }
override applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean { override applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder, dexAttr: DexAttrProps, soft: boolean = false): boolean {
const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex); const speciesForm = getPokemonSpeciesForm(pokemon.speciesId, dexAttr.formIndex);
const types = [ speciesForm.type1, speciesForm.type2 ]; const types = [ speciesForm.type1, speciesForm.type2 ];
if (soft && !SingleTypeChallenge.SPECIES_OVERRIDES.includes(pokemon.speciesId)) { if (soft && !SingleTypeChallenge.SPECIES_OVERRIDES.includes(pokemon.speciesId)) {
@ -568,7 +568,7 @@ export class SingleTypeChallenge extends Challenge {
return false; return false;
} }
applyPokemonInBattle(pokemon: Pokemon, valid: Utils.BooleanHolder): boolean { applyPokemonInBattle(pokemon: Pokemon, valid: BooleanHolder): boolean {
if (pokemon.isPlayer() && !pokemon.isOfType(this.value - 1, false, false, true) if (pokemon.isPlayer() && !pokemon.isOfType(this.value - 1, false, false, true)
&& !SingleTypeChallenge.TYPE_OVERRIDES.some(o => o.type === (this.value - 1) && (pokemon.isFusion() && o.fusion ? pokemon.fusionSpecies! : pokemon.species).speciesId === o.species)) { // TODO: is the bang on fusionSpecies correct? && !SingleTypeChallenge.TYPE_OVERRIDES.some(o => o.type === (this.value - 1) && (pokemon.isFusion() && o.fusion ? pokemon.fusionSpecies! : pokemon.species).speciesId === o.species)) { // TODO: is the bang on fusionSpecies correct?
valid.value = false; valid.value = false;
@ -628,7 +628,7 @@ export class FreshStartChallenge extends Challenge {
super(Challenges.FRESH_START, 1); super(Challenges.FRESH_START, 1);
} }
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder): boolean { applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder): boolean {
if (!defaultStarterSpecies.includes(pokemon.speciesId)) { if (!defaultStarterSpecies.includes(pokemon.speciesId)) {
valid.value = false; valid.value = false;
return true; return true;
@ -636,7 +636,7 @@ export class FreshStartChallenge extends Challenge {
return false; return false;
} }
applyStarterCost(species: Species, cost: Utils.NumberHolder): boolean { applyStarterCost(species: Species, cost: NumberHolder): boolean {
if (defaultStarterSpecies.includes(species)) { if (defaultStarterSpecies.includes(species)) {
cost.value = speciesStarterCosts[species]; cost.value = speciesStarterCosts[species];
return true; return true;
@ -688,7 +688,7 @@ export class InverseBattleChallenge extends Challenge {
return 0; return 0;
} }
applyTypeEffectiveness(effectiveness: Utils.NumberHolder): boolean { applyTypeEffectiveness(effectiveness: NumberHolder): boolean {
if (effectiveness.value < 1) { if (effectiveness.value < 1) {
effectiveness.value = 2; effectiveness.value = 2;
return true; return true;
@ -719,7 +719,7 @@ export class LowerStarterMaxCostChallenge extends Challenge {
return (DEFAULT_PARTY_MAX_COST - overrideValue).toString(); return (DEFAULT_PARTY_MAX_COST - overrideValue).toString();
} }
applyStarterChoice(pokemon: PokemonSpecies, valid: Utils.BooleanHolder): boolean { applyStarterChoice(pokemon: PokemonSpecies, valid: BooleanHolder): boolean {
if (speciesStarterCosts[pokemon.speciesId] > DEFAULT_PARTY_MAX_COST - this.value) { if (speciesStarterCosts[pokemon.speciesId] > DEFAULT_PARTY_MAX_COST - this.value) {
valid.value = false; valid.value = false;
return true; return true;
@ -753,7 +753,7 @@ export class LowerStarterPointsChallenge extends Challenge {
return (DEFAULT_PARTY_MAX_COST - overrideValue).toString(); return (DEFAULT_PARTY_MAX_COST - overrideValue).toString();
} }
applyStarterPoints(points: Utils.NumberHolder): boolean { applyStarterPoints(points: NumberHolder): boolean {
points.value -= this.value; points.value -= this.value;
return true; return true;
} }
@ -771,29 +771,29 @@ export class LowerStarterPointsChallenge extends Challenge {
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_CHOICE * @param challengeType {@link ChallengeType} ChallengeType.STARTER_CHOICE
* @param pokemon {@link PokemonSpecies} The pokemon to check the validity of. * @param pokemon {@link PokemonSpecies} The pokemon to check the validity of.
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed. * @param valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
* @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon. * @param dexAttr {@link DexAttrProps} The dex attributes of the pokemon.
* @param soft {@link boolean} If true, allow it if it could become a valid pokemon. * @param soft {@link boolean} If true, allow it if it could become a valid pokemon.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: Utils.BooleanHolder, dexAttr: DexAttrProps, soft: boolean): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_CHOICE, pokemon: PokemonSpecies, valid: BooleanHolder, dexAttr: DexAttrProps, soft: boolean): boolean;
/** /**
* Apply all challenges that modify available total starter points. * Apply all challenges that modify available total starter points.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_POINTS * @param challengeType {@link ChallengeType} ChallengeType.STARTER_POINTS
* @param points {@link Utils.NumberHolder} The amount of points you have available. * @param points {@link NumberHolder} The amount of points you have available.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_POINTS, points: Utils.NumberHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_POINTS, points: NumberHolder): boolean;
/** /**
* Apply all challenges that modify the cost of a starter. * Apply all challenges that modify the cost of a starter.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
* @param challengeType {@link ChallengeType} ChallengeType.STARTER_COST * @param challengeType {@link ChallengeType} ChallengeType.STARTER_COST
* @param species {@link Species} The pokemon to change the cost of. * @param species {@link Species} The pokemon to change the cost of.
* @param points {@link Utils.NumberHolder} The cost of the pokemon. * @param points {@link NumberHolder} The cost of the pokemon.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_COST, species: Species, cost: Utils.NumberHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.STARTER_COST, species: Species, cost: NumberHolder): boolean;
/** /**
* Apply all challenges that modify a starter after selection. * Apply all challenges that modify a starter after selection.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
@ -807,10 +807,10 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
* @param challengeType {@link ChallengeType} ChallengeType.POKEMON_IN_BATTLE * @param challengeType {@link ChallengeType} ChallengeType.POKEMON_IN_BATTLE
* @param pokemon {@link Pokemon} The pokemon to check the validity of. * @param pokemon {@link Pokemon} The pokemon to check the validity of.
* @param valid {@link Utils.BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed. * @param valid {@link BooleanHolder} A BooleanHolder, the value gets set to false if the pokemon isn't allowed.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.POKEMON_IN_BATTLE, pokemon: Pokemon, valid: Utils.BooleanHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.POKEMON_IN_BATTLE, pokemon: Pokemon, valid: BooleanHolder): boolean;
/** /**
* Apply all challenges that modify what fixed battles there are. * Apply all challenges that modify what fixed battles there are.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
@ -824,39 +824,39 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
* Apply all challenges that modify type effectiveness. * Apply all challenges that modify type effectiveness.
* @param gameMode {@linkcode GameMode} The current gameMode * @param gameMode {@linkcode GameMode} The current gameMode
* @param challengeType {@linkcode ChallengeType} ChallengeType.TYPE_EFFECTIVENESS * @param challengeType {@linkcode ChallengeType} ChallengeType.TYPE_EFFECTIVENESS
* @param effectiveness {@linkcode Utils.NumberHolder} The current effectiveness of the move. * @param effectiveness {@linkcode NumberHolder} The current effectiveness of the move.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.TYPE_EFFECTIVENESS, effectiveness: Utils.NumberHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.TYPE_EFFECTIVENESS, effectiveness: NumberHolder): boolean;
/** /**
* Apply all challenges that modify what level AI are. * Apply all challenges that modify what level AI are.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
* @param challengeType {@link ChallengeType} ChallengeType.AI_LEVEL * @param challengeType {@link ChallengeType} ChallengeType.AI_LEVEL
* @param level {@link Utils.IntegerHolder} The generated level of the pokemon. * @param level {@link NumberHolder} The generated level of the pokemon.
* @param levelCap {@link Number} The maximum level cap for the current wave. * @param levelCap {@link Number} The maximum level cap for the current wave.
* @param isTrainer {@link Boolean} Whether this is a trainer pokemon. * @param isTrainer {@link Boolean} Whether this is a trainer pokemon.
* @param isBoss {@link Boolean} Whether this is a non-trainer boss pokemon. * @param isBoss {@link Boolean} Whether this is a non-trainer boss pokemon.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_LEVEL, level: Utils.IntegerHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_LEVEL, level: NumberHolder, levelCap: number, isTrainer: boolean, isBoss: boolean): boolean;
/** /**
* Apply all challenges that modify how many move slots the AI has. * Apply all challenges that modify how many move slots the AI has.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
* @param challengeType {@link ChallengeType} ChallengeType.AI_MOVE_SLOTS * @param challengeType {@link ChallengeType} ChallengeType.AI_MOVE_SLOTS
* @param pokemon {@link Pokemon} The pokemon being considered. * @param pokemon {@link Pokemon} The pokemon being considered.
* @param moveSlots {@link Utils.IntegerHolder} The amount of move slots. * @param moveSlots {@link NumberHolder} The amount of move slots.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_MOVE_SLOTS, pokemon: Pokemon, moveSlots: Utils.IntegerHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.AI_MOVE_SLOTS, pokemon: Pokemon, moveSlots: NumberHolder): boolean;
/** /**
* Apply all challenges that modify whether a pokemon has its passive. * Apply all challenges that modify whether a pokemon has its passive.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
* @param challengeType {@link ChallengeType} ChallengeType.PASSIVE_ACCESS * @param challengeType {@link ChallengeType} ChallengeType.PASSIVE_ACCESS
* @param pokemon {@link Pokemon} The pokemon to modify. * @param pokemon {@link Pokemon} The pokemon to modify.
* @param hasPassive {@link Utils.BooleanHolder} Whether it has its passive. * @param hasPassive {@link BooleanHolder} Whether it has its passive.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.PASSIVE_ACCESS, pokemon: Pokemon, hasPassive: Utils.BooleanHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.PASSIVE_ACCESS, pokemon: Pokemon, hasPassive: BooleanHolder): boolean;
/** /**
* Apply all challenges that modify the game modes settings. * Apply all challenges that modify the game modes settings.
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
@ -871,10 +871,10 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
* @param pokemon {@link Pokemon} What pokemon would learn the move. * @param pokemon {@link Pokemon} What pokemon would learn the move.
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from. * @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
* @param move {@link Moves} The move in question. * @param move {@link Moves} The move in question.
* @param level {@link Utils.IntegerHolder} The level threshold for access. * @param level {@link NumberHolder} The level threshold for access.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_ACCESS, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_ACCESS, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: NumberHolder): boolean;
/** /**
* Apply all challenges that modify what weight a pokemon gives to move generation * Apply all challenges that modify what weight a pokemon gives to move generation
* @param gameMode {@link GameMode} The current gameMode * @param gameMode {@link GameMode} The current gameMode
@ -882,10 +882,10 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
* @param pokemon {@link Pokemon} What pokemon would learn the move. * @param pokemon {@link Pokemon} What pokemon would learn the move.
* @param moveSource {@link MoveSourceType} What source the pokemon would get the move from. * @param moveSource {@link MoveSourceType} What source the pokemon would get the move from.
* @param move {@link Moves} The move in question. * @param move {@link Moves} The move in question.
* @param weight {@link Utils.IntegerHolder} The weight of the move. * @param weight {@link NumberHolder} The weight of the move.
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_WEIGHT, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, weight: Utils.IntegerHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_WEIGHT, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, weight: NumberHolder): boolean;
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean { export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean {
let ret = false; let ret = false;
gameMode.challenges.forEach(c => { gameMode.challenges.forEach(c => {

View File

@ -3,9 +3,9 @@ import { Species } from "#enums/species";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { PlayerPokemon } from "#app/field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import { Starter } from "#app/ui/starter-select-ui-handler"; import { Starter } from "#app/ui/starter-select-ui-handler";
import * as Utils from "#app/utils"; import { apiFetch, randSeedGauss, randSeedInt, randSeedItem } from "#app/utils";
import PokemonSpecies, { PokemonSpeciesForm, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; import PokemonSpecies, { PokemonSpeciesForm, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#balance/starters";
export interface DailyRunConfig { export interface DailyRunConfig {
seed: integer; seed: integer;
@ -14,7 +14,7 @@ export interface DailyRunConfig {
export function fetchDailyRunSeed(): Promise<string | null> { export function fetchDailyRunSeed(): Promise<string | null> {
return new Promise<string | null>((resolve, reject) => { return new Promise<string | null>((resolve, reject) => {
Utils.apiFetch("daily/seed").then(response => { apiFetch("daily/seed").then(response => {
if (!response.ok) { if (!response.ok) {
resolve(null); resolve(null);
return; return;
@ -41,8 +41,8 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
} }
const starterCosts: integer[] = []; const starterCosts: integer[] = [];
starterCosts.push(Math.min(Math.round(3.5 + Math.abs(Utils.randSeedGauss(1))), 8)); starterCosts.push(Math.min(Math.round(3.5 + Math.abs(randSeedGauss(1))), 8));
starterCosts.push(Utils.randSeedInt(9 - starterCosts[0], 1)); starterCosts.push(randSeedInt(9 - starterCosts[0], 1));
starterCosts.push(10 - (starterCosts[0] + starterCosts[1])); starterCosts.push(10 - (starterCosts[0] + starterCosts[1]));
for (let c = 0; c < starterCosts.length; c++) { for (let c = 0; c < starterCosts.length; c++) {
@ -50,7 +50,7 @@ export function getDailyRunStarters(scene: BattleScene, seed: string): Starter[]
const costSpecies = Object.keys(speciesStarterCosts) const costSpecies = Object.keys(speciesStarterCosts)
.map(s => parseInt(s) as Species) .map(s => parseInt(s) as Species)
.filter(s => speciesStarterCosts[s] === cost); .filter(s => speciesStarterCosts[s] === cost);
const randPkmSpecies = getPokemonSpecies(Utils.randSeedItem(costSpecies)); const randPkmSpecies = getPokemonSpecies(randSeedItem(costSpecies));
const starterSpecies = getPokemonSpecies(randPkmSpecies.getTrainerSpeciesForLevel(startingLevel, true, PartyMemberStrength.STRONGER)); const starterSpecies = getPokemonSpecies(randPkmSpecies.getTrainerSpeciesForLevel(startingLevel, true, PartyMemberStrength.STRONGER));
starters.push(getDailyRunStarter(scene, starterSpecies, startingLevel)); starters.push(getDailyRunStarter(scene, starterSpecies, startingLevel));
} }

View File

@ -1,17 +1,41 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species"; import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import { VariantTier } from "#enums/variant-tier"; import { VariantTier } from "#enums/variant-tier";
import * as Utils from "#app/utils"; import { randInt, randomString, randSeedInt, getIvsFromId } from "#app/utils";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonPrevolutions } from "#balance/pokemon-evolutions";
import { PlayerPokemon } from "#app/field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
import { EggTier } from "#enums/egg-type"; import { EggTier } from "#enums/egg-type";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { EggSourceType } from "#enums/egg-source-types"; import { EggSourceType } from "#enums/egg-source-types";
import { MANAPHY_EGG_MANAPHY_RATE, SAME_SPECIES_EGG_HA_RATE, GACHA_EGG_HA_RATE, GACHA_DEFAULT_RARE_EGGMOVE_RATE, SAME_SPECIES_EGG_RARE_EGGMOVE_RATE, GACHA_MOVE_UP_RARE_EGGMOVE_RATE, GACHA_DEFAULT_SHINY_RATE, GACHA_SHINY_UP_SHINY_RATE, SAME_SPECIES_EGG_SHINY_RATE, EGG_PITY_LEGENDARY_THRESHOLD, EGG_PITY_EPIC_THRESHOLD, EGG_PITY_RARE_THRESHOLD, SHINY_VARIANT_CHANCE, SHINY_EPIC_CHANCE, GACHA_DEFAULT_COMMON_EGG_THRESHOLD, GACHA_DEFAULT_RARE_EGG_THRESHOLD, GACHA_DEFAULT_EPIC_EGG_THRESHOLD, GACHA_LEGENDARY_UP_THRESHOLD_OFFSET, HATCH_WAVES_MANAPHY_EGG, HATCH_WAVES_COMMON_EGG, HATCH_WAVES_RARE_EGG, HATCH_WAVES_EPIC_EGG, HATCH_WAVES_LEGENDARY_EGG } from "#app/data/balance/rates"; import {
import { speciesEggTiers } from "#app/data/balance/species-egg-tiers"; MANAPHY_EGG_MANAPHY_RATE,
SAME_SPECIES_EGG_HA_RATE,
GACHA_EGG_HA_RATE,
GACHA_DEFAULT_RARE_EGGMOVE_RATE,
SAME_SPECIES_EGG_RARE_EGGMOVE_RATE,
GACHA_MOVE_UP_RARE_EGGMOVE_RATE,
GACHA_DEFAULT_SHINY_RATE,
GACHA_SHINY_UP_SHINY_RATE,
SAME_SPECIES_EGG_SHINY_RATE,
EGG_PITY_LEGENDARY_THRESHOLD,
EGG_PITY_EPIC_THRESHOLD,
EGG_PITY_RARE_THRESHOLD,
SHINY_VARIANT_CHANCE,
SHINY_EPIC_CHANCE,
GACHA_DEFAULT_COMMON_EGG_THRESHOLD,
GACHA_DEFAULT_RARE_EGG_THRESHOLD,
GACHA_DEFAULT_EPIC_EGG_THRESHOLD,
GACHA_LEGENDARY_UP_THRESHOLD_OFFSET,
HATCH_WAVES_MANAPHY_EGG,
HATCH_WAVES_COMMON_EGG,
HATCH_WAVES_RARE_EGG,
HATCH_WAVES_EPIC_EGG,
HATCH_WAVES_LEGENDARY_EGG,
} from "#balance/rates";
import { speciesEggTiers } from "#balance/species-egg-tiers";
export const EGG_SEED = 1073741824; export const EGG_SEED = 1073741824;
@ -146,7 +170,7 @@ export class Egg {
this.checkForPityTierOverrides(eggOptions.scene!); // TODO: is this bang correct? this.checkForPityTierOverrides(eggOptions.scene!); // TODO: is this bang correct?
} }
this._id = eggOptions?.id ?? Utils.randInt(EGG_SEED, EGG_SEED * this._tier); this._id = eggOptions?.id ?? randInt(EGG_SEED, EGG_SEED * this._tier);
this._sourceType = eggOptions?.sourceType ?? undefined; this._sourceType = eggOptions?.sourceType ?? undefined;
this._hatchWaves = eggOptions?.hatchWaves ?? this.getEggTierDefaultHatchWaves(); this._hatchWaves = eggOptions?.hatchWaves ?? this.getEggTierDefaultHatchWaves();
@ -179,7 +203,7 @@ export class Egg {
}; };
if (eggOptions?.scene) { if (eggOptions?.scene) {
const seedOverride = Utils.randomString(24); const seedOverride = randomString(24);
eggOptions?.scene.executeWithSeedOffset(() => { eggOptions?.scene.executeWithSeedOffset(() => {
generateEggProperties(eggOptions); generateEggProperties(eggOptions);
}, 0, seedOverride); }, 0, seedOverride);
@ -220,14 +244,14 @@ export class Egg {
let pokemonSpecies = getPokemonSpecies(this._species); let pokemonSpecies = getPokemonSpecies(this._species);
// Special condition to have Phione eggs also have a chance of generating Manaphy // Special condition to have Phione eggs also have a chance of generating Manaphy
if (this._species === Species.PHIONE && this._sourceType === EggSourceType.SAME_SPECIES_EGG) { if (this._species === Species.PHIONE && this._sourceType === EggSourceType.SAME_SPECIES_EGG) {
pokemonSpecies = getPokemonSpecies(Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY); pokemonSpecies = getPokemonSpecies(randSeedInt(MANAPHY_EGG_MANAPHY_RATE) ? Species.PHIONE : Species.MANAPHY);
} }
// Sets the hidden ability if a hidden ability exists and // Sets the hidden ability if a hidden ability exists and
// the override is set or the egg hits the chance // the override is set or the egg hits the chance
let abilityIndex: number | undefined = undefined; let abilityIndex: number | undefined = undefined;
const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !Utils.randSeedInt(SAME_SPECIES_EGG_HA_RATE)); const sameSpeciesEggHACheck = (this._sourceType === EggSourceType.SAME_SPECIES_EGG && !randSeedInt(SAME_SPECIES_EGG_HA_RATE));
const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !Utils.randSeedInt(GACHA_EGG_HA_RATE)); const gachaEggHACheck = (!(this._sourceType === EggSourceType.SAME_SPECIES_EGG) && !randSeedInt(GACHA_EGG_HA_RATE));
if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility || sameSpeciesEggHACheck || gachaEggHACheck)) { if (pokemonSpecies.abilityHidden && (this._overrideHiddenAbility || sameSpeciesEggHACheck || gachaEggHACheck)) {
abilityIndex = 2; abilityIndex = 2;
} }
@ -237,7 +261,7 @@ export class Egg {
ret.shiny = this._isShiny; ret.shiny = this._isShiny;
ret.variant = this._variantTier; ret.variant = this._variantTier;
const secondaryIvs = Utils.getIvsFromId(Utils.randSeedInt(4294967295)); const secondaryIvs = getIvsFromId(randSeedInt(4294967295));
for (let s = 0; s < ret.ivs.length; s++) { for (let s = 0; s < ret.ivs.length; s++) {
ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]); ret.ivs[s] = Math.max(ret.ivs[s], secondaryIvs[s]);
@ -326,7 +350,7 @@ export class Egg {
} }
const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier); const tierMultiplier = this.isManaphyEgg() ? 2 : Math.pow(2, 3 - this.tier);
return Utils.randSeedInt(baseChance * tierMultiplier) ? Utils.randSeedInt(3) : 3; return randSeedInt(baseChance * tierMultiplier) ? randSeedInt(3) : 3;
} }
private getEggTierDefaultHatchWaves(eggTier?: EggTier): number { private getEggTierDefaultHatchWaves(eggTier?: EggTier): number {
@ -347,7 +371,7 @@ export class Egg {
private rollEggTier(): EggTier { private rollEggTier(): EggTier {
const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0; const tierValueOffset = this._sourceType === EggSourceType.GACHA_LEGENDARY ? GACHA_LEGENDARY_UP_THRESHOLD_OFFSET : 0;
const tierValue = Utils.randInt(256); const tierValue = randInt(256);
return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.RARE : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.EPIC : EggTier.LEGENDARY; return tierValue >= GACHA_DEFAULT_COMMON_EGG_THRESHOLD + tierValueOffset ? EggTier.COMMON : tierValue >= GACHA_DEFAULT_RARE_EGG_THRESHOLD + tierValueOffset ? EggTier.RARE : tierValue >= GACHA_DEFAULT_EPIC_EGG_THRESHOLD + tierValueOffset ? EggTier.EPIC : EggTier.LEGENDARY;
} }
@ -366,11 +390,11 @@ export class Egg {
* when Utils.randSeedInt(8) = 1, and by making the generatePlayerPokemon() species * when Utils.randSeedInt(8) = 1, and by making the generatePlayerPokemon() species
* check pass when Utils.randSeedInt(8) = 0, we can tell them apart during tests. * check pass when Utils.randSeedInt(8) = 0, we can tell them apart during tests.
*/ */
const rand = (Utils.randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1); const rand = (randSeedInt(MANAPHY_EGG_MANAPHY_RATE) !== 1);
return rand ? Species.PHIONE : Species.MANAPHY; return rand ? Species.PHIONE : Species.MANAPHY;
} else if (this.tier === EggTier.LEGENDARY } else if (this.tier === EggTier.LEGENDARY
&& this._sourceType === EggSourceType.GACHA_LEGENDARY) { && this._sourceType === EggSourceType.GACHA_LEGENDARY) {
if (!Utils.randSeedInt(2)) { if (!randSeedInt(2)) {
return getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp); return getLegendaryGachaSpeciesForTimestamp(scene, this.timestamp);
} }
} }
@ -444,7 +468,7 @@ export class Egg {
let species: Species; let species: Species;
const rand = Utils.randSeedInt(totalWeight); const rand = randSeedInt(totalWeight);
for (let s = 0; s < speciesWeights.length; s++) { for (let s = 0; s < speciesWeights.length; s++) {
if (rand < speciesWeights[s]) { if (rand < speciesWeights[s]) {
species = speciesPool[s]; species = speciesPool[s];
@ -479,7 +503,7 @@ export class Egg {
break; break;
} }
return !Utils.randSeedInt(shinyChance); return !randSeedInt(shinyChance);
} }
// Uses the same logic as pokemon.generateVariant(). I would like to only have this logic in one // Uses the same logic as pokemon.generateVariant(). I would like to only have this logic in one
@ -489,7 +513,7 @@ export class Egg {
return VariantTier.STANDARD; return VariantTier.STANDARD;
} }
const rand = Utils.randSeedInt(10); const rand = randSeedInt(10);
if (rand >= SHINY_VARIANT_CHANCE) { if (rand >= SHINY_VARIANT_CHANCE) {
return VariantTier.STANDARD; // 6/10 return VariantTier.STANDARD; // 6/10
} else if (rand >= SHINY_EPIC_CHANCE) { } else if (rand >= SHINY_EPIC_CHANCE) {

File diff suppressed because it is too large Load Diff

View File

@ -1,18 +1,18 @@
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#mystery-encounters/utils/encounter-phase-utils";
import { trainerConfigs, } from "#app/data/trainer-config"; import { trainerConfigs, } from "#app/data/trainer-config";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; 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 "#mystery-encounters/utils/encounter-pokemon-utils";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils";
import i18next from "i18next"; import i18next from "i18next";
import { IEggOptions } from "#app/data/egg"; import { IEggOptions } from "#app/data/egg";
import { EggSourceType } from "#enums/egg-source-types"; import { EggSourceType } from "#enums/egg-source-types";
import { EggTier } from "#enums/egg-type"; import { EggTier } from "#enums/egg-type";
import { PartyHealPhase } from "#app/phases/party-heal-phase"; import { PartyHealPhase } from "#phases/party-heal-phase";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -1,13 +1,13 @@
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
import { BerryModifierType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { BerryModifierType, modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { PersistentModifierRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { PersistentModifierRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { BerryModifier, PokemonInstantReviveModifier } from "#app/modifier/modifier"; import { BerryModifier, PokemonInstantReviveModifier } from "#app/modifier/modifier";
@ -16,12 +16,12 @@ 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";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { applyModifierTypeToPlayerPokemon, catchPokemon, getHighestLevelPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyModifierTypeToPlayerPokemon, catchPokemon, getHighestLevelPlayerPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import { PokeballType } from "#app/data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import HeldModifierConfig from "#app/interfaces/held-modifier-config";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -1,18 +1,18 @@
import { leaveEncounterWithoutBattle, setEncounterExp, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { leaveEncounterWithoutBattle, setEncounterExp, updatePlayerMoney, } from "#mystery-encounters/utils/encounter-phase-utils";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { AbilityRequirement, CombinationPokemonRequirement, MoveRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { getHighestStatTotalPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getHighestStatTotalPlayerPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import { EXTORTION_ABILITIES, EXTORTION_MOVES } from "#mystery-encounters/requirements/requirement-groups";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import { ModifierRewardPhase } from "#phases/modifier-reward-phase";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
/** the i18n namespace for this encounter */ /** the i18n namespace for this encounter */

View File

@ -1,10 +1,10 @@
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { import {
EnemyPartyConfig, generateModifierType, generateModifierTypeOption, EnemyPartyConfig, generateModifierType, generateModifierTypeOption,
initBattleWithEnemyConfig, initBattleWithEnemyConfig,
leaveEncounterWithoutBattle, setEncounterExp, leaveEncounterWithoutBattle, setEncounterExp,
setEncounterRewards setEncounterRewards
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
import { import {
BerryModifierType, BerryModifierType,
@ -17,19 +17,19 @@ import { randSeedInt } from "#app/utils";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import { applyModifierTypeToPlayerPokemon, getEncounterPokemonLevelForWave, getHighestStatPlayerPokemon, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyModifierTypeToPlayerPokemon, getEncounterPokemonLevelForWave, getHighestStatPlayerPokemon, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#mystery-encounters/utils/encounter-pokemon-utils";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { BerryModifier } from "#app/modifier/modifier"; import { BerryModifier } from "#app/modifier/modifier";
import i18next from "#app/plugins/i18n"; import i18next from "#app/plugins/i18n";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";
import { PERMANENT_STATS, Stat } from "#enums/stat"; import { PERMANENT_STATS, Stat } from "#enums/stat";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#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";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */

View File

@ -7,7 +7,7 @@ import {
selectPokemonForOption, selectPokemonForOption,
setEncounterRewards, setEncounterRewards,
transitionMysteryEncounterIntroVisuals, transitionMysteryEncounterIntroVisuals,
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#mystery-encounters/utils/encounter-phase-utils";
import { import {
getRandomPartyMemberFunc, getRandomPartyMemberFunc,
trainerConfigs, trainerConfigs,
@ -19,23 +19,23 @@ import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { PartyMemberStrength } from "#enums/party-member-strength"; import { PartyMemberStrength } from "#enums/party-member-strength";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils"; import { isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; 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 Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { getEncounterText, showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, showEncounterDialogue } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { LearnMovePhase } from "#phases/learn-move-phase";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { import {
AttackTypeBoosterHeldItemTypeRequirement, AttackTypeBoosterHeldItemTypeRequirement,
CombinationPokemonRequirement, CombinationPokemonRequirement,
HeldItemRequirement, HeldItemRequirement,
TypeRequirement TypeRequirement
} from "#app/data/mystery-encounters/mystery-encounter-requirements"; } from "#mystery-encounters/mystery-encounter-requirements";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import { AttackTypeBoosterModifierType, ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type"; import { AttackTypeBoosterModifierType, ModifierTypeOption, modifierTypes } from "#app/modifier/modifier-type";
import { import {
@ -51,7 +51,7 @@ import MoveInfoOverlay from "#app/ui/move-info-overlay";
import { allMoves } from "#app/data/move"; import { allMoves } from "#app/data/move";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getSpriteKeysFromSpecies } from "#mystery-encounters/utils/encounter-pokemon-utils";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
const namespace = "mysteryEncounters/bugTypeSuperfan"; const namespace = "mysteryEncounters/bugTypeSuperfan";

View File

@ -1,22 +1,22 @@
import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#mystery-encounters/utils/encounter-phase-utils";
import { trainerConfigs, TrainerPartyCompoundTemplate, TrainerPartyTemplate, } from "#app/data/trainer-config"; import { trainerConfigs, TrainerPartyCompoundTemplate, TrainerPartyTemplate, } from "#app/data/trainer-config";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } 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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyModifierTypeToPlayerPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#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";
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { showEncounterDialogue, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import i18next from "i18next"; import i18next from "i18next";
import { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler"; import { OptionSelectConfig } from "#app/ui/abstact-option-select-ui-handler";

View File

@ -1,10 +1,10 @@
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards } from "#mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
@ -14,16 +14,16 @@ import PokemonData from "#app/system/pokemon-data";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { EncounterBattleAnim } from "#app/data/battle-anims"; import { EncounterBattleAnim } from "#app/data/battle-anims";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, queueEncounterMessage } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoveRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { DANCING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import { DANCING_MOVES } from "#mystery-encounters/requirements/requirement-groups";
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { catchPokemon, getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { catchPokemon, getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { PokeballType } from "#enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { LearnMovePhase } from "#phases/learn-move-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { EncounterAnim } from "#enums/encounter-anims"; import { EncounterAnim } from "#enums/encounter-anims";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -5,13 +5,13 @@ import { Species } from "#enums/species";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, } from "../utils/encounter-phase-utils"; import { EnemyPartyConfig, EnemyPokemonConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, } from "../utils/encounter-phase-utils";
import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getRandomPlayerPokemon, getRandomSpeciesByStarterTier } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import { ModifierRewardPhase } from "#phases/modifier-reward-phase";
import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; import { PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -1,20 +1,20 @@
import { generateModifierType, leaveEncounterWithoutBattle, selectPokemonForOption, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { generateModifierType, leaveEncounterWithoutBattle, selectPokemonForOption, updatePlayerMoney, } from "#mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { CombinationPokemonRequirement, HeldItemRequirement, MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { CombinationPokemonRequirement, HeldItemRequirement, MoneyRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { BerryModifier, HealingBoosterModifier, LevelIncrementBoosterModifier, MoneyMultiplierModifier, PokemonHeldItemModifier, PreserveBerryModifier } from "#app/modifier/modifier"; import { BerryModifier, HealingBoosterModifier, LevelIncrementBoosterModifier, MoneyMultiplierModifier, PokemonHeldItemModifier, PreserveBerryModifier } from "#app/modifier/modifier";
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyModifierTypeToPlayerPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import i18next from "#app/plugins/i18n"; import i18next from "#app/plugins/i18n";
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase"; import { ModifierRewardPhase } from "#phases/modifier-reward-phase";
import { getPokemonSpecies } from "#app/data/pokemon-species"; 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";

View File

@ -1,7 +1,7 @@
import { import {
leaveEncounterWithoutBattle, leaveEncounterWithoutBattle,
setEncounterRewards, setEncounterRewards,
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#mystery-encounters/utils/encounter-phase-utils";
import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type"; import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
@ -9,7 +9,7 @@ import { Species } from "#enums/species";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { import MysteryEncounter, {
MysteryEncounterBuilder, MysteryEncounterBuilder,
} from "#app/data/mystery-encounters/mystery-encounter"; } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -1,12 +1,12 @@
import { MoveCategory } from "#app/data/move"; import { MoveCategory } from "#app/data/move";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { generateModifierTypeOption, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { generateModifierTypeOption, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards } from "#mystery-encounters/utils/encounter-phase-utils";
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";

View File

@ -1,10 +1,10 @@
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { EnemyPartyConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, generateModifierType } from "#mystery-encounters/utils/encounter-phase-utils";
import { AttackTypeBoosterModifierType, modifierTypes, } from "#app/modifier/modifier-type"; import { AttackTypeBoosterModifierType, modifierTypes, } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { TypeRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { TypeRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { Gender } from "#app/data/gender"; import { Gender } from "#app/data/gender";
@ -16,8 +16,8 @@ import { EncounterBattleAnim } from "#app/data/battle-anims";
import { WeatherType } from "#app/data/weather"; import { WeatherType } from "#app/data/weather";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils";
import { StatusEffect } from "#app/data/status-effect"; import { StatusEffect } from "#app/data/status-effect";
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { applyDamageToPokemon, applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyDamageToPokemon, applyModifierTypeToPlayerPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { EncounterAnim } from "#enums/encounter-anims"; import { EncounterAnim } from "#enums/encounter-anims";

View File

@ -1,11 +1,11 @@
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { import {
EnemyPartyConfig, EnemyPartyConfig,
initBattleWithEnemyConfig, initBattleWithEnemyConfig,
leaveEncounterWithoutBattle, setEncounterExp, leaveEncounterWithoutBattle, setEncounterExp,
setEncounterRewards setEncounterRewards
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#mystery-encounters/utils/encounter-phase-utils";
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import { STEALING_MOVES } from "#mystery-encounters/requirements/requirement-groups";
import Pokemon, { EnemyPokemon } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon } from "#app/field/pokemon";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { import {
@ -17,17 +17,17 @@ import {
} from "#app/modifier/modifier-type"; } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoveRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import { getEncounterPokemonLevelForWave, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getEncounterPokemonLevelForWave, getSpriteKeysFromPokemon, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#mystery-encounters/utils/encounter-pokemon-utils";
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 "#mystery-encounters/utils/encounter-dialogue-utils";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#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";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */

View File

@ -1,13 +1,13 @@
import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#mystery-encounters/utils/encounter-phase-utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { FieldPosition, PlayerPokemon } from "#app/field/pokemon";
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 "#mystery-encounters/mystery-encounter-requirements";
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
@ -16,13 +16,13 @@ import { getPokemonNameWithAffix } from "#app/messages";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball"; import { getPokeballAtlasKey, getPokeballTintColor } from "#app/data/pokeball";
import { addPokeballOpenParticles } from "#app/field/anims"; import { addPokeballOpenParticles } from "#app/field/anims";
import { ShinySparklePhase } from "#app/phases/shiny-sparkle-phase"; import { ShinySparklePhase } from "#phases/shiny-sparkle-phase";
import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms";
import { PostSummonPhase } from "#app/phases/post-summon-phase"; import { PostSummonPhase } from "#phases/post-summon-phase";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { isPokemonValidForEncounterOptionSelection } from "#mystery-encounters/utils/encounter-pokemon-utils";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
const namespace = "mysteryEncounters/funAndGames"; const namespace = "mysteryEncounters/funAndGames";

View File

@ -1,30 +1,44 @@
import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import {
leaveEncounterWithoutBattle,
selectPokemonForOption,
setEncounterRewards,
} from "#mystery-encounters/utils/encounter-phase-utils";
import { TrainerSlot, } from "#app/data/trainer-config"; import { TrainerSlot, } from "#app/data/trainer-config";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { getPlayerModifierTypeOptions, ModifierPoolType, ModifierTypeOption, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; import {
getPlayerModifierTypeOptions,
ModifierPoolType,
ModifierTypeOption,
regenerateModifierPoolThresholds,
} from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species"; import PokemonSpecies, { 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 "#mystery-encounters/mystery-encounter-option";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import * as Utils from "#app/utils"; import { isNullOrUndefined, NumberHolder, randInt, randSeedInt, randSeedShuffle } from "#app/utils";
import { IntegerHolder, isNullOrUndefined, randInt, randSeedInt, randSeedShuffle } from "#app/utils";
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier, ShinyRateBoosterModifier, SpeciesStatBoosterModifier } from "#app/modifier/modifier"; import {
HiddenAbilityRateBoosterModifier,
PokemonFormChangeItemModifier,
PokemonHeldItemModifier,
ShinyRateBoosterModifier,
SpeciesStatBoosterModifier,
} from "#app/modifier/modifier";
import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import i18next from "i18next"; import i18next from "i18next";
import { Gender, getGenderSymbol } from "#app/data/gender"; import { Gender, getGenderSymbol } from "#app/data/gender";
import { getNatureName } from "#app/data/nature"; import { getNatureName } from "#app/data/nature";
import { getPokeballAtlasKey, getPokeballTintColor, PokeballType } from "#app/data/pokeball"; import { getPokeballAtlasKey, getPokeballTintColor, PokeballType } from "#app/data/pokeball";
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { trainerNamePools } from "#app/data/trainer-names"; import { trainerNamePools } from "#app/data/trainer-names";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { addPokemonDataToDexAndValidateAchievements } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { addPokemonDataToDexAndValidateAchievements } from "#mystery-encounters/utils/encounter-pokemon-utils";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
const namespace = "mysteryEncounters/globalTradeSystem"; const namespace = "mysteryEncounters/globalTradeSystem";
@ -228,7 +242,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
const tradePokemon = new EnemyPokemon(scene, randomTradeOption, pokemon.level, TrainerSlot.NONE, false); const tradePokemon = new EnemyPokemon(scene, randomTradeOption, pokemon.level, TrainerSlot.NONE, false);
// Extra shiny roll at 1/128 odds (boosted by events and charms) // Extra shiny roll at 1/128 odds (boosted by events and charms)
if (!tradePokemon.shiny) { if (!tradePokemon.shiny) {
const shinyThreshold = new Utils.IntegerHolder(WONDER_TRADE_SHINY_CHANCE); const shinyThreshold = new NumberHolder(WONDER_TRADE_SHINY_CHANCE);
if (scene.eventManager.isEventActive()) { if (scene.eventManager.isEventActive()) {
shinyThreshold.value *= scene.eventManager.getShinyMultiplier(); shinyThreshold.value *= scene.eventManager.getShinyMultiplier();
} }
@ -245,7 +259,7 @@ export const GlobalTradeSystemEncounter: MysteryEncounter =
const hiddenIndex = tradePokemon.species.ability2 ? 2 : 1; const hiddenIndex = tradePokemon.species.ability2 ? 2 : 1;
if (tradePokemon.species.abilityHidden) { if (tradePokemon.species.abilityHidden) {
if (tradePokemon.abilityIndex < hiddenIndex) { if (tradePokemon.abilityIndex < hiddenIndex) {
const hiddenAbilityChance = new IntegerHolder(64); const hiddenAbilityChance = new NumberHolder(64);
scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value); const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value);

View File

@ -1,12 +1,12 @@
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { Moves } from "#app/enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#app/enums/species"; import { Species } from "#enums/species";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { leaveEncounterWithoutBattle, setEncounterExp } from "../utils/encounter-phase-utils"; import { leaveEncounterWithoutBattle, setEncounterExp } from "../utils/encounter-phase-utils";
import { applyDamageToPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyDamageToPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -2,7 +2,7 @@ import {
EnemyPartyConfig, EnemyPartyConfig,
initBattleWithEnemyConfig, initBattleWithEnemyConfig,
setEncounterRewards, setEncounterRewards,
} from "#app/data/mystery-encounters/utils/encounter-phase-utils"; } from "#mystery-encounters/utils/encounter-phase-utils";
import { import {
trainerConfigs, trainerConfigs,
TrainerPartyCompoundTemplate, TrainerPartyCompoundTemplate,
@ -14,8 +14,8 @@ 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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import * as Utils from "#app/utils"; import { randSeedInt } from "#app/utils";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
@ -46,7 +46,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
const normalConfig = trainerConfigs[normalTrainerType].clone(); const normalConfig = trainerConfigs[normalTrainerType].clone();
let female = false; let female = false;
if (normalConfig.hasGenders) { if (normalConfig.hasGenders) {
female = !!Utils.randSeedInt(2); female = !!randSeedInt(2);
} }
const normalSpriteKey = normalConfig.getSpriteKey(female, normalConfig.doubleOnly); const normalSpriteKey = normalConfig.getSpriteKey(female, normalConfig.doubleOnly);
encounter.enemyPartyConfigs.push({ encounter.enemyPartyConfigs.push({
@ -70,7 +70,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
hardConfig.setPartyTemplates(hardTemplate); hardConfig.setPartyTemplates(hardTemplate);
female = false; female = false;
if (hardConfig.hasGenders) { if (hardConfig.hasGenders) {
female = !!Utils.randSeedInt(2); female = !!randSeedInt(2);
} }
const hardSpriteKey = hardConfig.getSpriteKey(female, hardConfig.doubleOnly); const hardSpriteKey = hardConfig.getSpriteKey(female, hardConfig.doubleOnly);
encounter.enemyPartyConfigs.push({ encounter.enemyPartyConfigs.push({
@ -93,7 +93,7 @@ export const MysteriousChallengersEncounter: MysteryEncounter =
brutalConfig.partyTemplateFunc = null; // Overrides gym leader party template func brutalConfig.partyTemplateFunc = null; // Overrides gym leader party template func
female = false; female = false;
if (brutalConfig.hasGenders) { if (brutalConfig.hasGenders) {
female = !!Utils.randSeedInt(2); female = !!randSeedInt(2);
} }
const brutalSpriteKey = brutalConfig.getSpriteKey(female, brutalConfig.doubleOnly); const brutalSpriteKey = brutalConfig.getSpriteKey(female, brutalConfig.doubleOnly);
encounter.enemyPartyConfigs.push({ encounter.enemyPartyConfigs.push({

View File

@ -1,18 +1,18 @@
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals } from "#mystery-encounters/utils/encounter-phase-utils";
import { getHighestLevelPlayerPokemon, koPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getHighestLevelPlayerPokemon, koPlayerPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { GameOverPhase } from "#app/phases/game-over-phase"; import { GameOverPhase } from "#phases/game-over-phase";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
/** i18n namespace for encounter */ /** i18n namespace for encounter */

View File

@ -1,18 +1,18 @@
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney } from "#mystery-encounters/utils/encounter-phase-utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoveRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { CHARMING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import { CHARMING_MOVES } from "#mystery-encounters/requirements/requirement-groups";
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { showEncounterDialogue, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import i18next from "i18next"; import i18next from "i18next";
import Pokemon, { PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon } 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 { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { isPokemonValidForEncounterOptionSelection } from "#mystery-encounters/utils/encounter-pokemon-utils";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
const namespace = "mysteryEncounters/partTimer"; const namespace = "mysteryEncounters/partTimer";

View File

@ -1,23 +1,23 @@
import { initSubsequentOptionSelect, leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { initSubsequentOptionSelect, leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#mystery-encounters/utils/encounter-phase-utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import MysteryEncounterOption, { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import MysteryEncounterOption, { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifier/modifier"; import { HiddenAbilityRateBoosterModifier, IvScannerModifier } from "#app/modifier/modifier";
import { EnemyPokemon } from "#app/field/pokemon"; import { EnemyPokemon } from "#app/field/pokemon";
import { PokeballType } from "#app/data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { IntegerHolder, randSeedInt } from "#app/utils"; import { NumberHolder, randSeedInt } from "#app/utils";
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 "#mystery-encounters/mystery-encounter-requirements";
import { doPlayerFlee, doPokemonFlee, getRandomSpeciesByStarterTier, trainerThrowPokeball } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { doPlayerFlee, doPokemonFlee, getRandomSpeciesByStarterTier, trainerThrowPokeball } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { getEncounterText, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { ScanIvsPhase } from "#app/phases/scan-ivs-phase"; import { ScanIvsPhase } from "#phases/scan-ivs-phase";
import { SummonPhase } from "#app/phases/summon-phase"; import { SummonPhase } from "#phases/summon-phase";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */
@ -275,7 +275,7 @@ async function summonSafariPokemon(scene: BattleScene) {
if (pokemon.species.abilityHidden) { if (pokemon.species.abilityHidden) {
const hiddenIndex = pokemon.species.ability2 ? 2 : 1; const hiddenIndex = pokemon.species.ability2 ? 2 : 1;
if (pokemon.abilityIndex < hiddenIndex) { if (pokemon.abilityIndex < hiddenIndex) {
const hiddenAbilityChance = new IntegerHolder(256); const hiddenAbilityChance = new NumberHolder(256);
scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value); const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value);

View File

@ -1,15 +1,15 @@
import { generateModifierType, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { generateModifierType, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterExp, updatePlayerMoney, } from "#mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon } 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";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoneyRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { getEncounterText, queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, queueEncounterMessage } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { applyDamageToPokemon, applyModifierTypeToPlayerPokemon, isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyDamageToPokemon, applyModifierTypeToPlayerPokemon, isPokemonValidForEncounterOptionSelection } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";

View File

@ -1,21 +1,21 @@
import { STEALING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import { STEALING_MOVES } from "#mystery-encounters/requirements/requirement-groups";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { StatusEffect } from "#app/data/status-effect"; import { StatusEffect } from "#app/data/status-effect";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { MoveRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoveRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils"; import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, setEncounterExp, setEncounterRewards, } from "../utils/encounter-phase-utils";
import { queueEncounterMessage } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { AiType, PokemonMove } from "#app/field/pokemon"; import { AiType, PokemonMove } from "#app/field/pokemon";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { PartyHealPhase } from "#app/phases/party-heal-phase"; import { PartyHealPhase } from "#phases/party-heal-phase";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { BerryType } from "#enums/berry-type"; import { BerryType } from "#enums/berry-type";
import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { CustomPokemonData } from "#app/data/custom-pokemon-data";

View File

@ -1,12 +1,12 @@
import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, generateModifierTypeOption, initBattleWithEnemyConfig, setEncounterExp, setEncounterRewards, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#mystery-encounters/utils/encounter-phase-utils";
import { randSeedInt } from "#app/utils"; import { randSeedInt } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MoneyRequirement, WaveModulusRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoneyRequirement, WaveModulusRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import Pokemon, { EnemyPokemon } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon } from "#app/field/pokemon";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
@ -17,10 +17,10 @@ import { getPartyLuckValue, modifierTypes } from "#app/modifier/modifier-type";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getEncounterPokemonLevelForWave, STANDARD_ENCOUNTER_BOOSTED_LEVEL_MODIFIER } from "#mystery-encounters/utils/encounter-pokemon-utils";
/** the i18n namespace for this encounter */ /** the i18n namespace for this encounter */
const namespace = "mysteryEncounters/teleportingHijinks"; const namespace = "mysteryEncounters/teleportingHijinks";

View File

@ -1,4 +1,4 @@
import { EnemyPartyConfig, generateModifierType, handleMysteryEncounterBattleFailed, initBattleWithEnemyConfig, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, generateModifierType, handleMysteryEncounterBattleFailed, initBattleWithEnemyConfig, setEncounterRewards, } from "#mystery-encounters/utils/encounter-phase-utils";
import { trainerConfigs } from "#app/data/trainer-config"; import { trainerConfigs } from "#app/data/trainer-config";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
@ -11,15 +11,15 @@ import { TrainerType } from "#enums/trainer-type";
import i18next from "i18next"; import i18next from "i18next";
import { Species } from "#enums/species"; import { Species } from "#enums/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 "#balance/starters";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { PlayerPokemon } from "#app/field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { IEggOptions } from "#app/data/egg"; import { IEggOptions } from "#app/data/egg";
import { EggSourceType } from "#enums/egg-source-types"; import { EggSourceType } from "#enums/egg-source-types";
import { EggTier } from "#enums/egg-type"; import { EggTier } from "#enums/egg-type";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";

View File

@ -1,17 +1,17 @@
import { leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { leaveEncounterWithoutBattle, transitionMysteryEncounterIntroVisuals, updatePlayerMoney, } from "#mystery-encounters/utils/encounter-phase-utils";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MoneyRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoneyRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { catchPokemon, getRandomSpeciesByStarterTier, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { catchPokemon, getRandomSpeciesByStarterTier, getSpriteKeysFromPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { PokeballType } from "#app/data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon"; import { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { showEncounterDialogue } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { showEncounterDialogue } from "#mystery-encounters/utils/encounter-dialogue-utils";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";

View File

@ -1,14 +1,14 @@
import { EnemyPartyConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, generateModifierType } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, initBattleWithEnemyConfig, loadCustomMovesForEncounter, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, generateModifierType } from "#mystery-encounters/utils/encounter-phase-utils";
import { modifierTypes, PokemonHeldItemModifierType, } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType, } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { Nature } from "#app/data/nature"; import { Nature } from "#app/data/nature";
import Pokemon, { PokemonMove } from "#app/field/pokemon"; import Pokemon, { PokemonMove } from "#app/field/pokemon";
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { modifyPlayerPokemonBST } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { modifyPlayerPokemonBST } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
@ -16,7 +16,7 @@ import { BerryType } from "#enums/berry-type";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { CustomPokemonData } from "#app/data/custom-pokemon-data";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#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";
/** the i18n namespace for the encounter */ /** the i18n namespace for the encounter */

View File

@ -1,8 +1,8 @@
import { EnemyPartyConfig, generateModifierType, generateModifierTypeOption, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, generateModifierType, generateModifierTypeOption, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#mystery-encounters/utils/encounter-phase-utils";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; 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";
@ -15,11 +15,11 @@ import { BerryType } from "#enums/berry-type";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { SpeciesFormChangeManualTrigger } from "#app/data/pokemon-forms"; import { SpeciesFormChangeManualTrigger } from "#app/data/pokemon-forms";
import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/ability"; import { applyPostBattleInitAbAttrs, PostBattleInitAbAttr } from "#app/data/ability";
import { showEncounterDialogue, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { showEncounterDialogue, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { PartyHealPhase } from "#app/phases/party-heal-phase"; import { PartyHealPhase } from "#phases/party-heal-phase";
import { ShowTrainerPhase } from "#app/phases/show-trainer-phase"; import { ShowTrainerPhase } from "#phases/show-trainer-phase";
import { ReturnPhase } from "#app/phases/return-phase"; import { ReturnPhase } from "#phases/return-phase";
import i18next from "i18next"; import i18next from "i18next";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -1,7 +1,7 @@
import { Ability, allAbilities } from "#app/data/ability"; import { Ability, allAbilities } from "#app/data/ability";
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, selectPokemonForOption, setEncounterRewards, } from "#mystery-encounters/utils/encounter-phase-utils";
import { getNatureName, Nature } from "#app/data/nature"; import { getNatureName, Nature } from "#app/data/nature";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import Pokemon, { PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
import { PokemonHeldItemModifier } from "#app/modifier/modifier"; import { PokemonHeldItemModifier } from "#app/modifier/modifier";
import { AbilityAttr } from "#app/system/game-data"; import { AbilityAttr } from "#app/system/game-data";
@ -11,16 +11,16 @@ import { isNullOrUndefined, randSeedShuffle } from "#app/utils";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { queueEncounterMessage, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import HeldModifierConfig from "#app/interfaces/held-modifier-config";
import i18next from "i18next"; import i18next from "i18next";
import { getStatKey } from "#enums/stat"; import { getStatKey } from "#enums/stat";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
import { isPokemonValidForEncounterOptionSelection } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { isPokemonValidForEncounterOptionSelection } from "#mystery-encounters/utils/encounter-pokemon-utils";
/** The i18n namespace for the encounter */ /** The i18n namespace for the encounter */
const namespace = "mysteryEncounters/trainingSession"; const namespace = "mysteryEncounters/trainingSession";

View File

@ -1,15 +1,15 @@
import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, EnemyPokemonConfig, generateModifierType, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, loadCustomMovesForEncounter, setEncounterRewards, transitionMysteryEncounterIntroVisuals, } from "#mystery-encounters/utils/encounter-phase-utils";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { HitHealModifier, PokemonHeldItemModifier, TurnHealModifier } from "#app/modifier/modifier"; import { HitHealModifier, PokemonHeldItemModifier, TurnHealModifier } from "#app/modifier/modifier";
import { applyModifierTypeToPlayerPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { applyModifierTypeToPlayerPokemon } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import i18next from "#app/plugins/i18n"; import i18next from "#app/plugins/i18n";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { getPokemonSpecies } from "#app/data/pokemon-species"; import { getPokemonSpecies } from "#app/data/pokemon-species";

View File

@ -1,16 +1,16 @@
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig, initBattleWithEnemyConfig, leaveEncounterWithoutBattle, setEncounterExp, setEncounterRewards } from "#mystery-encounters/utils/encounter-phase-utils";
import { CHARMING_MOVES } from "#app/data/mystery-encounters/requirements/requirement-groups"; import { CHARMING_MOVES } from "#mystery-encounters/requirements/requirement-groups";
import Pokemon, { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
import { getPartyLuckValue } from "#app/modifier/modifier-type"; import { getPartyLuckValue } from "#app/modifier/modifier-type";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MoveRequirement, PersistentModifierRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { MoveRequirement, PersistentModifierRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import { catchPokemon, getHighestLevelPlayerPokemon, getSpriteKeysFromPokemon } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { catchPokemon, getHighestLevelPlayerPokemon, getSpriteKeysFromPokemon } from "#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";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
@ -18,9 +18,9 @@ import { BattlerIndex } from "#app/battle";
import { SelfStatusMove } from "#app/data/move"; import { SelfStatusMove } from "#app/data/move";
import { PokeballType } from "#enums/pokeball"; import { PokeballType } from "#enums/pokeball";
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 "#mystery-encounters/utils/encounter-dialogue-utils";
import { BerryModifier } from "#app/modifier/modifier"; import { BerryModifier } from "#app/modifier/modifier";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";

View File

@ -2,21 +2,21 @@ import { Type } from "#app/data/type";
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 BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounter, { MysteryEncounterBuilder } from "#app/data/mystery-encounters/mystery-encounter"; import MysteryEncounter, { MysteryEncounterBuilder } from "#mystery-encounters/mystery-encounter";
import { MysteryEncounterOptionBuilder } from "#app/data/mystery-encounters/mystery-encounter-option"; import { MysteryEncounterOptionBuilder } from "#mystery-encounters/mystery-encounter-option";
import { leaveEncounterWithoutBattle, setEncounterRewards, } from "../utils/encounter-phase-utils"; import { leaveEncounterWithoutBattle, setEncounterRewards, } from "../utils/encounter-phase-utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { IntegerHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils"; import { NumberHolder, isNullOrUndefined, randSeedInt, randSeedShuffle } from "#app/utils";
import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species"; import PokemonSpecies, { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier"; import { HiddenAbilityRateBoosterModifier, PokemonFormChangeItemModifier, PokemonHeldItemModifier } from "#app/modifier/modifier";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { CustomPokemonData } from "#app/data/custom-pokemon-data";
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import i18next from "#app/plugins/i18n"; import i18next from "#app/plugins/i18n";
import { doPokemonTransformationSequence, TransformationScreenPosition } from "#app/data/mystery-encounters/utils/encounter-transformation-sequence"; import { doPokemonTransformationSequence, TransformationScreenPosition } from "#mystery-encounters/utils/encounter-transformation-sequence";
import { getLevelTotalExp } from "#app/data/exp"; import { getLevelTotalExp } from "#app/data/exp";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode"; import { CLASSIC_MODE_MYSTERY_ENCOUNTER_WAVES } from "#app/game-mode";
@ -300,7 +300,7 @@ async function doNewTeamPostProcess(scene: BattleScene, transformations: Pokemon
if (newPokemon.species.abilityHidden) { if (newPokemon.species.abilityHidden) {
const hiddenIndex = newPokemon.species.ability2 ? 2 : 1; const hiddenIndex = newPokemon.species.ability2 ? 2 : 1;
if (newPokemon.abilityIndex < hiddenIndex) { if (newPokemon.abilityIndex < hiddenIndex) {
const hiddenAbilityChance = new IntegerHolder(256); const hiddenAbilityChance = new NumberHolder(256);
scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value); const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value);

View File

@ -1,9 +1,9 @@
import { OptionTextDisplay } from "#app/data/mystery-encounters/mystery-encounter-dialogue"; import { OptionTextDisplay } from "#mystery-encounters/mystery-encounter-dialogue";
import { Moves } from "#app/enums/moves"; import { Moves } from "#enums/moves";
import Pokemon, { PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon } from "#app/field/pokemon";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { Type } from "../type"; import { Type } from "../type";
import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { EncounterPokemonRequirement, EncounterSceneRequirement, MoneyRequirement, TypeRequirement } from "#mystery-encounters/mystery-encounter-requirements";
import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement"; import { CanLearnMoveRequirement, CanLearnMoveRequirementOptions } from "./requirements/can-learn-move-requirement";
import { isNullOrUndefined, randSeedInt } from "#app/utils"; import { isNullOrUndefined, randSeedInt } from "#app/utils";
import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode"; import { MysteryEncounterOptionMode } from "#enums/mystery-encounter-option-mode";

View File

@ -6,7 +6,7 @@ import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { TimeOfDay } from "#enums/time-of-day"; import { TimeOfDay } from "#enums/time-of-day";
import { Nature } from "#app/data/nature"; import { Nature } from "#app/data/nature";
import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { EvolutionItem, pokemonEvolutions } from "#balance/pokemon-evolutions";
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms"; import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms";
import { StatusEffect } from "#app/data/status-effect"; import { StatusEffect } from "#app/data/status-effect";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";

View File

@ -1,5 +1,5 @@
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { 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 "#mystery-encounters/mystery-encounters";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -1,10 +1,10 @@
import { EnemyPartyConfig } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { EnemyPartyConfig } from "#mystery-encounters/utils/encounter-phase-utils";
import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils"; import { capitalizeFirstLetter, isNullOrUndefined } from "#app/utils";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import MysteryEncounterIntroVisuals, { MysteryEncounterSpriteConfig } from "#app/field/mystery-encounter-intro"; import MysteryEncounterIntroVisuals, { MysteryEncounterSpriteConfig } from "#app/field/mystery-encounter-intro";
import * as Utils from "#app/utils"; import { randSeedInt } from "#app/utils";
import { StatusEffect } from "../status-effect"; import { StatusEffect } from "../status-effect";
import MysteryEncounterDialogue, { OptionTextDisplay } from "./mystery-encounter-dialogue"; import MysteryEncounterDialogue, { OptionTextDisplay } from "./mystery-encounter-dialogue";
import MysteryEncounterOption, { MysteryEncounterOptionBuilder, OptionPhaseCallback } from "./mystery-encounter-option"; import MysteryEncounterOption, { MysteryEncounterOptionBuilder, OptionPhaseCallback } from "./mystery-encounter-option";
@ -356,13 +356,13 @@ export default class MysteryEncounter implements IMysteryEncounter {
} }
if (truePrimaryPool.length > 0) { if (truePrimaryPool.length > 0) {
// Always choose from the non-overlapping pokemon first // Always choose from the non-overlapping pokemon first
this.primaryPokemon = truePrimaryPool[Utils.randSeedInt(truePrimaryPool.length, 0)]; this.primaryPokemon = truePrimaryPool[randSeedInt(truePrimaryPool.length, 0)];
return true; return true;
} else { } else {
// If there are multiple overlapping pokemon, we're okay - just choose one and take it out of the primary pokemon pool // If there are multiple overlapping pokemon, we're okay - just choose one and take it out of the primary pokemon pool
if (overlap.length > 1 || (this.secondaryPokemon.length - overlap.length >= 1)) { if (overlap.length > 1 || (this.secondaryPokemon.length - overlap.length >= 1)) {
// is this working? // is this working?
this.primaryPokemon = overlap[Utils.randSeedInt(overlap.length, 0)]; this.primaryPokemon = overlap[randSeedInt(overlap.length, 0)];
this.secondaryPokemon = this.secondaryPokemon.filter((supp) => supp !== this.primaryPokemon); this.secondaryPokemon = this.secondaryPokemon.filter((supp) => supp !== this.primaryPokemon);
return true; return true;
} }
@ -371,7 +371,7 @@ export default class MysteryEncounter implements IMysteryEncounter {
} }
} else { } else {
// this means we CAN have the same pokemon be a primary and secondary pokemon, so just choose any qualifying one randomly. // this means we CAN have the same pokemon be a primary and secondary pokemon, so just choose any qualifying one randomly.
this.primaryPokemon = qualified[Utils.randSeedInt(qualified.length, 0)]; this.primaryPokemon = qualified[randSeedInt(qualified.length, 0)];
return true; return true;
} }
} }

View File

@ -11,28 +11,28 @@ import { ShadyVitaminDealerEncounter } from "./encounters/shady-vitamin-dealer-e
import { SlumberingSnorlaxEncounter } from "./encounters/slumbering-snorlax-encounter"; import { SlumberingSnorlaxEncounter } from "./encounters/slumbering-snorlax-encounter";
import { TrainingSessionEncounter } from "./encounters/training-session-encounter"; import { TrainingSessionEncounter } from "./encounters/training-session-encounter";
import MysteryEncounter from "./mystery-encounter"; import MysteryEncounter from "./mystery-encounter";
import { SafariZoneEncounter } from "#app/data/mystery-encounters/encounters/safari-zone-encounter"; import { SafariZoneEncounter } from "#mystery-encounters/encounters/safari-zone-encounter";
import { FieryFalloutEncounter } from "#app/data/mystery-encounters/encounters/fiery-fallout-encounter"; import { FieryFalloutEncounter } from "#mystery-encounters/encounters/fiery-fallout-encounter";
import { TheStrongStuffEncounter } from "#app/data/mystery-encounters/encounters/the-strong-stuff-encounter"; import { TheStrongStuffEncounter } from "#mystery-encounters/encounters/the-strong-stuff-encounter";
import { ThePokemonSalesmanEncounter } from "#app/data/mystery-encounters/encounters/the-pokemon-salesman-encounter"; import { ThePokemonSalesmanEncounter } from "#mystery-encounters/encounters/the-pokemon-salesman-encounter";
import { AnOfferYouCantRefuseEncounter } from "#app/data/mystery-encounters/encounters/an-offer-you-cant-refuse-encounter"; import { AnOfferYouCantRefuseEncounter } from "#mystery-encounters/encounters/an-offer-you-cant-refuse-encounter";
import { DelibirdyEncounter } from "#app/data/mystery-encounters/encounters/delibirdy-encounter"; import { DelibirdyEncounter } from "#mystery-encounters/encounters/delibirdy-encounter";
import { AbsoluteAvariceEncounter } from "#app/data/mystery-encounters/encounters/absolute-avarice-encounter"; import { AbsoluteAvariceEncounter } from "#mystery-encounters/encounters/absolute-avarice-encounter";
import { ATrainersTestEncounter } from "#app/data/mystery-encounters/encounters/a-trainers-test-encounter"; import { ATrainersTestEncounter } from "#mystery-encounters/encounters/a-trainers-test-encounter";
import { TrashToTreasureEncounter } from "#app/data/mystery-encounters/encounters/trash-to-treasure-encounter"; import { TrashToTreasureEncounter } from "#mystery-encounters/encounters/trash-to-treasure-encounter";
import { BerriesAboundEncounter } from "#app/data/mystery-encounters/encounters/berries-abound-encounter"; import { BerriesAboundEncounter } from "#mystery-encounters/encounters/berries-abound-encounter";
import { ClowningAroundEncounter } from "#app/data/mystery-encounters/encounters/clowning-around-encounter"; import { ClowningAroundEncounter } from "#mystery-encounters/encounters/clowning-around-encounter";
import { PartTimerEncounter } from "#app/data/mystery-encounters/encounters/part-timer-encounter"; import { PartTimerEncounter } from "#mystery-encounters/encounters/part-timer-encounter";
import { DancingLessonsEncounter } from "#app/data/mystery-encounters/encounters/dancing-lessons-encounter"; import { DancingLessonsEncounter } from "#mystery-encounters/encounters/dancing-lessons-encounter";
import { WeirdDreamEncounter } from "#app/data/mystery-encounters/encounters/weird-dream-encounter"; import { WeirdDreamEncounter } from "#mystery-encounters/encounters/weird-dream-encounter";
import { TheWinstrateChallengeEncounter } from "#app/data/mystery-encounters/encounters/the-winstrate-challenge-encounter"; import { TheWinstrateChallengeEncounter } from "#mystery-encounters/encounters/the-winstrate-challenge-encounter";
import { TeleportingHijinksEncounter } from "#app/data/mystery-encounters/encounters/teleporting-hijinks-encounter"; import { TeleportingHijinksEncounter } from "#mystery-encounters/encounters/teleporting-hijinks-encounter";
import { BugTypeSuperfanEncounter } from "#app/data/mystery-encounters/encounters/bug-type-superfan-encounter"; import { BugTypeSuperfanEncounter } from "#mystery-encounters/encounters/bug-type-superfan-encounter";
import { FunAndGamesEncounter } from "#app/data/mystery-encounters/encounters/fun-and-games-encounter"; import { FunAndGamesEncounter } from "#mystery-encounters/encounters/fun-and-games-encounter";
import { UncommonBreedEncounter } from "#app/data/mystery-encounters/encounters/uncommon-breed-encounter"; import { UncommonBreedEncounter } from "#mystery-encounters/encounters/uncommon-breed-encounter";
import { GlobalTradeSystemEncounter } from "#app/data/mystery-encounters/encounters/global-trade-system-encounter"; import { GlobalTradeSystemEncounter } from "#mystery-encounters/encounters/global-trade-system-encounter";
import { TheExpertPokemonBreederEncounter } from "#app/data/mystery-encounters/encounters/the-expert-pokemon-breeder-encounter"; import { TheExpertPokemonBreederEncounter } from "#mystery-encounters/encounters/the-expert-pokemon-breeder-encounter";
import { getBiomeName } from "#app/data/balance/biomes"; import { getBiomeName } from "#balance/biomes";
/** /**
* Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT * Spawn chance: (BASE_MYSTERY_ENCOUNTER_SPAWN_WEIGHT + WIGHT_INCREMENT_ON_SPAWN_MISS * <number of missed spawns>) / MYSTERY_ENCOUNTER_SPAWN_MAX_WEIGHT

View File

@ -1,8 +1,8 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { Moves } from "#app/enums/moves"; import { Moves } from "#enums/moves";
import { PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import { PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils";
import { EncounterPokemonRequirement } from "#app/data/mystery-encounters/mystery-encounter-requirements"; import { EncounterPokemonRequirement } from "#mystery-encounters/mystery-encounter-requirements";
/** /**
* {@linkcode CanLearnMoveRequirement} options * {@linkcode CanLearnMoveRequirement} options

View File

@ -1,17 +1,32 @@
import Battle, { BattlerIndex, BattleType } from "#app/battle"; import Battle, { BattlerIndex, BattleType } from "#app/battle";
import { biomeLinks, BiomePoolTier } from "#app/data/balance/biomes"; import { biomeLinks, BiomePoolTier } from "#balance/biomes";
import MysteryEncounterOption from "#app/data/mystery-encounters/mystery-encounter-option"; import MysteryEncounterOption from "#mystery-encounters/mystery-encounter-option";
import { AVERAGE_ENCOUNTERS_PER_RUN_TARGET, WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters"; import {
import { showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; AVERAGE_ENCOUNTERS_PER_RUN_TARGET,
WEIGHT_INCREMENT_ON_SPAWN_MISS,
} from "#mystery-encounters/mystery-encounters";
import { showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import Pokemon, { AiType, FieldPosition, PlayerPokemon, PokemonMove, PokemonSummonData } from "#app/field/pokemon"; import Pokemon, { AiType, FieldPosition, PlayerPokemon, PokemonMove, PokemonSummonData } from "#app/field/pokemon";
import { CustomModifierSettings, ModifierPoolType, ModifierType, ModifierTypeGenerator, ModifierTypeOption, modifierTypes, regenerateModifierPoolThresholds } from "#app/modifier/modifier-type"; import {
import { MysteryEncounterBattlePhase, MysteryEncounterBattleStartCleanupPhase, MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phases"; CustomModifierSettings,
ModifierPoolType,
ModifierType,
ModifierTypeGenerator,
ModifierTypeOption,
modifierTypes,
regenerateModifierPoolThresholds,
} from "#app/modifier/modifier-type";
import {
MysteryEncounterBattlePhase,
MysteryEncounterBattleStartCleanupPhase,
MysteryEncounterPhase,
MysteryEncounterRewardsPhase,
} from "#phases/mystery-encounter-phases";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler"; import { OptionSelectConfig, OptionSelectItem } from "#app/ui/abstact-option-select-ui-handler";
import { PartyOption, PartyUiMode, PokemonSelectFilter } from "#app/ui/party-ui-handler"; import { PartyOption, PartyUiMode, PokemonSelectFilter } from "#app/ui/party-ui-handler";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import * as Utils from "#app/utils"; import { isNullOrUndefined, randSeedInt, randomString } from "#app/utils";
import { isNullOrUndefined } from "#app/utils";
import { BattlerTagType } from "#enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
@ -29,13 +44,13 @@ import PokemonSpecies from "#app/data/pokemon-species";
import { Egg, IEggOptions } from "#app/data/egg"; import { Egg, IEggOptions } from "#app/data/egg";
import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { CustomPokemonData } from "#app/data/custom-pokemon-data";
import HeldModifierConfig from "#app/interfaces/held-modifier-config"; import HeldModifierConfig from "#app/interfaces/held-modifier-config";
import { MovePhase } from "#app/phases/move-phase"; import { MovePhase } from "#phases/move-phase";
import { EggLapsePhase } from "#app/phases/egg-lapse-phase"; import { EggLapsePhase } from "#phases/egg-lapse-phase";
import { TrainerVictoryPhase } from "#app/phases/trainer-victory-phase"; import { TrainerVictoryPhase } from "#phases/trainer-victory-phase";
import { BattleEndPhase } from "#app/phases/battle-end-phase"; import { BattleEndPhase } from "#phases/battle-end-phase";
import { GameOverPhase } from "#app/phases/game-over-phase"; import { GameOverPhase } from "#phases/game-over-phase";
import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import { SelectModifierPhase } from "#phases/select-modifier-phase";
import { PartyExpPhase } from "#app/phases/party-exp-phase"; import { PartyExpPhase } from "#phases/party-exp-phase";
import { Variant } from "#app/data/variant"; import { Variant } from "#app/data/variant";
/** /**
@ -139,7 +154,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
const doubleTrainer = trainerConfig.doubleOnly || (trainerConfig.hasDouble && !!partyConfig.doubleBattle); const doubleTrainer = trainerConfig.doubleOnly || (trainerConfig.hasDouble && !!partyConfig.doubleBattle);
doubleBattle = doubleTrainer; doubleBattle = doubleTrainer;
const trainerFemale = isNullOrUndefined(partyConfig.female) ? !!(Utils.randSeedInt(2)) : partyConfig.female; const trainerFemale = isNullOrUndefined(partyConfig.female) ? !!(randSeedInt(2)) : partyConfig.female;
const newTrainer = new Trainer(scene, trainerConfig.trainerType, doubleTrainer ? TrainerVariant.DOUBLE : trainerFemale ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT, undefined, undefined, undefined, trainerConfig); const newTrainer = new Trainer(scene, trainerConfig.trainerType, doubleTrainer ? TrainerVariant.DOUBLE : trainerFemale ? TrainerVariant.FEMALE : TrainerVariant.DEFAULT, undefined, undefined, undefined, trainerConfig);
newTrainer.x += 300; newTrainer.x += 300;
newTrainer.setVisible(false); newTrainer.setVisible(false);
@ -231,7 +246,7 @@ export async function initBattleWithEnemyConfig(scene: BattleScene, partyConfig:
// Generate new id, reset status and HP in case using data source // Generate new id, reset status and HP in case using data source
if (config.dataSource) { if (config.dataSource) {
enemyPokemon.id = Utils.randSeedInt(4294967296); enemyPokemon.id = randSeedInt(4294967296);
} }
// Set form // Set form
@ -898,7 +913,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
const validMEfloorsByBiome = new Map<string, number>(biomes.map(b => [ b, 0 ])); const validMEfloorsByBiome = new Map<string, number>(biomes.map(b => [ b, 0 ]));
let currentBiome = Biome.TOWN; let currentBiome = Biome.TOWN;
let currentArena = scene.newArena(currentBiome); let currentArena = scene.newArena(currentBiome);
scene.setSeed(Utils.randomString(24)); scene.setSeed(randomString(24));
scene.resetSeed(); scene.resetSeed();
for (let i = 10; i < 180; i++) { for (let i = 10; i < 180; i++) {
// Boss // Boss
@ -913,16 +928,16 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
scene.executeWithSeedOffset(() => { scene.executeWithSeedOffset(() => {
biomes = (biomeLinks[currentBiome] as (Biome | [Biome, number])[]) biomes = (biomeLinks[currentBiome] as (Biome | [Biome, number])[])
.filter(b => { .filter(b => {
return !Array.isArray(b) || !Utils.randSeedInt(b[1]); return !Array.isArray(b) || !randSeedInt(b[1]);
}) })
.map(b => !Array.isArray(b) ? b : b[0]); .map(b => !Array.isArray(b) ? b : b[0]);
}, i * 100); }, i * 100);
if (biomes! && biomes.length > 0) { if (biomes! && biomes.length > 0) {
const specialBiomes = biomes.filter(b => alwaysPickTheseBiomes.includes(b)); const specialBiomes = biomes.filter(b => alwaysPickTheseBiomes.includes(b));
if (specialBiomes.length > 0) { if (specialBiomes.length > 0) {
currentBiome = specialBiomes[Utils.randSeedInt(specialBiomes.length)]; currentBiome = specialBiomes[randSeedInt(specialBiomes.length)];
} else { } else {
currentBiome = biomes[Utils.randSeedInt(biomes.length)]; currentBiome = biomes[randSeedInt(biomes.length)];
} }
} }
} else if (biomeLinks.hasOwnProperty(currentBiome)) { } else if (biomeLinks.hasOwnProperty(currentBiome)) {
@ -950,7 +965,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
// Otherwise, roll encounter // Otherwise, roll encounter
const roll = Utils.randSeedInt(256); const roll = randSeedInt(256);
validMEfloorsByBiome.set(Biome[currentBiome], (validMEfloorsByBiome.get(Biome[currentBiome]) ?? 0) + 1); validMEfloorsByBiome.set(Biome[currentBiome], (validMEfloorsByBiome.get(Biome[currentBiome]) ?? 0) + 1);
// If total number of encounters is lower than expected for the run, slightly favor a new encounter // If total number of encounters is lower than expected for the run, slightly favor a new encounter
@ -975,7 +990,7 @@ export function calculateMEAggregateStats(scene: BattleScene, baseSpawnWeight: n
tierWeights[1] = tierWeights[1] - 4 * numEncounters[1]; tierWeights[1] = tierWeights[1] - 4 * numEncounters[1];
const totalWeight = tierWeights.reduce((a, b) => a + b); const totalWeight = tierWeights.reduce((a, b) => a + b);
const tierValue = Utils.randSeedInt(totalWeight); const tierValue = randSeedInt(totalWeight);
const commonThreshold = totalWeight - tierWeights[0]; // 64 - 32 = 32 const commonThreshold = totalWeight - tierWeights[0]; // 64 - 32 = 32
const uncommonThreshold = totalWeight - tierWeights[0] - tierWeights[1]; // 64 - 32 - 16 = 16 const uncommonThreshold = totalWeight - tierWeights[0] - tierWeights[1]; // 64 - 32 - 16 = 16
const rareThreshold = totalWeight - tierWeights[0] - tierWeights[1] - tierWeights[2]; // 64 - 32 - 16 - 10 = 6 const rareThreshold = totalWeight - tierWeights[0] - tierWeights[1] - tierWeights[2]; // 64 - 32 - 16 - 10 = 6
@ -1055,7 +1070,7 @@ export function calculateRareSpawnAggregateStats(scene: BattleScene, luckValue:
const calculateNumRareEncounters = (): any[] => { const calculateNumRareEncounters = (): any[] => {
const bossEncountersByRarity = [ 0, 0, 0, 0 ]; const bossEncountersByRarity = [ 0, 0, 0, 0 ];
scene.setSeed(Utils.randomString(24)); scene.setSeed(randomString(24));
scene.resetSeed(); scene.resetSeed();
// There are 12 wild boss floors // There are 12 wild boss floors
for (let i = 0; i < 12; i++) { for (let i = 0; i < 12; i++) {
@ -1065,7 +1080,7 @@ export function calculateRareSpawnAggregateStats(scene: BattleScene, luckValue:
if (!isNaN(luckValue)) { if (!isNaN(luckValue)) {
luckModifier = luckValue * 0.5; luckModifier = luckValue * 0.5;
} }
const tierValue = Utils.randSeedInt(64 - luckModifier); const tierValue = randSeedInt(64 - luckModifier);
const tier = tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE; const tier = tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE;
switch (tier) { switch (tier) {

View File

@ -13,13 +13,13 @@ import { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species"; import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import { getEncounterText, queueEncounterMessage, showEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText, queueEncounterMessage, showEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type"; import { modifierTypes, PokemonHeldItemModifierType } from "#app/modifier/modifier-type";
import { Gender } from "#app/data/gender"; import { Gender } from "#app/data/gender";
import { PermanentStat } from "#enums/stat"; import { PermanentStat } from "#enums/stat";
import { VictoryPhase } from "#app/phases/victory-phase"; import { VictoryPhase } from "#phases/victory-phase";
import { SummaryUiMode } from "#app/ui/summary-ui-handler"; import { SummaryUiMode } from "#app/ui/summary-ui-handler";
/** Will give +1 level every 10 waves */ /** Will give +1 level every 10 waves */

View File

@ -1,14 +1,14 @@
import * as Utils from "../utils"; import { toReadableString } from "#app/utils";
import { TextStyle, getBBCodeFrag } from "../ui/text"; import { TextStyle, getBBCodeFrag } from "#app/ui/text";
import { Nature } from "#enums/nature"; import { Nature } from "#enums/nature";
import { UiTheme } from "#enums/ui-theme"; import { UiTheme } from "#enums/ui-theme";
import i18next from "i18next"; import i18next from "i18next";
import { Stat, EFFECTIVE_STATS, getShortenedStatKey } from "#app/enums/stat"; import { Stat, EFFECTIVE_STATS, getShortenedStatKey } from "#enums/stat";
export { Nature }; export { Nature };
export function getNatureName(nature: Nature, includeStatEffects: boolean = false, forStarterSelect: boolean = false, ignoreBBCode: boolean = false, uiTheme: UiTheme = UiTheme.DEFAULT): string { export function getNatureName(nature: Nature, includeStatEffects: boolean = false, forStarterSelect: boolean = false, ignoreBBCode: boolean = false, uiTheme: UiTheme = UiTheme.DEFAULT): string {
let ret = Utils.toReadableString(Nature[nature]); let ret = toReadableString(Nature[nature]);
//Translating nature //Translating nature
if (i18next.exists("nature:" + ret)) { if (i18next.exists("nature:" + ret)) {
ret = i18next.t("nature:" + ret as any); ret = i18next.t("nature:" + ret as any);

View File

@ -11,7 +11,7 @@ import { TimeOfDay } from "#enums/time-of-day";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import i18next from "i18next"; import i18next from "i18next";
import { WeatherType } from "./weather"; import { WeatherType } from "./weather";
import { Challenges } from "#app/enums/challenges"; import { Challenges } from "#enums/challenges";
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
export enum FormChangeItem { export enum FormChangeItem {

View File

@ -7,16 +7,16 @@ import i18next from "i18next";
import BattleScene, { AnySound } from "#app/battle-scene"; import BattleScene, { AnySound } from "#app/battle-scene";
import { GameMode } from "#app/game-mode"; import { GameMode } from "#app/game-mode";
import { StarterMoveset } from "#app/system/game-data"; import { StarterMoveset } from "#app/system/game-data";
import * as Utils from "#app/utils"; import { randSeedInt, randSeedGauss, randSeedItem } from "#app/utils";
import { uncatchableSpecies } from "#app/data/balance/biomes"; import { uncatchableSpecies } from "#balance/biomes";
import { speciesEggMoves } from "#app/data/balance/egg-moves"; import { speciesEggMoves } from "#balance/egg-moves";
import { GrowthRate } from "#app/data/exp"; import { GrowthRate } from "#app/data/exp";
import { EvolutionLevel, SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { EvolutionLevel, SpeciesWildEvolutionDelay, pokemonEvolutions, pokemonPrevolutions } from "#balance/pokemon-evolutions";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import { LevelMoves, pokemonFormLevelMoves, pokemonFormLevelMoves as pokemonSpeciesFormLevelMoves, pokemonSpeciesLevelMoves } from "#app/data/balance/pokemon-level-moves"; import { LevelMoves, pokemonFormLevelMoves, pokemonFormLevelMoves as pokemonSpeciesFormLevelMoves, pokemonSpeciesLevelMoves } from "#balance/pokemon-level-moves";
import { Stat } from "#enums/stat"; import { Stat } from "#enums/stat";
import { Variant, VariantSet, variantColorCache, variantData } from "#app/data/variant"; import { Variant, VariantSet, variantColorCache, variantData } from "#app/data/variant";
import { speciesStarterCosts, POKERUS_STARTER_COUNT } from "#app/data/balance/starters"; import { speciesStarterCosts, POKERUS_STARTER_COUNT } from "#balance/starters";
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
export enum Region { export enum Region {
@ -793,7 +793,7 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
return this.speciesId; return this.speciesId;
} }
const randValue = evolutionPool.size === 1 ? 0 : Utils.randSeedInt(totalWeight); const randValue = evolutionPool.size === 1 ? 0 : randSeedInt(totalWeight);
for (const weight of evolutionPool.keys()) { for (const weight of evolutionPool.keys()) {
if (randValue < weight) { if (randValue < weight) {
@ -855,11 +855,11 @@ export default class PokemonSpecies extends PokemonSpeciesForm implements Locali
ret.push([ prevolutionLevels[0][0], 1 ]); ret.push([ prevolutionLevels[0][0], 1 ]);
for (let l = 1; l < prevolutionLevels.length; l++) { for (let l = 1; l < prevolutionLevels.length; l++) {
const evolution = pokemonEvolutions[prevolutionLevels[l - 1][0]].find(e => e.speciesId === prevolutionLevels[l][0]); const evolution = pokemonEvolutions[prevolutionLevels[l - 1][0]].find(e => e.speciesId === prevolutionLevels[l][0]);
ret.push([ prevolutionLevels[l][0], Math.min(Math.max((evolution?.level!) + Math.round(Utils.randSeedGauss(0.5, 1 + levelDiff * 0.2) * Math.max((evolution?.wildDelay!), 0.5) * 5) - 1, 2, (evolution?.level!)), currentLevel - 1) ]); // TODO: are those bangs correct? ret.push([ prevolutionLevels[l][0], Math.min(Math.max((evolution?.level!) + Math.round(randSeedGauss(0.5, 1 + levelDiff * 0.2) * Math.max((evolution?.wildDelay!), 0.5) * 5) - 1, 2, (evolution?.level!)), currentLevel - 1) ]); // TODO: are those bangs correct?
} }
const lastPrevolutionLevel = ret[prevolutionLevels.length - 1][1]; const lastPrevolutionLevel = ret[prevolutionLevels.length - 1][1];
const evolution = pokemonEvolutions[prevolutionLevels[prevolutionLevels.length - 1][0]].find(e => e.speciesId === this.speciesId); const evolution = pokemonEvolutions[prevolutionLevels[prevolutionLevels.length - 1][0]].find(e => e.speciesId === this.speciesId);
ret.push([ this.speciesId, Math.min(Math.max(lastPrevolutionLevel + Math.round(Utils.randSeedGauss(0.5, 1 + levelDiff * 0.2) * Math.max((evolution?.wildDelay!), 0.5) * 5), lastPrevolutionLevel + 1, (evolution?.level!)), currentLevel) ]); // TODO: are those bangs correct? ret.push([ this.speciesId, Math.min(Math.max(lastPrevolutionLevel + Math.round(randSeedGauss(0.5, 1 + levelDiff * 0.2) * Math.max((evolution?.wildDelay!), 0.5) * 5), lastPrevolutionLevel + 1, (evolution?.level!)), currentLevel) ]); // TODO: are those bangs correct?
} else { } else {
ret.push([ this.speciesId, 1 ]); ret.push([ this.speciesId, 1 ]);
} }
@ -957,7 +957,7 @@ export function getPokerusStarters(scene: BattleScene): PokemonSpecies[] {
date.setUTCHours(0, 0, 0, 0); date.setUTCHours(0, 0, 0, 0);
scene.executeWithSeedOffset(() => { scene.executeWithSeedOffset(() => {
while (pokerusStarters.length < POKERUS_STARTER_COUNT) { while (pokerusStarters.length < POKERUS_STARTER_COUNT) {
const randomSpeciesId = parseInt(Utils.randSeedItem(Object.keys(speciesStarterCosts)), 10); const randomSpeciesId = parseInt(randSeedItem(Object.keys(speciesStarterCosts)), 10);
const species = getPokemonSpecies(randomSpeciesId); const species = getPokemonSpecies(randomSpeciesId);
if (!pokerusStarters.includes(species)) { if (!pokerusStarters.includes(species)) {
pokerusStarters.push(species); pokerusStarters.push(species);

View File

@ -1,4 +1,4 @@
import * as Utils from "../utils"; import { randIntRange } from "#app/utils";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import i18next, { ParseKeys } from "i18next"; import i18next, { ParseKeys } from "i18next";
@ -107,7 +107,7 @@ export function getStatusEffectCatchRateMultiplier(statusEffect: StatusEffect):
* Returns a random non-volatile StatusEffect * Returns a random non-volatile StatusEffect
*/ */
export function generateRandomStatusEffect(): StatusEffect { export function generateRandomStatusEffect(): StatusEffect {
return Utils.randIntRange(1, 6); return randIntRange(1, 6);
} }
/** /**
@ -123,7 +123,7 @@ export function getRandomStatusEffect(statusEffectA: StatusEffect, statusEffectB
return statusEffectA; return statusEffectA;
} }
return Utils.randIntRange(0, 2) ? statusEffectA : statusEffectB; return randIntRange(0, 2) ? statusEffectA : statusEffectB;
} }
/** /**
@ -140,7 +140,7 @@ export function getRandomStatus(statusA: Status | null, statusB: Status | null):
} }
return Utils.randIntRange(0, 2) ? statusA : statusB; return randIntRange(0, 2) ? statusA : statusB;
} }
/** /**

View File

@ -1,7 +1,7 @@
import Pokemon from "../field/pokemon"; import Pokemon from "#app/field/pokemon";
import Move from "./move"; import Move from "./move";
import { Type } from "./type"; import { Type } from "./type";
import * as Utils from "../utils"; import { NumberHolder } from "#app/utils";
import { ChangeMovePriorityAbAttr, applyAbAttrs } from "./ability"; import { ChangeMovePriorityAbAttr, applyAbAttrs } from "./ability";
import { ProtectAttr } from "./move"; import { ProtectAttr } from "./move";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
@ -58,7 +58,7 @@ export class Terrain {
switch (this.terrainType) { switch (this.terrainType) {
case TerrainType.PSYCHIC: case TerrainType.PSYCHIC:
if (!move.hasAttr(ProtectAttr)) { if (!move.hasAttr(ProtectAttr)) {
const priority = new Utils.IntegerHolder(move.priority); const priority = new NumberHolder(move.priority);
applyAbAttrs(ChangeMovePriorityAbAttr, user, null, false, move, priority); applyAbAttrs(ChangeMovePriorityAbAttr, user, null, false, move, priority);
// 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 priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded()); return priority.value > 0 && user.getOpponents().some(o => targets.includes(o.getBattlerIndex()) && o.isGrounded());

View File

@ -1,11 +1,11 @@
import BattleScene, { startingWave } from "#app/battle-scene"; import BattleScene, { startingWave } from "#app/battle-scene";
import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type"; import { ModifierTypeFunc, modifierTypes } from "#app/modifier/modifier-type";
import { EnemyPokemon, PokemonMove } from "#app/field/pokemon"; import { EnemyPokemon, PokemonMove } from "#app/field/pokemon";
import * as Utils from "#app/utils"; import { toReadableString, randSeedItem, randSeedInt } from "#app/utils";
import { PokeballType } from "#app/data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import { pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonEvolutions, pokemonPrevolutions } from "#balance/pokemon-evolutions";
import PokemonSpecies, { getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species"; import PokemonSpecies, { getPokemonSpecies, PokemonSpeciesFilter } from "#app/data/pokemon-species";
import { tmSpecies } from "#app/data/balance/tms"; import { tmSpecies } from "#balance/tms";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import { doubleBattleDialogue } from "#app/data/dialogue"; import { doubleBattleDialogue } from "#app/data/dialogue";
import { PersistentModifier } from "#app/modifier/modifier"; import { PersistentModifier } from "#app/modifier/modifier";
@ -223,7 +223,7 @@ export class TrainerConfig {
constructor(trainerType: TrainerType, allowLegendaries?: boolean) { constructor(trainerType: TrainerType, allowLegendaries?: boolean) {
this.trainerType = trainerType; this.trainerType = trainerType;
this.name = Utils.toReadableString(TrainerType[this.getDerivedType()]); this.name = toReadableString(TrainerType[this.getDerivedType()]);
this.battleBgm = "battle_trainer"; this.battleBgm = "battle_trainer";
this.mixedBattleBgm = "battle_trainer"; this.mixedBattleBgm = "battle_trainer";
this.victoryBgm = "victory_trainer"; this.victoryBgm = "victory_trainer";
@ -1157,7 +1157,7 @@ function getGymLeaderPartyTemplate(scene: BattleScene) {
*/ */
export function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void) { export function getRandomPartyMemberFunc(speciesPool: Species[], trainerSlot: TrainerSlot = TrainerSlot.TRAINER, ignoreEvolution: boolean = false, postProcess?: (enemyPokemon: EnemyPokemon) => void) {
return (scene: BattleScene, level: number, strength: PartyMemberStrength) => { return (scene: BattleScene, level: number, strength: PartyMemberStrength) => {
let species = Utils.randSeedItem(speciesPool); let species = randSeedItem(speciesPool);
if (!ignoreEvolution) { if (!ignoreEvolution) {
species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex); species = getPokemonSpecies(species).getTrainerSpeciesForLevel(level, true, strength, scene.currentBattle.waveIndex);
} }
@ -1178,9 +1178,9 @@ function getRandomTeraModifiers(party: EnemyPokemon[], count: integer, types?: T
const ret: PersistentModifier[] = []; const ret: PersistentModifier[] = [];
const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i); const partyMemberIndexes = new Array(party.length).fill(null).map((_, i) => i);
for (let t = 0; t < Math.min(count, party.length); t++) { for (let t = 0; t < Math.min(count, party.length); t++) {
const randomIndex = Utils.randSeedItem(partyMemberIndexes); const randomIndex = randSeedItem(partyMemberIndexes);
partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1); partyMemberIndexes.splice(partyMemberIndexes.indexOf(randomIndex), 1);
ret.push(modifierTypes.TERA_SHARD().generateType([], [ Utils.randSeedItem(types ? types : party[randomIndex].getTypes()) ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct? ret.push(modifierTypes.TERA_SHARD().generateType([], [ randSeedItem(types ? types : party[randomIndex].getTypes()) ])!.withIdFromFunc(modifierTypes.TERA_SHARD).newModifier(party[randomIndex]) as PersistentModifier); // TODO: is the bang correct?
} }
return ret; return ret;
} }
@ -2081,7 +2081,7 @@ export const trainerConfigs: TrainerConfigs = {
p.setBoss(true, 2); p.setBoss(true, 2);
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ULTRA_BALL; p.pokeball = PokeballType.ULTRA_BALL;
p.formIndex = Utils.randSeedInt(4, 1); // Shock, Burn, Chill, or Douse Drive p.formIndex = randSeedInt(4, 1); // Shock, Burn, Chill, or Douse Drive
})) }))
.setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BASCULEGION, Species.JELLICENT ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(1, getRandomPartyMemberFunc([ Species.BASCULEGION, Species.JELLICENT ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
@ -2299,7 +2299,7 @@ export const trainerConfigs: TrainerConfigs = {
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.LEAFEON, Species.GLACEON ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.LEAFEON, Species.GLACEON ]))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.ROTOM ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.ROTOM ], TrainerSlot.TRAINER, true, p => {
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.formIndex = Utils.randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow p.formIndex = randSeedInt(5, 1); // Heat, Wash, Frost, Fan, or Mow
})) }))
.setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(4, getRandomPartyMemberFunc([ Species.SYLVEON ], TrainerSlot.TRAINER, true, p => {
p.abilityIndex = 2; // Pixilate p.abilityIndex = 2; // Pixilate
@ -2330,7 +2330,7 @@ export const trainerConfigs: TrainerConfigs = {
})) }))
.setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WALKING_WAKE, Species.GOUGING_FIRE, Species.RAGING_BOLT ])) .setPartyMemberFunc(2, getRandomPartyMemberFunc([ Species.WALKING_WAKE, Species.GOUGING_FIRE, Species.RAGING_BOLT ]))
.setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => { .setPartyMemberFunc(3, getRandomPartyMemberFunc([ Species.REVAVROOM ], TrainerSlot.TRAINER, true, p => {
p.formIndex = Utils.randSeedInt(5, 1); //Random Starmobile form p.formIndex = randSeedInt(5, 1); //Random Starmobile form
p.generateAndPopulateMoveset(); p.generateAndPopulateMoveset();
p.pokeball = PokeballType.ROGUE_BALL; p.pokeball = PokeballType.ROGUE_BALL;
})) }))

View File

@ -1,12 +1,12 @@
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import * as Utils from "../utils"; import { toReadableString } from "#app/utils";
class TrainerNameConfig { class TrainerNameConfig {
public urls: string[]; public urls: string[];
public femaleUrls: string[] | null; public femaleUrls: string[] | null;
constructor(type: TrainerType, ...urls: string[]) { constructor(type: TrainerType, ...urls: string[]) {
this.urls = urls.length ? urls : [ Utils.toReadableString(TrainerType[type]).replace(/ /g, "_") ]; this.urls = urls.length ? urls : [ toReadableString(TrainerType[type]).replace(/ /g, "_") ];
} }
hasGenderVariant(...femaleUrls: string[]): TrainerNameConfig { hasGenderVariant(...femaleUrls: string[]): TrainerNameConfig {

View File

@ -1,4 +1,4 @@
import { VariantTier } from "#app/enums/variant-tier"; import { VariantTier } from "#enums/variant-tier";
export type Variant = 0 | 1 | 2; export type Variant = 0 | 1 | 2;

View File

@ -1,11 +1,11 @@
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { getPokemonNameWithAffix } from "../messages"; import { getPokemonNameWithAffix } from "#app/messages";
import Pokemon from "../field/pokemon"; import Pokemon from "#app/field/pokemon";
import { Type } from "./type"; import { Type } from "./type";
import Move, { AttackMove } from "./move"; import Move, { AttackMove } from "./move";
import * as Utils from "../utils"; import { randSeedInt } from "#app/utils";
import BattleScene from "../battle-scene"; import BattleScene from "#app/battle-scene";
import { SuppressWeatherEffectAbAttr } from "./ability"; import { SuppressWeatherEffectAbAttr } from "./ability";
import { TerrainType, getTerrainName } from "./terrain"; import { TerrainType, getTerrainName } from "./terrain";
import i18next from "i18next"; import i18next from "i18next";
@ -378,7 +378,7 @@ export function getRandomWeatherType(arena: any /* Importing from arena causes a
let totalWeight = 0; let totalWeight = 0;
weatherPool.forEach(w => totalWeight += w.weight); weatherPool.forEach(w => totalWeight += w.weight);
const rand = Utils.randSeedInt(totalWeight); const rand = randSeedInt(totalWeight);
let w = 0; let w = 0;
for (const weather of weatherPool) { for (const weather of weatherPool) {
w += weather.weight; w += weather.weight;

View File

@ -1,6 +1,6 @@
import BattleScene from "../battle-scene"; import BattleScene from "#app/battle-scene";
import { PokeballType } from "../data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import * as Utils from "../utils"; import { getFrameMs, randGauss } from "#app/utils";
export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void { export function addPokeballOpenParticles(scene: BattleScene, x: number, y: number, pokeballType: PokeballType): void {
switch (pokeballType) { switch (pokeballType) {
@ -127,7 +127,7 @@ function doFanOutParticle(scene: BattleScene, trigIndex: integer, x: integer, y:
const particleTimer = scene.tweens.addCounter({ const particleTimer = scene.tweens.addCounter({
repeat: -1, repeat: -1,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
updateParticle(); updateParticle();
} }
@ -159,7 +159,7 @@ export function addPokeballCaptureStars(scene: BattleScene, pokeball: Phaser.Gam
} }
}); });
const dist = Utils.randGauss(25); const dist = randGauss(25);
scene.tweens.add({ scene.tweens.add({
targets: particle, targets: particle,
x: pokeball.x + dist, x: pokeball.x + dist,

View File

@ -1,16 +1,33 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { biomePokemonPools, BiomePoolTier, BiomeTierTrainerPools, biomeTrainerPools, PokemonPools } from "#app/data/balance/biomes"; import {
import { Constructor } from "#app/utils"; biomePokemonPools,
import * as Utils from "#app/utils"; BiomePoolTier,
BiomeTierTrainerPools,
biomeTrainerPools,
PokemonPools,
} from "#balance/biomes";
import { Constructor, randSeedInt } from "#app/utils";
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species"; import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
import { getTerrainClearMessage, getTerrainStartMessage, getWeatherClearMessage, getWeatherStartMessage, Weather, WeatherType } from "#app/data/weather"; import {
getTerrainClearMessage,
getTerrainStartMessage,
getWeatherClearMessage,
getWeatherStartMessage,
Weather,
WeatherType,
} from "#app/data/weather";
import { CommonAnim } from "#app/data/battle-anims"; import { CommonAnim } from "#app/data/battle-anims";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import Move from "#app/data/move"; import Move from "#app/data/move";
import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "#app/data/arena-tag"; import { ArenaTag, ArenaTagSide, ArenaTrapTag, getArenaTag } from "#app/data/arena-tag";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { Terrain, TerrainType } from "#app/data/terrain"; import { Terrain, TerrainType } from "#app/data/terrain";
import { applyPostTerrainChangeAbAttrs, applyPostWeatherChangeAbAttrs, PostTerrainChangeAbAttr, PostWeatherChangeAbAttr } from "#app/data/ability"; import {
applyPostTerrainChangeAbAttrs,
applyPostWeatherChangeAbAttrs,
PostTerrainChangeAbAttr,
PostWeatherChangeAbAttr,
} from "#app/data/ability";
import Pokemon from "#app/field/pokemon"; import Pokemon from "#app/field/pokemon";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena"; import { TagAddedEvent, TagRemovedEvent, TerrainChangedEvent, WeatherChangedEvent } from "#app/events/arena";
@ -22,8 +39,8 @@ import { TimeOfDay } from "#enums/time-of-day";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms"; import { SpeciesFormChangeRevertWeatherFormTrigger, SpeciesFormChangeWeatherTrigger } from "#app/data/pokemon-forms";
import { CommonAnimPhase } from "#app/phases/common-anim-phase"; import { CommonAnimPhase } from "#phases/common-anim-phase";
import { ShowAbilityPhase } from "#app/phases/show-ability-phase"; import { ShowAbilityPhase } from "#phases/show-ability-phase";
export class Arena { export class Arena {
public scene: BattleScene; public scene: BattleScene;
@ -90,7 +107,7 @@ export class Arena {
if (typeof luckValue !== "undefined") { if (typeof luckValue !== "undefined") {
luckModifier = luckValue * (isBossSpecies ? 0.5 : 2); luckModifier = luckValue * (isBossSpecies ? 0.5 : 2);
} }
const tierValue = Utils.randSeedInt(randVal - luckModifier); const tierValue = randSeedInt(randVal - luckModifier);
let tier = !isBossSpecies let tier = !isBossSpecies
? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE ? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE
: tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE; : tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE;
@ -105,7 +122,7 @@ export class Arena {
if (!tierPool.length) { if (!tierPool.length) {
ret = this.scene.randomSpecies(waveIndex, level); ret = this.scene.randomSpecies(waveIndex, level);
} else { } else {
const entry = tierPool[Utils.randSeedInt(tierPool.length)]; const entry = tierPool[randSeedInt(tierPool.length)];
let species: Species; let species: Species;
if (typeof entry === "number") { if (typeof entry === "number") {
species = entry as Species; species = entry as Species;
@ -116,7 +133,7 @@ export class Arena {
if (level >= levelThreshold) { if (level >= levelThreshold) {
const speciesIds = entry[levelThreshold]; const speciesIds = entry[levelThreshold];
if (speciesIds.length > 1) { if (speciesIds.length > 1) {
species = speciesIds[Utils.randSeedInt(speciesIds.length)]; species = speciesIds[randSeedInt(speciesIds.length)];
} else { } else {
species = speciesIds[0]; species = speciesIds[0];
} }
@ -162,7 +179,7 @@ export class Arena {
const isTrainerBoss = !!this.trainerPool[BiomePoolTier.BOSS].length const isTrainerBoss = !!this.trainerPool[BiomePoolTier.BOSS].length
&& (this.scene.gameMode.isTrainerBoss(waveIndex, this.biomeType, this.scene.offsetGym) || isBoss); && (this.scene.gameMode.isTrainerBoss(waveIndex, this.biomeType, this.scene.offsetGym) || isBoss);
console.log(isBoss, this.trainerPool); console.log(isBoss, this.trainerPool);
const tierValue = Utils.randSeedInt(!isTrainerBoss ? 512 : 64); const tierValue = randSeedInt(!isTrainerBoss ? 512 : 64);
let tier = !isTrainerBoss let tier = !isTrainerBoss
? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE ? tierValue >= 156 ? BiomePoolTier.COMMON : tierValue >= 32 ? BiomePoolTier.UNCOMMON : tierValue >= 6 ? BiomePoolTier.RARE : tierValue >= 1 ? BiomePoolTier.SUPER_RARE : BiomePoolTier.ULTRA_RARE
: tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE; : tierValue >= 20 ? BiomePoolTier.BOSS : tierValue >= 6 ? BiomePoolTier.BOSS_RARE : tierValue >= 1 ? BiomePoolTier.BOSS_SUPER_RARE : BiomePoolTier.BOSS_ULTRA_RARE;
@ -172,7 +189,7 @@ export class Arena {
tier--; tier--;
} }
const tierPool = this.trainerPool[tier] || []; const tierPool = this.trainerPool[tier] || [];
return !tierPool.length ? TrainerType.BREEDER : tierPool[Utils.randSeedInt(tierPool.length)]; return !tierPool.length ? TrainerType.BREEDER : tierPool[randSeedInt(tierPool.length)];
} }
getSpeciesFormIndex(species: PokemonSpecies): integer { getSpeciesFormIndex(species: PokemonSpecies): integer {
@ -912,7 +929,7 @@ export class ArenaBase extends Phaser.GameObjects.Container {
if (!this.player) { if (!this.player) {
(this.scene as BattleScene).executeWithSeedOffset(() => { (this.scene as BattleScene).executeWithSeedOffset(() => {
this.propValue = propValue === undefined this.propValue = propValue === undefined
? hasProps ? Utils.randSeedInt(8) : 0 ? hasProps ? randSeedInt(8) : 0
: propValue; : propValue;
this.props.forEach((prop, p) => { this.props.forEach((prop, p) => {
const propKey = `${biomeKey}_b${hasProps ? `_${p + 1}` : ""}`; const propKey = `${biomeKey}_b${hasProps ? `_${p + 1}` : ""}`;

View File

@ -1,7 +1,7 @@
import { TextStyle, addTextObject } from "../ui/text"; import { TextStyle, addTextObject } from "#app/ui/text";
import Pokemon, { DamageResult, HitResult } from "./pokemon"; import Pokemon, { DamageResult, HitResult } from "./pokemon";
import * as Utils from "../utils"; import { formatStat, fixedInt } from "#app/utils";
import { BattlerIndex } from "../battle"; import { BattlerIndex } from "#app/battle";
type TextAndShadowArr = [ string | null, string | null ]; type TextAndShadowArr = [ string | null, string | null ];
@ -21,7 +21,7 @@ export default class DamageNumberHandler {
const battlerIndex = target.getBattlerIndex(); const battlerIndex = target.getBattlerIndex();
const baseScale = target.getSpriteScale() / 6; const baseScale = target.getSpriteScale() / 6;
const damageNumber = addTextObject(scene, target.x, -(scene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, Utils.formatStat(amount, true), TextStyle.SUMMARY); const damageNumber = addTextObject(scene, target.x, -(scene.game.canvas.height / 6) + target.y - target.getSprite().height / 2, formatStat(amount, true), TextStyle.SUMMARY);
damageNumber.setName("text-damage-number"); damageNumber.setName("text-damage-number");
damageNumber.setOrigin(0.5, 1); damageNumber.setOrigin(0.5, 1);
damageNumber.setScale(baseScale); damageNumber.setScale(baseScale);
@ -74,14 +74,14 @@ export default class DamageNumberHandler {
if (scene.damageNumbersMode === 1) { if (scene.damageNumbersMode === 1) {
scene.tweens.add({ scene.tweens.add({
targets: damageNumber, targets: damageNumber,
duration: Utils.fixedInt(750), duration: fixedInt(750),
alpha: 1, alpha: 1,
y: "-=32" y: "-=32"
}); });
scene.tweens.add({ scene.tweens.add({
delay: 375, delay: 375,
targets: damageNumber, targets: damageNumber,
duration: Utils.fixedInt(625), duration: fixedInt(625),
alpha: 0, alpha: 0,
ease: "Sine.easeIn", ease: "Sine.easeIn",
onComplete: () => { onComplete: () => {
@ -98,7 +98,7 @@ export default class DamageNumberHandler {
targets: damageNumber, targets: damageNumber,
tweens: [ tweens: [
{ {
duration: Utils.fixedInt(250), duration: fixedInt(250),
alpha: 1, alpha: 1,
scaleX: 0.75 * baseScale, scaleX: 0.75 * baseScale,
scaleY: 1.25 * baseScale, scaleY: 1.25 * baseScale,
@ -106,7 +106,7 @@ export default class DamageNumberHandler {
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
}, },
{ {
duration: Utils.fixedInt(175), duration: fixedInt(175),
alpha: 1, alpha: 1,
scaleX: 0.875 * baseScale, scaleX: 0.875 * baseScale,
scaleY: 1.125 * baseScale, scaleY: 1.125 * baseScale,
@ -114,59 +114,59 @@ export default class DamageNumberHandler {
ease: "Cubic.easeIn" ease: "Cubic.easeIn"
}, },
{ {
duration: Utils.fixedInt(100), duration: fixedInt(100),
scaleX: 1.25 * baseScale, scaleX: 1.25 * baseScale,
scaleY: 0.75 * baseScale, scaleY: 0.75 * baseScale,
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
}, },
{ {
duration: Utils.fixedInt(175), duration: fixedInt(175),
scaleX: 0.875 * baseScale, scaleX: 0.875 * baseScale,
scaleY: 1.125 * baseScale, scaleY: 1.125 * baseScale,
y: "-=8", y: "-=8",
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
}, },
{ {
duration: Utils.fixedInt(50), duration: fixedInt(50),
scaleX: 0.925 * baseScale, scaleX: 0.925 * baseScale,
scaleY: 1.075 * baseScale, scaleY: 1.075 * baseScale,
y: "+=8", y: "+=8",
ease: "Cubic.easeIn" ease: "Cubic.easeIn"
}, },
{ {
duration: Utils.fixedInt(100), duration: fixedInt(100),
scaleX: 1.125 * baseScale, scaleX: 1.125 * baseScale,
scaleY: 0.875 * baseScale, scaleY: 0.875 * baseScale,
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
}, },
{ {
duration: Utils.fixedInt(175), duration: fixedInt(175),
scaleX: 0.925 * baseScale, scaleX: 0.925 * baseScale,
scaleY: 1.075 * baseScale, scaleY: 1.075 * baseScale,
y: "-=4", y: "-=4",
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
}, },
{ {
duration: Utils.fixedInt(50), duration: fixedInt(50),
scaleX: 0.975 * baseScale, scaleX: 0.975 * baseScale,
scaleY: 1.025 * baseScale, scaleY: 1.025 * baseScale,
y: "+=4", y: "+=4",
ease: "Cubic.easeIn" ease: "Cubic.easeIn"
}, },
{ {
duration: Utils.fixedInt(100), duration: fixedInt(100),
scaleX: 1.075 * baseScale, scaleX: 1.075 * baseScale,
scaleY: 0.925 * baseScale, scaleY: 0.925 * baseScale,
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
}, },
{ {
duration: Utils.fixedInt(25), duration: fixedInt(25),
scaleX: baseScale, scaleX: baseScale,
scaleY: baseScale, scaleY: baseScale,
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
}, },
{ {
delay: Utils.fixedInt(500), delay: fixedInt(500),
alpha: 0, alpha: 0,
onComplete: () => { onComplete: () => {
this.damageNumbers.get(battlerIndex)!.splice(this.damageNumbers.get(battlerIndex)!.indexOf(damageNumber), 1); this.damageNumbers.get(battlerIndex)!.splice(this.damageNumbers.get(battlerIndex)!.indexOf(damageNumber), 1);

View File

@ -3,7 +3,7 @@ import BattleScene from "../battle-scene";
import MysteryEncounter from "../data/mystery-encounters/mystery-encounter"; import MysteryEncounter from "../data/mystery-encounters/mystery-encounter";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils";
import { getSpriteKeysFromSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getSpriteKeysFromSpecies } from "#mystery-encounters/utils/encounter-pokemon-utils";
import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig; import PlayAnimationConfig = Phaser.Types.Animations.PlayAnimationConfig;
type KnownFileRoot = type KnownFileRoot =

View File

@ -1,6 +1,6 @@
import BattleScene from "../battle-scene"; import BattleScene from "#app/battle-scene";
import Pokemon from "./pokemon"; import Pokemon from "./pokemon";
import * as Utils from "../utils"; import { fixedInt, randInt } from "#app/utils";
export default class PokemonSpriteSparkleHandler { export default class PokemonSpriteSparkleHandler {
private sprites: Set<Phaser.GameObjects.Sprite>; private sprites: Set<Phaser.GameObjects.Sprite>;
@ -9,7 +9,7 @@ export default class PokemonSpriteSparkleHandler {
this.sprites = new Set(); this.sprites = new Set();
scene.tweens.addCounter({ scene.tweens.addCounter({
duration: Utils.fixedInt(200), duration: fixedInt(200),
from: 0, from: 0,
to: 1, to: 1,
yoyo: true, yoyo: true,
@ -31,7 +31,7 @@ export default class PokemonSpriteSparkleHandler {
const parent = (pokemon || s).parentContainer; const parent = (pokemon || s).parentContainer;
const texture = s.texture; const texture = s.texture;
const [ width, height ] = [ texture.source[0].width, texture.source[0].height ]; const [ width, height ] = [ texture.source[0].width, texture.source[0].height ];
const [ pixelX, pixelY ] = [ Utils.randInt(width), Utils.randInt(height) ]; const [ pixelX, pixelY ] = [ randInt(width), randInt(height) ];
const ratioX = s.width / width; const ratioX = s.width / width;
const ratioY = s.height / height; const ratioY = s.height / height;
const pixel = texture.manager.getPixel(pixelX, pixelY, texture.key, "__BASE"); const pixel = texture.manager.getPixel(pixelX, pixelY, texture.key, "__BASE");
@ -42,7 +42,7 @@ export default class PokemonSpriteSparkleHandler {
sparkle.setName("sprite-tera-sparkle"); sparkle.setName("sprite-tera-sparkle");
sparkle.play("tera_sparkle"); sparkle.play("tera_sparkle");
parent.add(sparkle); parent.add(sparkle);
s.scene.time.delayedCall(Utils.fixedInt(Math.floor((1000 / 12) * 13)), () => sparkle.destroy()); s.scene.time.delayedCall(fixedInt(Math.floor((1000 / 12) * 13)), () => sparkle.destroy());
} }
} }
} }

View File

@ -3,42 +3,203 @@ import BattleScene, { AnySound } from "#app/battle-scene";
import { Variant, VariantSet, variantColorCache } from "#app/data/variant"; import { Variant, VariantSet, variantColorCache } from "#app/data/variant";
import { variantData } from "#app/data/variant"; import { variantData } from "#app/data/variant";
import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info"; import BattleInfo, { PlayerBattleInfo, EnemyBattleInfo } from "#app/ui/battle-info";
import Move, { HighCritAttr, HitsTagAttr, applyMoveAttrs, FixedDamageAttr, VariableAtkAttr, allMoves, MoveCategory, TypelessAttr, CritOnlyAttr, getMoveTargets, OneHitKOAttr, VariableMoveTypeAttr, VariableDefAttr, AttackMove, ModifiedDamageAttr, VariableMoveTypeMultiplierAttr, IgnoreOpponentStatStagesAttr, SacrificialAttr, VariableMoveCategoryAttr, CounterDamageAttr, StatStageChangeAttr, RechargeAttr, ChargeAttr, IgnoreWeatherTypeDebuffAttr, BypassBurnDamageReductionAttr, SacrificialAttrOnHit, OneHitKOAccuracyAttr, RespectAttackTypeImmunityAttr, MoveTarget, CombinedPledgeStabBoostAttr } from "#app/data/move"; import Move, {
import { default as PokemonSpecies, PokemonSpeciesForm, getFusedSpeciesName, getPokemonSpecies, getPokemonSpeciesForm } from "#app/data/pokemon-species"; HighCritAttr,
import { CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER, getStarterValueFriendshipCap, speciesStarterCosts } from "#app/data/balance/starters"; HitsTagAttr,
import { starterPassiveAbilities } from "#app/data/balance/passives"; applyMoveAttrs,
import { Constructor, isNullOrUndefined, randSeedInt } from "#app/utils"; FixedDamageAttr,
import * as Utils from "#app/utils"; VariableAtkAttr,
allMoves,
MoveCategory,
TypelessAttr,
CritOnlyAttr,
getMoveTargets,
OneHitKOAttr,
VariableMoveTypeAttr,
VariableDefAttr,
AttackMove,
ModifiedDamageAttr,
VariableMoveTypeMultiplierAttr,
IgnoreOpponentStatStagesAttr,
SacrificialAttr,
VariableMoveCategoryAttr,
CounterDamageAttr,
StatStageChangeAttr,
RechargeAttr,
ChargeAttr,
IgnoreWeatherTypeDebuffAttr,
BypassBurnDamageReductionAttr,
SacrificialAttrOnHit,
OneHitKOAccuracyAttr,
RespectAttackTypeImmunityAttr,
MoveTarget,
CombinedPledgeStabBoostAttr,
} from "#app/data/move";
import {
default as PokemonSpecies,
PokemonSpeciesForm,
getFusedSpeciesName,
getPokemonSpecies,
getPokemonSpeciesForm,
} from "#app/data/pokemon-species";
import {
CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER,
getStarterValueFriendshipCap,
speciesStarterCosts,
} from "#balance/starters";
import { starterPassiveAbilities } from "#balance/passives";
import {
randSeedInt,
getIvsFromId,
BooleanHolder,
NumberHolder,
getEnumValues,
isNullOrUndefined,
toDmgValue,
fixedInt,
rgbaToInt,
rgbHexToRgba,
rgbToHsv,
deltaRgb,
isBetween,
Constructor,
} from "#app/utils";
import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "#app/data/type"; import { Type, TypeDamageMultiplier, getTypeDamageMultiplier, getTypeRgb } from "#app/data/type";
import { getLevelTotalExp } from "#app/data/exp"; import { getLevelTotalExp } from "#app/data/exp";
import { Stat, type PermanentStat, type BattleStat, type EffectiveStat, PERMANENT_STATS, BATTLE_STATS, EFFECTIVE_STATS } from "#enums/stat"; import {
import { DamageMoneyRewardModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, HiddenAbilityRateBoosterModifier, BaseStatModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonNatureWeightModifier, ShinyRateBoosterModifier, SurviveDamageModifier, TempStatStageBoosterModifier, TempCritBoosterModifier, StatBoosterModifier, CritBoosterModifier, TerastallizeModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonIncrementingStatModifier, EvoTrackerModifier } from "#app/modifier/modifier"; Stat,
type PermanentStat,
type BattleStat,
type EffectiveStat,
PERMANENT_STATS,
BATTLE_STATS,
EFFECTIVE_STATS,
} from "#enums/stat";
import {
DamageMoneyRewardModifier,
EnemyDamageBoosterModifier,
EnemyDamageReducerModifier,
EnemyEndureChanceModifier,
EnemyFusionChanceModifier,
HiddenAbilityRateBoosterModifier,
BaseStatModifier,
PokemonFriendshipBoosterModifier,
PokemonHeldItemModifier,
PokemonNatureWeightModifier,
ShinyRateBoosterModifier,
SurviveDamageModifier,
TempStatStageBoosterModifier,
TempCritBoosterModifier,
StatBoosterModifier,
CritBoosterModifier,
TerastallizeModifier,
PokemonBaseStatFlatModifier,
PokemonBaseStatTotalModifier,
PokemonIncrementingStatModifier,
EvoTrackerModifier,
} from "#app/modifier/modifier";
import { PokeballType } from "#app/data/pokeball"; import { PokeballType } from "#app/data/pokeball";
import { Gender } from "#app/data/gender"; import { Gender } from "#app/data/gender";
import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims"; import { initMoveAnim, loadMoveAnimAssets } from "#app/data/battle-anims";
import { Status, StatusEffect, getRandomStatus } from "#app/data/status-effect"; import { Status, StatusEffect, getRandomStatus } from "#app/data/status-effect";
import { pokemonEvolutions, pokemonPrevolutions, SpeciesFormEvolution, SpeciesEvolutionCondition, FusionSpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions"; import {
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#app/data/balance/tms"; pokemonEvolutions,
import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoostTag, SubstituteTag, TypeImmuneTag, getBattlerTag, SemiInvulnerableTag, TypeBoostTag, MoveRestrictionBattlerTag, ExposedTag, DragonCheerTag, CritBoostTag, TrappedTag, TarShotTag, AutotomizedTag, PowerTrickTag } from "../data/battler-tags"; pokemonPrevolutions,
SpeciesFormEvolution,
SpeciesEvolutionCondition,
FusionSpeciesFormEvolution,
} from "#balance/pokemon-evolutions";
import { reverseCompatibleTms, tmSpecies, tmPoolTiers } from "#balance/tms";
import {
BattlerTag,
BattlerTagLapseType,
EncoreTag,
GroundedTag,
HighestStatBoostTag,
SubstituteTag,
TypeImmuneTag,
getBattlerTag,
SemiInvulnerableTag,
TypeBoostTag,
MoveRestrictionBattlerTag,
ExposedTag,
DragonCheerTag,
CritBoostTag,
TrappedTag,
TarShotTag,
AutotomizedTag,
PowerTrickTag,
} from "#app/data/battler-tags";
import { WeatherType } from "#app/data/weather"; import { WeatherType } from "#app/data/weather";
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag"; import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag";
import { Ability, AbAttr, StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, ReduceStatusEffectDurationAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs, InfiltratorAbAttr } from "#app/data/ability"; import {
Ability,
AbAttr,
StatMultiplierAbAttr,
BlockCritAbAttr,
BonusCritAbAttr,
BypassBurnDamageReductionAbAttr,
FieldPriorityMoveImmunityAbAttr,
IgnoreOpponentStatStagesAbAttr,
MoveImmunityAbAttr,
PreDefendFullHpEndureAbAttr,
ReceivedMoveDamageMultiplierAbAttr,
ReduceStatusEffectDurationAbAttr,
StabBoostAbAttr,
StatusEffectImmunityAbAttr,
TypeImmunityAbAttr,
WeightMultiplierAbAttr,
allAbilities,
applyAbAttrs,
applyStatMultiplierAbAttrs,
applyPreApplyBattlerTagAbAttrs,
applyPreAttackAbAttrs,
applyPreDefendAbAttrs,
applyPreSetStatusAbAttrs,
UnsuppressableAbilityAbAttr,
SuppressFieldAbilitiesAbAttr,
NoFusionAbilityAbAttr,
MultCritAbAttr,
IgnoreTypeImmunityAbAttr,
DamageBoostAbAttr,
IgnoreTypeStatusEffectImmunityAbAttr,
ConditionalCritAbAttr,
applyFieldStatMultiplierAbAttrs,
FieldMultiplyStatAbAttr,
AddSecondStrikeAbAttr,
UserFieldStatusEffectImmunityAbAttr,
UserFieldBattlerTagImmunityAbAttr,
BattlerTagImmunityAbAttr,
MoveTypeChangeAbAttr,
FullHpResistTypeAbAttr,
applyCheckTrappedAbAttrs,
CheckTrappedAbAttr,
PostSetStatusAbAttr,
applyPostSetStatusAbAttrs,
InfiltratorAbAttr,
} from "#app/data/ability";
import PokemonData from "#app/system/pokemon-data"; import PokemonData from "#app/system/pokemon-data";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import PartyUiHandler, { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler"; import PartyUiHandler, { PartyOption, PartyUiMode } from "#app/ui/party-ui-handler";
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import { LevelMoves } from "#app/data/balance/pokemon-level-moves"; import { LevelMoves } from "#balance/pokemon-level-moves";
import { DamageAchv, achvs } from "#app/system/achv"; import { DamageAchv, achvs } from "#app/system/achv";
import { DexAttr, StarterDataEntry, StarterMoveset } from "#app/system/game-data"; import { DexAttr, StarterDataEntry, StarterMoveset } from "#app/system/game-data";
import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities"; import { QuantizerCelebi, argbFromRgba, rgbaFromArgb } from "@material/material-color-utilities";
import { Nature, getNatureStatMultiplier } from "#app/data/nature"; import { Nature, getNatureStatMultiplier } from "#app/data/nature";
import { SpeciesFormChange, SpeciesFormChangeActiveTrigger, SpeciesFormChangeMoveLearnedTrigger, SpeciesFormChangePostMoveTrigger, SpeciesFormChangeStatusEffectTrigger } from "#app/data/pokemon-forms"; import {
SpeciesFormChange,
SpeciesFormChangeActiveTrigger,
SpeciesFormChangeMoveLearnedTrigger,
SpeciesFormChangePostMoveTrigger,
SpeciesFormChangeStatusEffectTrigger,
} from "#app/data/pokemon-forms";
import { TerrainType } from "#app/data/terrain"; import { TerrainType } from "#app/data/terrain";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import i18next from "i18next"; import i18next from "i18next";
import { speciesEggMoves } from "#app/data/balance/egg-moves"; import { speciesEggMoves } from "#balance/egg-moves";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { applyChallenges, ChallengeType } from "#app/data/challenge"; import { applyChallenges, ChallengeType } from "#app/data/challenge";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
@ -50,22 +211,27 @@ import { Biome } from "#enums/biome";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { DamagePhase } from "#app/phases/damage-phase"; import { DamagePhase } from "#phases/damage-phase";
import { FaintPhase } from "#app/phases/faint-phase"; import { FaintPhase } from "#phases/faint-phase";
import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { LearnMovePhase } from "#phases/learn-move-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEffectPhase } from "#phases/move-effect-phase";
import { MoveEndPhase } from "#app/phases/move-end-phase"; import { MoveEndPhase } from "#phases/move-end-phase";
import { ObtainStatusEffectPhase } from "#app/phases/obtain-status-effect-phase"; import { ObtainStatusEffectPhase } from "#phases/obtain-status-effect-phase";
import { StatStageChangePhase } from "#app/phases/stat-stage-change-phase"; import { StatStageChangePhase } from "#phases/stat-stage-change-phase";
import { SwitchSummonPhase } from "#app/phases/switch-summon-phase"; import { SwitchSummonPhase } from "#phases/switch-summon-phase";
import { ToggleDoublePositionPhase } from "#app/phases/toggle-double-position-phase"; import { ToggleDoublePositionPhase } from "#phases/toggle-double-position-phase";
import { Challenges } from "#enums/challenges"; import { Challenges } from "#enums/challenges";
import { PokemonAnimType } from "#enums/pokemon-anim-type"; import { PokemonAnimType } from "#enums/pokemon-anim-type";
import { PLAYER_PARTY_MAX_SIZE } from "#app/constants"; import { PLAYER_PARTY_MAX_SIZE } from "#app/constants";
import { CustomPokemonData } from "#app/data/custom-pokemon-data"; import { CustomPokemonData } from "#app/data/custom-pokemon-data";
import { SwitchType } from "#enums/switch-type"; import { SwitchType } from "#enums/switch-type";
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
import { BASE_HIDDEN_ABILITY_CHANCE, BASE_SHINY_CHANCE, SHINY_EPIC_CHANCE, SHINY_VARIANT_CHANCE } from "#app/data/balance/rates"; import {
BASE_HIDDEN_ABILITY_CHANCE,
BASE_SHINY_CHANCE,
SHINY_EPIC_CHANCE,
SHINY_VARIANT_CHANCE,
} from "#balance/rates";
export enum FieldPosition { export enum FieldPosition {
CENTER, CENTER,
@ -143,7 +309,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
throw `Cannot create a player Pokemon for species '${species.getName(formIndex)}'`; throw `Cannot create a player Pokemon for species '${species.getName(formIndex)}'`;
} }
const hiddenAbilityChance = new Utils.IntegerHolder(BASE_HIDDEN_ABILITY_CHANCE); const hiddenAbilityChance = new NumberHolder(BASE_HIDDEN_ABILITY_CHANCE);
if (!this.hasTrainer()) { if (!this.hasTrainer()) {
this.scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); this.scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
} }
@ -158,8 +324,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.abilityIndex = abilityIndex; // Use the provided ability index if it is defined this.abilityIndex = abilityIndex; // Use the provided ability index if it is defined
} else { } else {
// If abilityIndex is not provided, determine it based on species and hidden ability // If abilityIndex is not provided, determine it based on species and hidden ability
const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value); const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value);
const randAbilityIndex = Utils.randSeedInt(2); const randAbilityIndex = randSeedInt(2);
if (species.abilityHidden && hasHiddenAbility) { if (species.abilityHidden && hasHiddenAbility) {
// If the species has a hidden ability and the hidden ability is present // If the species has a hidden ability and the hidden ability is present
this.abilityIndex = 2; this.abilityIndex = 2;
@ -215,8 +381,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.usedTMs = dataSource.usedTMs ?? []; this.usedTMs = dataSource.usedTMs ?? [];
this.customPokemonData = new CustomPokemonData(dataSource.customPokemonData); this.customPokemonData = new CustomPokemonData(dataSource.customPokemonData);
} else { } else {
this.id = Utils.randSeedInt(4294967296); this.id = randSeedInt(4294967296);
this.ivs = ivs || Utils.getIvsFromId(this.id); this.ivs = ivs || getIvsFromId(this.id);
if (this.gender === undefined) { if (this.gender === undefined) {
this.generateGender(); this.generateGender();
@ -250,7 +416,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
this.pokerus = false; this.pokerus = false;
if (level > 1) { if (level > 1) {
const fused = new Utils.BooleanHolder(scene.gameMode.isSplicedOnly); const fused = new BooleanHolder(scene.gameMode.isSplicedOnly);
if (!fused.value && !this.isPlayer() && !this.hasTrainer()) { if (!fused.value && !this.isPlayer() && !this.hasTrainer()) {
this.scene.applyModifier(EnemyFusionChanceModifier, false, fused); this.scene.applyModifier(EnemyFusionChanceModifier, false, fused);
} }
@ -345,7 +511,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns {boolean} True if pokemon is allowed in battle * @returns {boolean} True if pokemon is allowed in battle
*/ */
isAllowed(): boolean { isAllowed(): boolean {
const challengeAllowed = new Utils.BooleanHolder(true); const challengeAllowed = new BooleanHolder(true);
applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed); applyChallenges(this.scene.gameMode, ChallengeType.POKEMON_IN_BATTLE, this, challengeAllowed);
return challengeAllowed.value; return challengeAllowed.value;
} }
@ -858,11 +1024,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns the final critical-hit stage value * @returns the final critical-hit stage value
*/ */
getCritStage(source: Pokemon, move: Move): number { getCritStage(source: Pokemon, move: Move): number {
const critStage = new Utils.IntegerHolder(0); const critStage = new NumberHolder(0);
applyMoveAttrs(HighCritAttr, source, this, move, critStage); applyMoveAttrs(HighCritAttr, source, this, move, critStage);
this.scene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critStage); this.scene.applyModifiers(CritBoosterModifier, source.isPlayer(), source, critStage);
this.scene.applyModifiers(TempCritBoosterModifier, source.isPlayer(), critStage); this.scene.applyModifiers(TempCritBoosterModifier, source.isPlayer(), critStage);
const bonusCrit = new Utils.BooleanHolder(false); const bonusCrit = new BooleanHolder(false);
//@ts-ignore //@ts-ignore
if (applyAbAttrs(BonusCritAbAttr, source, null, false, bonusCrit)) { // TODO: resolve ts-ignore. This is a promise. Checking a promise is bogus. if (applyAbAttrs(BonusCritAbAttr, source, null, false, bonusCrit)) { // TODO: resolve ts-ignore. This is a promise. Checking a promise is bogus.
if (bonusCrit.value) { if (bonusCrit.value) {
@ -896,11 +1062,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns the final in-battle value of a stat * @returns the final in-battle value of a stat
*/ */
getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreAbility: boolean = false, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): integer { getEffectiveStat(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreAbility: boolean = false, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): integer {
const statValue = new Utils.NumberHolder(this.getStat(stat, false)); const statValue = new NumberHolder(this.getStat(stat, false));
this.scene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue); this.scene.applyModifiers(StatBoosterModifier, this.isPlayer(), this, stat, statValue);
// The Ruin abilities here are never ignored, but they reveal themselves on summon anyway // The Ruin abilities here are never ignored, but they reveal themselves on summon anyway
const fieldApplied = new Utils.BooleanHolder(false); const fieldApplied = new BooleanHolder(false);
for (const pokemon of this.scene.getField(true)) { for (const pokemon of this.scene.getField(true)) {
applyFieldStatMultiplierAbAttrs(FieldMultiplyStatAbAttr, pokemon, stat, statValue, this, fieldApplied, simulated); applyFieldStatMultiplierAbAttrs(FieldMultiplyStatAbAttr, pokemon, stat, statValue, this, fieldApplied, simulated);
if (fieldApplied.value) { if (fieldApplied.value) {
@ -966,7 +1132,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const baseStats = this.calculateBaseStats(); const baseStats = this.calculateBaseStats();
// Using base stats, calculate and store stats one by one // Using base stats, calculate and store stats one by one
for (const s of PERMANENT_STATS) { for (const s of PERMANENT_STATS) {
const statHolder = new Utils.IntegerHolder(Math.floor(((2 * baseStats[s] + this.ivs[s]) * this.level) * 0.01)); const statHolder = new NumberHolder(Math.floor(((2 * baseStats[s] + this.ivs[s]) * this.level) * 0.01));
if (s === Stat.HP) { if (s === Stat.HP) {
statHolder.value = statHolder.value + this.level + 10; statHolder.value = statHolder.value + this.level + 10;
this.scene.applyModifier(PokemonIncrementingStatModifier, this.isPlayer(), this, s, statHolder); this.scene.applyModifier(PokemonIncrementingStatModifier, this.isPlayer(), this, s, statHolder);
@ -983,7 +1149,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
} else { } else {
statHolder.value += 5; statHolder.value += 5;
const natureStatMultiplier = new Utils.NumberHolder(getNatureStatMultiplier(this.getNature(), s)); const natureStatMultiplier = new NumberHolder(getNatureStatMultiplier(this.getNature(), s));
this.scene.applyModifier(PokemonNatureWeightModifier, this.isPlayer(), this, natureStatMultiplier); this.scene.applyModifier(PokemonNatureWeightModifier, this.isPlayer(), this, natureStatMultiplier);
if (natureStatMultiplier.value !== 1) { if (natureStatMultiplier.value !== 1) {
statHolder.value = Math.max(Math[natureStatMultiplier.value > 1 ? "ceil" : "floor"](statHolder.value * natureStatMultiplier.value), 1); statHolder.value = Math.max(Math[natureStatMultiplier.value > 1 ? "ceil" : "floor"](statHolder.value * natureStatMultiplier.value), 1);
@ -1030,9 +1196,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
generateNature(naturePool?: Nature[]): void { generateNature(naturePool?: Nature[]): void {
if (naturePool === undefined) { if (naturePool === undefined) {
naturePool = Utils.getEnumValues(Nature); naturePool = getEnumValues(Nature);
} }
const nature = naturePool[Utils.randSeedInt(naturePool.length)]; const nature = naturePool[randSeedInt(naturePool.length)];
this.setNature(nature); this.setNature(nature);
} }
@ -1404,7 +1570,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return false; return false;
} }
if (this.isOnField() && !ability.hasAttr(SuppressFieldAbilitiesAbAttr)) { if (this.isOnField() && !ability.hasAttr(SuppressFieldAbilitiesAbAttr)) {
const suppressed = new Utils.BooleanHolder(false); const suppressed = new BooleanHolder(false);
this.scene.getField(true).filter(p => p !== this).map(p => { this.scene.getField(true).filter(p => p !== this).map(p => {
if (p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility()) { if (p.getAbility().hasAttr(SuppressFieldAbilitiesAbAttr) && p.canApplyAbility()) {
p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, false, suppressed, [ ability ])); p.getAbility().getAttrs(SuppressFieldAbilitiesAbAttr).map(a => a.apply(this, false, false, suppressed, [ ability ]));
@ -1467,11 +1633,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
getWeight(): number { getWeight(): number {
const autotomizedTag = this.getTag(AutotomizedTag); const autotomizedTag = this.getTag(AutotomizedTag);
let weightRemoved = 0; let weightRemoved = 0;
if (!Utils.isNullOrUndefined(autotomizedTag)) { if (!isNullOrUndefined(autotomizedTag)) {
weightRemoved = 100 * autotomizedTag!.autotomizeCount; weightRemoved = 100 * autotomizedTag!.autotomizeCount;
} }
const minWeight = 0.1; const minWeight = 0.1;
const weight = new Utils.NumberHolder(this.species.weight - weightRemoved); const weight = new NumberHolder(this.species.weight - weightRemoved);
// This will trigger the ability overlay so only call this function when necessary // This will trigger the ability overlay so only call this function when necessary
applyAbAttrs(WeightMultiplierAbAttr, this, null, false, weight); applyAbAttrs(WeightMultiplierAbAttr, this, null, false, weight);
@ -1517,7 +1683,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return false; return false;
} }
const trappedByAbility = new Utils.BooleanHolder(false); const trappedByAbility = new BooleanHolder(false);
const opposingField = this.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField(); const opposingField = this.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField();
opposingField.forEach(opponent => opposingField.forEach(opponent =>
@ -1535,7 +1701,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns the {@linkcode Type} of the move after attributes are applied * @returns the {@linkcode Type} of the move after attributes are applied
*/ */
getMoveType(move: Move, simulated: boolean = true): Type { getMoveType(move: Move, simulated: boolean = true): Type {
const moveTypeHolder = new Utils.NumberHolder(move.type); const moveTypeHolder = new NumberHolder(move.type);
applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder); applyMoveAttrs(VariableMoveTypeAttr, this, null, move, moveTypeHolder);
applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder); applyPreAttackAbAttrs(MoveTypeChangeAbAttr, this, null, move, simulated, moveTypeHolder);
@ -1556,12 +1722,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @param move {@linkcode Move} The move being used by the attacking Pokémon. * @param move {@linkcode Move} The move being used by the attacking Pokémon.
* @param ignoreAbility Whether to ignore abilities that might affect type effectiveness or immunity (defaults to `false`). * @param ignoreAbility Whether to ignore abilities that might affect type effectiveness or immunity (defaults to `false`).
* @param simulated Whether to apply abilities via simulated calls (defaults to `true`) * @param simulated Whether to apply abilities via simulated calls (defaults to `true`)
* @param cancelled {@linkcode Utils.BooleanHolder} Stores whether the move was cancelled by a non-type-based immunity. * @param cancelled {@linkcode BooleanHolder} Stores whether the move was cancelled by a non-type-based immunity.
* Currently only used by {@linkcode Pokemon.apply} to determine whether a "No effect" message should be shown. * Currently only used by {@linkcode Pokemon.apply} to determine whether a "No effect" message should be shown.
* @returns The type damage multiplier, indicating the effectiveness of the move * @returns The type damage multiplier, indicating the effectiveness of the move
*/ */
getMoveEffectiveness(source: Pokemon, move: Move, ignoreAbility: boolean = false, simulated: boolean = true, cancelled?: Utils.BooleanHolder): TypeDamageMultiplier { getMoveEffectiveness(source: Pokemon, move: Move, ignoreAbility: boolean = false, simulated: boolean = true, cancelled?: BooleanHolder): TypeDamageMultiplier {
if (!Utils.isNullOrUndefined(this.turnData?.moveEffectiveness)) { if (!isNullOrUndefined(this.turnData?.moveEffectiveness)) {
return this.turnData?.moveEffectiveness; return this.turnData?.moveEffectiveness;
} }
@ -1570,7 +1736,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
const moveType = source.getMoveType(move); const moveType = source.getMoveType(move);
const typeMultiplier = new Utils.NumberHolder((move.category !== MoveCategory.STATUS || move.hasAttr(RespectAttackTypeImmunityAttr)) const typeMultiplier = new NumberHolder((move.category !== MoveCategory.STATUS || move.hasAttr(RespectAttackTypeImmunityAttr))
? this.getAttackTypeEffectiveness(moveType, source, false, simulated) ? this.getAttackTypeEffectiveness(moveType, source, false, simulated)
: 1); : 1);
@ -1583,7 +1749,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
typeMultiplier.value *= 2; typeMultiplier.value *= 2;
} }
const cancelledHolder = cancelled ?? new Utils.BooleanHolder(false); const cancelledHolder = cancelled ?? new BooleanHolder(false);
if (!ignoreAbility) { if (!ignoreAbility) {
applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelledHolder, simulated, typeMultiplier); applyPreDefendAbAttrs(TypeImmunityAbAttr, this, source, move, cancelledHolder, simulated, typeMultiplier);
@ -1642,10 +1808,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
let multiplier = types.map(defType => { let multiplier = types.map(defType => {
const multiplier = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, defType)); const multiplier = new NumberHolder(getTypeDamageMultiplier(moveType, defType));
applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier); applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, multiplier);
if (source) { if (source) {
const ignoreImmunity = new Utils.BooleanHolder(false); const ignoreImmunity = new BooleanHolder(false);
if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) { if (source.isActive(true) && source.hasAbilityWithAttr(IgnoreTypeImmunityAbAttr)) {
applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType); applyAbAttrs(IgnoreTypeImmunityAbAttr, source, ignoreImmunity, simulated, moveType, defType);
} }
@ -1665,7 +1831,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return multiplier.value; return multiplier.value;
}).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier; }).reduce((acc, cur) => acc * cur, 1) as TypeDamageMultiplier;
const typeMultiplierAgainstFlying = new Utils.NumberHolder(getTypeDamageMultiplier(moveType, Type.FLYING)); const typeMultiplierAgainstFlying = new NumberHolder(getTypeDamageMultiplier(moveType, Type.FLYING));
applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, typeMultiplierAgainstFlying); applyChallenges(this.scene.gameMode, ChallengeType.TYPE_EFFECTIVENESS, typeMultiplierAgainstFlying);
// Handle strong winds lowering effectiveness of types super effective against pure flying // Handle strong winds lowering effectiveness of types super effective against pure flying
if (!ignoreStrongWinds && arena.weather?.weatherType === WeatherType.STRONG_WINDS && !arena.weather.isEffectSuppressed(this.scene) && this.isOfType(Type.FLYING) && typeMultiplierAgainstFlying.value === 2) { if (!ignoreStrongWinds && arena.weather?.weatherType === WeatherType.STRONG_WINDS && !arena.weather.isEffectSuppressed(this.scene) && this.isOfType(Type.FLYING) && typeMultiplierAgainstFlying.value === 2) {
@ -1874,7 +2040,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId; const E = this.scene.gameData.trainerId ^ this.scene.gameData.secretId;
const F = rand1 ^ rand2; const F = rand1 ^ rand2;
const shinyThreshold = new Utils.IntegerHolder(BASE_SHINY_CHANCE); const shinyThreshold = new NumberHolder(BASE_SHINY_CHANCE);
if (thresholdOverride === undefined) { if (thresholdOverride === undefined) {
if (this.scene.eventManager.isEventActive()) { if (this.scene.eventManager.isEventActive()) {
shinyThreshold.value *= this.scene.eventManager.getShinyMultiplier(); shinyThreshold.value *= this.scene.eventManager.getShinyMultiplier();
@ -1905,7 +2071,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @returns true if the Pokemon has been set as a shiny, false otherwise * @returns true if the Pokemon has been set as a shiny, false otherwise
*/ */
trySetShinySeed(thresholdOverride?: integer, applyModifiersToOverride?: boolean): boolean { trySetShinySeed(thresholdOverride?: integer, applyModifiersToOverride?: boolean): boolean {
const shinyThreshold = new Utils.IntegerHolder(BASE_SHINY_CHANCE); const shinyThreshold = new NumberHolder(BASE_SHINY_CHANCE);
if (thresholdOverride === undefined || applyModifiersToOverride) { if (thresholdOverride === undefined || applyModifiersToOverride) {
if (thresholdOverride !== undefined && applyModifiersToOverride) { if (thresholdOverride !== undefined && applyModifiersToOverride) {
shinyThreshold.value = thresholdOverride; shinyThreshold.value = thresholdOverride;
@ -1949,9 +2115,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (!this.shiny || (!variantData.hasOwnProperty(variantDataIndex) && !variantData.hasOwnProperty(this.species.speciesId))) { if (!this.shiny || (!variantData.hasOwnProperty(variantDataIndex) && !variantData.hasOwnProperty(this.species.speciesId))) {
return 0; return 0;
} }
const rand = new Utils.NumberHolder(0); const rand = new NumberHolder(0);
this.scene.executeWithSeedOffset(() => { this.scene.executeWithSeedOffset(() => {
rand.value = Utils.randSeedInt(10); rand.value = randSeedInt(10);
}, this.id, this.scene.waveSeed); }, this.id, this.scene.waveSeed);
if (rand.value >= SHINY_VARIANT_CHANCE) { if (rand.value >= SHINY_VARIANT_CHANCE) {
return 0; // 6/10 return 0; // 6/10
@ -1963,13 +2129,13 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
generateFusionSpecies(forStarter?: boolean): void { generateFusionSpecies(forStarter?: boolean): void {
const hiddenAbilityChance = new Utils.IntegerHolder(BASE_HIDDEN_ABILITY_CHANCE); const hiddenAbilityChance = new NumberHolder(BASE_HIDDEN_ABILITY_CHANCE);
if (!this.hasTrainer()) { if (!this.hasTrainer()) {
this.scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance); this.scene.applyModifiers(HiddenAbilityRateBoosterModifier, true, hiddenAbilityChance);
} }
const hasHiddenAbility = !Utils.randSeedInt(hiddenAbilityChance.value); const hasHiddenAbility = !randSeedInt(hiddenAbilityChance.value);
const randAbilityIndex = Utils.randSeedInt(2); const randAbilityIndex = randSeedInt(2);
const filter = !forStarter ? this.species.getCompatibleFusionSpeciesFilter() const filter = !forStarter ? this.species.getCompatibleFusionSpeciesFilter()
: species => { : species => {
@ -2151,7 +2317,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (stabMovePool.length) { if (stabMovePool.length) {
const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0); const totalWeight = stabMovePool.reduce((v, m) => v + m[1], 0);
let rand = Utils.randSeedInt(totalWeight); let rand = randSeedInt(totalWeight);
let index = 0; let index = 0;
while (rand > stabMovePool[index][1]) { while (rand > stabMovePool[index][1]) {
rand -= stabMovePool[index++][1]; rand -= stabMovePool[index++][1];
@ -2162,7 +2328,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const attackMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS); const attackMovePool = baseWeights.filter(m => allMoves[m[0]].category !== MoveCategory.STATUS);
if (attackMovePool.length) { if (attackMovePool.length) {
const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0); const totalWeight = attackMovePool.reduce((v, m) => v + m[1], 0);
let rand = Utils.randSeedInt(totalWeight); let rand = randSeedInt(totalWeight);
let index = 0; let index = 0;
while (rand > attackMovePool[index][1]) { while (rand > attackMovePool[index][1]) {
rand -= attackMovePool[index++][1]; rand -= attackMovePool[index++][1];
@ -2181,7 +2347,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo?.moveId)); movePool = baseWeights.filter(m => !this.moveset.some(mo => m[0] === mo?.moveId));
} }
const totalWeight = movePool.reduce((v, m) => v + m[1], 0); const totalWeight = movePool.reduce((v, m) => v + m[1], 0);
let rand = Utils.randSeedInt(totalWeight); let rand = randSeedInt(totalWeight);
let index = 0; let index = 0;
while (rand > movePool[index][1]) { while (rand > movePool[index][1]) {
rand -= movePool[index++][1]; rand -= movePool[index++][1];
@ -2346,8 +2512,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* @return the stat stage multiplier to be used for effective stat calculation * @return the stat stage multiplier to be used for effective stat calculation
*/ */
getStatStageMultiplier(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): number { getStatStageMultiplier(stat: EffectiveStat, opponent?: Pokemon, move?: Move, ignoreOppAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): number {
const statStage = new Utils.IntegerHolder(this.getStatStage(stat)); const statStage = new NumberHolder(this.getStatStage(stat));
const ignoreStatStage = new Utils.BooleanHolder(false); const ignoreStatStage = new BooleanHolder(false);
if (opponent) { if (opponent) {
if (isCritical) { if (isCritical) {
@ -2371,7 +2537,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
if (!ignoreStatStage.value) { if (!ignoreStatStage.value) {
const statStageMultiplier = new Utils.NumberHolder(Math.max(2, 2 + statStage.value) / Math.max(2, 2 - statStage.value)); const statStageMultiplier = new NumberHolder(Math.max(2, 2 + statStage.value) / Math.max(2, 2 - statStage.value));
this.scene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), stat, statStageMultiplier); this.scene.applyModifiers(TempStatStageBoosterModifier, this.isPlayer(), stat, statStageMultiplier);
return Math.min(statStageMultiplier.value, 4); return Math.min(statStageMultiplier.value, 4);
} }
@ -2394,11 +2560,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return 1; return 1;
} }
const userAccStage = new Utils.IntegerHolder(this.getStatStage(Stat.ACC)); const userAccStage = new NumberHolder(this.getStatStage(Stat.ACC));
const targetEvaStage = new Utils.IntegerHolder(target.getStatStage(Stat.EVA)); const targetEvaStage = new NumberHolder(target.getStatStage(Stat.EVA));
const ignoreAccStatStage = new Utils.BooleanHolder(false); const ignoreAccStatStage = new BooleanHolder(false);
const ignoreEvaStatStage = new Utils.BooleanHolder(false); const ignoreEvaStatStage = new BooleanHolder(false);
applyAbAttrs(IgnoreOpponentStatStagesAbAttr, target, null, false, Stat.ACC, ignoreAccStatStage); applyAbAttrs(IgnoreOpponentStatStagesAbAttr, target, null, false, Stat.ACC, ignoreAccStatStage);
applyAbAttrs(IgnoreOpponentStatStagesAbAttr, this, null, false, Stat.EVA, ignoreEvaStatStage); applyAbAttrs(IgnoreOpponentStatStagesAbAttr, this, null, false, Stat.EVA, ignoreEvaStatStage);
@ -2413,7 +2579,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
targetEvaStage.value = Math.min(0, targetEvaStage.value); targetEvaStage.value = Math.min(0, targetEvaStage.value);
} }
const accuracyMultiplier = new Utils.NumberHolder(1); const accuracyMultiplier = new NumberHolder(1);
if (userAccStage.value !== targetEvaStage.value) { if (userAccStage.value !== targetEvaStage.value) {
accuracyMultiplier.value = userAccStage.value > targetEvaStage.value accuracyMultiplier.value = userAccStage.value > targetEvaStage.value
? (3 + Math.min(userAccStage.value - targetEvaStage.value, 6)) / 3 ? (3 + Math.min(userAccStage.value - targetEvaStage.value, 6)) / 3
@ -2422,7 +2588,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
applyStatMultiplierAbAttrs(StatMultiplierAbAttr, this, Stat.ACC, accuracyMultiplier, false, sourceMove); applyStatMultiplierAbAttrs(StatMultiplierAbAttr, this, Stat.ACC, accuracyMultiplier, false, sourceMove);
const evasionMultiplier = new Utils.NumberHolder(1); const evasionMultiplier = new NumberHolder(1);
applyStatMultiplierAbAttrs(StatMultiplierAbAttr, target, Stat.EVA, evasionMultiplier); applyStatMultiplierAbAttrs(StatMultiplierAbAttr, target, Stat.EVA, evasionMultiplier);
return accuracyMultiplier.value / evasionMultiplier.value; return accuracyMultiplier.value / evasionMultiplier.value;
@ -2453,14 +2619,14 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* The attacker's offensive stat for the given move's category. * The attacker's offensive stat for the given move's category.
* Critical hits cause negative stat stages to be ignored. * Critical hits cause negative stat stages to be ignored.
*/ */
const sourceAtk = new Utils.NumberHolder(source.getEffectiveStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, ignoreSourceAbility, ignoreAbility, isCritical, simulated)); const sourceAtk = new NumberHolder(source.getEffectiveStat(isPhysical ? Stat.ATK : Stat.SPATK, this, undefined, ignoreSourceAbility, ignoreAbility, isCritical, simulated));
applyMoveAttrs(VariableAtkAttr, source, this, move, sourceAtk); applyMoveAttrs(VariableAtkAttr, source, this, move, sourceAtk);
/** /**
* This Pokemon's defensive stat for the given move's category. * This Pokemon's defensive stat for the given move's category.
* Critical hits cause positive stat stages to be ignored. * Critical hits cause positive stat stages to be ignored.
*/ */
const targetDef = new Utils.NumberHolder(this.getEffectiveStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, ignoreAbility, ignoreSourceAbility, isCritical, simulated)); const targetDef = new NumberHolder(this.getEffectiveStat(isPhysical ? Stat.DEF : Stat.SPDEF, source, move, ignoreAbility, ignoreSourceAbility, isCritical, simulated));
applyMoveAttrs(VariableDefAttr, source, this, move, targetDef); applyMoveAttrs(VariableDefAttr, source, this, move, targetDef);
/** /**
@ -2491,10 +2657,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* - `damage`: `number` the attack's final damage output. * - `damage`: `number` the attack's final damage output.
*/ */
getAttackDamage(source: Pokemon, move: Move, ignoreAbility: boolean = false, ignoreSourceAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): DamageCalculationResult { getAttackDamage(source: Pokemon, move: Move, ignoreAbility: boolean = false, ignoreSourceAbility: boolean = false, isCritical: boolean = false, simulated: boolean = true): DamageCalculationResult {
const damage = new Utils.NumberHolder(0); const damage = new NumberHolder(0);
const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
const variableCategory = new Utils.NumberHolder(move.category); const variableCategory = new NumberHolder(move.category);
applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory); applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, variableCategory);
const moveCategory = variableCategory.value as MoveCategory; const moveCategory = variableCategory.value as MoveCategory;
@ -2502,7 +2668,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const moveType = source.getMoveType(move); const moveType = source.getMoveType(move);
/** If `value` is `true`, cancels the move and suppresses "No Effect" messages */ /** If `value` is `true`, cancels the move and suppresses "No Effect" messages */
const cancelled = new Utils.BooleanHolder(false); const cancelled = new BooleanHolder(false);
/** /**
* The effectiveness of the move being used. Along with type matchups, this * The effectiveness of the move being used. Along with type matchups, this
@ -2516,7 +2682,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const isPhysical = moveCategory === MoveCategory.PHYSICAL; const isPhysical = moveCategory === MoveCategory.PHYSICAL;
/** Combined damage multiplier from field effects such as weather, terrain, etc. */ /** Combined damage multiplier from field effects such as weather, terrain, etc. */
const arenaAttackTypeMultiplier = new Utils.NumberHolder(this.scene.arena.getAttackTypeMultiplier(moveType, source.isGrounded())); const arenaAttackTypeMultiplier = new NumberHolder(this.scene.arena.getAttackTypeMultiplier(moveType, source.isGrounded()));
applyMoveAttrs(IgnoreWeatherTypeDebuffAttr, source, this, move, arenaAttackTypeMultiplier); applyMoveAttrs(IgnoreWeatherTypeDebuffAttr, source, this, move, arenaAttackTypeMultiplier);
const isTypeImmune = (typeMultiplier * arenaAttackTypeMultiplier.value) === 0; const isTypeImmune = (typeMultiplier * arenaAttackTypeMultiplier.value) === 0;
@ -2530,7 +2696,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
// If the attack deals fixed damaged, return a result with that much damage // If the attack deals fixed damaged, return a result with that much damage
const fixedDamage = new Utils.IntegerHolder(0); const fixedDamage = new NumberHolder(0);
applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage); applyMoveAttrs(FixedDamageAttr, source, this, move, fixedDamage);
if (fixedDamage.value) { if (fixedDamage.value) {
return { return {
@ -2541,7 +2707,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
// If the attack is a one-hit KO move, return a result with damage equal to this Pokemon's HP // If the attack is a one-hit KO move, return a result with damage equal to this Pokemon's HP
const isOneHitKo = new Utils.BooleanHolder(false); const isOneHitKo = new BooleanHolder(false);
applyMoveAttrs(OneHitKOAttr, source, this, move, isOneHitKo); applyMoveAttrs(OneHitKOAttr, source, this, move, isOneHitKo);
if (isOneHitKo.value) { if (isOneHitKo.value) {
return { return {
@ -2563,19 +2729,19 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const targetMultiplier = (numTargets > 1) ? 0.75 : 1; const targetMultiplier = (numTargets > 1) ? 0.75 : 1;
/** 0.25x multiplier if this is an added strike from the attacker's Parental Bond */ /** 0.25x multiplier if this is an added strike from the attacker's Parental Bond */
const parentalBondMultiplier = new Utils.NumberHolder(1); const parentalBondMultiplier = new NumberHolder(1);
if (!ignoreSourceAbility) { if (!ignoreSourceAbility) {
applyPreAttackAbAttrs(AddSecondStrikeAbAttr, source, this, move, simulated, numTargets, new Utils.IntegerHolder(0), parentalBondMultiplier); applyPreAttackAbAttrs(AddSecondStrikeAbAttr, source, this, move, simulated, numTargets, new NumberHolder(0), parentalBondMultiplier);
} }
/** Doubles damage if this Pokemon's last move was Glaive Rush */ /** Doubles damage if this Pokemon's last move was Glaive Rush */
const glaiveRushMultiplier = new Utils.IntegerHolder(1); const glaiveRushMultiplier = new NumberHolder(1);
if (this.getTag(BattlerTagType.RECEIVE_DOUBLE_DAMAGE)) { if (this.getTag(BattlerTagType.RECEIVE_DOUBLE_DAMAGE)) {
glaiveRushMultiplier.value = 2; glaiveRushMultiplier.value = 2;
} }
/** The damage multiplier when the given move critically hits */ /** The damage multiplier when the given move critically hits */
const criticalMultiplier = new Utils.NumberHolder(isCritical ? 1.5 : 1); const criticalMultiplier = new NumberHolder(isCritical ? 1.5 : 1);
applyAbAttrs(MultCritAbAttr, source, null, simulated, criticalMultiplier); applyAbAttrs(MultCritAbAttr, source, null, simulated, criticalMultiplier);
/** /**
@ -2588,7 +2754,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const sourceTeraType = source.getTeraType(); const sourceTeraType = source.getTeraType();
const matchesSourceType = sourceTypes.includes(moveType); 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 Utils.NumberHolder(1); const stabMultiplier = new NumberHolder(1);
if (matchesSourceType) { if (matchesSourceType) {
stabMultiplier.value += 0.5; stabMultiplier.value += 0.5;
} }
@ -2604,10 +2770,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
stabMultiplier.value = Math.min(stabMultiplier.value, 2.25); 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 Utils.NumberHolder(1); const burnMultiplier = new NumberHolder(1);
if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) { if (isPhysical && source.status && source.status.effect === StatusEffect.BURN) {
if (!move.hasAttr(BypassBurnDamageReductionAttr)) { if (!move.hasAttr(BypassBurnDamageReductionAttr)) {
const burnDamageReductionCancelled = new Utils.BooleanHolder(false); const burnDamageReductionCancelled = new BooleanHolder(false);
if (!ignoreSourceAbility) { if (!ignoreSourceAbility) {
applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled, simulated); applyAbAttrs(BypassBurnDamageReductionAbAttr, source, burnDamageReductionCancelled, simulated);
} }
@ -2618,7 +2784,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
/** Reduces damage if this Pokemon has a relevant screen (e.g. Light Screen for special attacks) */ /** Reduces damage if this Pokemon has a relevant screen (e.g. Light Screen for special attacks) */
const screenMultiplier = new Utils.NumberHolder(1); const screenMultiplier = new NumberHolder(1);
this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, simulated, source, moveCategory, screenMultiplier); this.scene.arena.applyTagsForSide(WeakenMoveScreenTag, defendingSide, simulated, source, moveCategory, screenMultiplier);
/** /**
@ -2627,7 +2793,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* AND * AND
* The move doubles damage when used against that tag * The move doubles damage when used against that tag
*/ */
const hitsTagMultiplier = new Utils.NumberHolder(1); const hitsTagMultiplier = new NumberHolder(1);
move.getAttrs(HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => { move.getAttrs(HitsTagAttr).filter(hta => hta.doubleDamage).forEach(hta => {
if (this.getTag(hta.tagType)) { if (this.getTag(hta.tagType)) {
hitsTagMultiplier.value *= 2; hitsTagMultiplier.value *= 2;
@ -2639,7 +2805,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
? 0.5 ? 0.5
: 1; : 1;
damage.value = Utils.toDmgValue( damage.value = toDmgValue(
baseDamage baseDamage
* targetMultiplier * targetMultiplier
* parentalBondMultiplier.value * parentalBondMultiplier.value
@ -2709,10 +2875,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
*/ */
apply(source: Pokemon, move: Move): HitResult { apply(source: Pokemon, move: Move): HitResult {
const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
const moveCategory = new Utils.NumberHolder(move.category); const moveCategory = new NumberHolder(move.category);
applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, moveCategory); applyMoveAttrs(VariableMoveCategoryAttr, source, this, move, moveCategory);
if (moveCategory.value === MoveCategory.STATUS) { if (moveCategory.value === MoveCategory.STATUS) {
const cancelled = new Utils.BooleanHolder(false); const cancelled = new BooleanHolder(false);
const typeMultiplier = this.getMoveEffectiveness(source, move, false, false, cancelled); const typeMultiplier = this.getMoveEffectiveness(source, move, false, false, cancelled);
if (!cancelled.value && typeMultiplier === 0) { if (!cancelled.value && typeMultiplier === 0) {
@ -2722,7 +2888,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} else { } else {
/** Determines whether the attack critically hits */ /** Determines whether the attack critically hits */
let isCritical: boolean; let isCritical: boolean;
const critOnly = new Utils.BooleanHolder(false); const critOnly = new BooleanHolder(false);
const critAlways = source.getTag(BattlerTagType.ALWAYS_CRIT); const critAlways = source.getTag(BattlerTagType.ALWAYS_CRIT);
applyMoveAttrs(CritOnlyAttr, source, this, move, critOnly); applyMoveAttrs(CritOnlyAttr, source, this, move, critOnly);
applyAbAttrs(ConditionalCritAbAttr, source, null, false, critOnly, this, move); applyAbAttrs(ConditionalCritAbAttr, source, null, false, critOnly, this, move);
@ -2734,7 +2900,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
const noCritTag = this.scene.arena.getTagOnSide(NoCritTag, defendingSide); const noCritTag = this.scene.arena.getTagOnSide(NoCritTag, defendingSide);
const blockCrit = new Utils.BooleanHolder(false); const blockCrit = new BooleanHolder(false);
applyAbAttrs(BlockCritAbAttr, this, null, false, blockCrit); applyAbAttrs(BlockCritAbAttr, this, null, false, blockCrit);
if (noCritTag || blockCrit.value || Overrides.NEVER_CRIT_OVERRIDE) { if (noCritTag || blockCrit.value || Overrides.NEVER_CRIT_OVERRIDE) {
isCritical = false; isCritical = false;
@ -2785,7 +2951,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (damage > 0) { if (damage > 0) {
if (source.isPlayer()) { if (source.isPlayer()) {
this.scene.validateAchvs(DamageAchv, new Utils.NumberHolder(damage)); this.scene.validateAchvs(DamageAchv, new NumberHolder(damage));
if (damage > this.scene.gameData.gameStats.highestDamage) { if (damage > this.scene.gameData.gameStats.highestDamage) {
this.scene.gameData.gameStats.highestDamage = damage; this.scene.gameData.gameStats.highestDamage = damage;
} }
@ -2797,7 +2963,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const attackResult = { move: move.id, result: result as DamageResult, damage: damage, critical: isCritical, sourceId: source.id, sourceBattlerIndex: source.getBattlerIndex() }; const attackResult = { move: move.id, result: result as DamageResult, damage: damage, critical: isCritical, sourceId: source.id, sourceBattlerIndex: source.getBattlerIndex() };
this.turnData.attacksReceived.unshift(attackResult); this.turnData.attacksReceived.unshift(attackResult);
if (source.isPlayer() && !this.isPlayer()) { if (source.isPlayer() && !this.isPlayer()) {
this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, new Utils.NumberHolder(damage)); this.scene.applyModifiers(DamageMoneyRewardModifier, true, source, new NumberHolder(damage));
} }
} }
} }
@ -2850,7 +3016,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
if (this.isFainted()) { if (this.isFainted()) {
return 0; return 0;
} }
const surviveDamage = new Utils.BooleanHolder(false); const surviveDamage = new BooleanHolder(false);
if (!preventEndure && this.hp - damage <= 0) { if (!preventEndure && this.hp - damage <= 0) {
if (this.hp >= 1 && this.getTag(BattlerTagType.ENDURING)) { if (this.hp >= 1 && this.getTag(BattlerTagType.ENDURING)) {
@ -2926,7 +3092,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const stubTag = new BattlerTag(tagType, 0, 0); const stubTag = new BattlerTag(tagType, 0, 0);
const cancelled = new Utils.BooleanHolder(false); const cancelled = new BooleanHolder(false);
applyPreApplyBattlerTagAbAttrs(BattlerTagImmunityAbAttr, this, stubTag, cancelled, true); applyPreApplyBattlerTagAbAttrs(BattlerTagImmunityAbAttr, this, stubTag, cancelled, true);
const userField = this.getAlliedField(); const userField = this.getAlliedField();
@ -2944,7 +3110,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const newTag = getBattlerTag(tagType, turnCount, sourceMove!, sourceId!); // TODO: are the bangs correct? const newTag = getBattlerTag(tagType, turnCount, sourceMove!, sourceId!); // TODO: are the bangs correct?
const cancelled = new Utils.BooleanHolder(false); const cancelled = new BooleanHolder(false);
applyPreApplyBattlerTagAbAttrs(BattlerTagImmunityAbAttr, this, newTag, cancelled); applyPreApplyBattlerTagAbAttrs(BattlerTagImmunityAbAttr, this, newTag, cancelled);
const userField = this.getAlliedField(); const userField = this.getAlliedField();
@ -3179,11 +3345,11 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
let fusionCry = this.getFusionSpeciesForm().cry(scene, soundConfig, true); let fusionCry = this.getFusionSpeciesForm().cry(scene, soundConfig, true);
duration = Math.min(duration, fusionCry.totalDuration * 1000); duration = Math.min(duration, fusionCry.totalDuration * 1000);
fusionCry.destroy(); fusionCry.destroy();
scene.time.delayedCall(Utils.fixedInt(Math.ceil(duration * 0.4)), () => { scene.time.delayedCall(fixedInt(Math.ceil(duration * 0.4)), () => {
try { try {
SoundFade.fadeOut(scene, cry, Utils.fixedInt(Math.ceil(duration * 0.2))); SoundFade.fadeOut(scene, cry, fixedInt(Math.ceil(duration * 0.2)));
fusionCry = this.getFusionSpeciesForm().cry(scene, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0) }, soundConfig)); fusionCry = this.getFusionSpeciesForm().cry(scene, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0) }, soundConfig));
SoundFade.fadeIn(scene, fusionCry, Utils.fixedInt(Math.ceil(duration * 0.2)), scene.masterVolume * scene.seVolume, 0); SoundFade.fadeIn(scene, fusionCry, fixedInt(Math.ceil(duration * 0.2)), scene.masterVolume * scene.seVolume, 0);
} catch (err) { } catch (err) {
console.error(err); console.error(err);
} }
@ -3214,7 +3380,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
tintSprite?.anims.pause(); tintSprite?.anims.pause();
let faintCryTimer : Phaser.Time.TimerEvent | null = this.scene.time.addEvent({ let faintCryTimer : Phaser.Time.TimerEvent | null = this.scene.time.addEvent({
delay: Utils.fixedInt(delay), delay: fixedInt(delay),
repeat: -1, repeat: -1,
callback: () => { callback: () => {
++i; ++i;
@ -3241,7 +3407,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}); });
// Failsafe // Failsafe
this.scene.time.delayedCall(Utils.fixedInt(3000), () => { this.scene.time.delayedCall(fixedInt(3000), () => {
if (!faintCryTimer || !this.scene) { if (!faintCryTimer || !this.scene) {
return; return;
} }
@ -3294,7 +3460,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
tintSprite?.anims.pause(); tintSprite?.anims.pause();
let faintCryTimer: Phaser.Time.TimerEvent | null = this.scene.time.addEvent({ let faintCryTimer: Phaser.Time.TimerEvent | null = this.scene.time.addEvent({
delay: Utils.fixedInt(delay), delay: fixedInt(delay),
repeat: -1, repeat: -1,
callback: () => { callback: () => {
++i; ++i;
@ -3308,9 +3474,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
frameProgress -= frameThreshold; frameProgress -= frameThreshold;
} }
if (i === transitionIndex) { if (i === transitionIndex) {
SoundFade.fadeOut(this.scene, cry, Utils.fixedInt(Math.ceil((duration / rate) * 0.2))); SoundFade.fadeOut(this.scene, cry, fixedInt(Math.ceil((duration / rate) * 0.2)));
fusionCry = this.scene.playSound(fusionCryKey, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0), rate: rate })); fusionCry = this.scene.playSound(fusionCryKey, Object.assign({ seek: Math.max(fusionCry.totalDuration * 0.4, 0), rate: rate }));
SoundFade.fadeIn(this.scene, fusionCry, Utils.fixedInt(Math.ceil((duration / rate) * 0.2)), this.scene.masterVolume * this.scene.seVolume, 0); SoundFade.fadeIn(this.scene, fusionCry, fixedInt(Math.ceil((duration / rate) * 0.2)), this.scene.masterVolume * this.scene.seVolume, 0);
} }
rate *= 0.99; rate *= 0.99;
if (cry && !cry.pendingRemove) { if (cry && !cry.pendingRemove) {
@ -3330,7 +3496,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}); });
// Failsafe // Failsafe
this.scene.time.delayedCall(Utils.fixedInt(3000), () => { this.scene.time.delayedCall(fixedInt(3000), () => {
if (!faintCryTimer || !this.scene) { if (!faintCryTimer || !this.scene) {
return; return;
} }
@ -3378,7 +3544,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
// Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity // Check if the source Pokemon has an ability that cancels the Poison/Toxic immunity
const cancelImmunity = new Utils.BooleanHolder(false); const cancelImmunity = new BooleanHolder(false);
if (sourcePokemon) { if (sourcePokemon) {
applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType); applyAbAttrs(IgnoreTypeStatusEffectImmunityAbAttr, sourcePokemon, cancelImmunity, false, effect, defType);
if (cancelImmunity.value) { if (cancelImmunity.value) {
@ -3417,7 +3583,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
break; break;
} }
const cancelled = new Utils.BooleanHolder(false); const cancelled = new BooleanHolder(false);
applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet); applyPreSetStatusAbAttrs(StatusEffectImmunityAbAttr, this, effect, cancelled, quiet);
const userField = this.getAlliedField(); const userField = this.getAlliedField();
@ -3448,10 +3614,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return true; return true;
} }
let statusCureTurn: Utils.IntegerHolder; let statusCureTurn: NumberHolder;
if (effect === StatusEffect.SLEEP) { if (effect === StatusEffect.SLEEP) {
statusCureTurn = new Utils.IntegerHolder(this.randSeedIntRange(2, 4)); statusCureTurn = new NumberHolder(this.randSeedIntRange(2, 4));
applyAbAttrs(ReduceStatusEffectDurationAbAttr, this, null, false, effect, statusCureTurn); applyAbAttrs(ReduceStatusEffectDurationAbAttr, this, null, false, effect, statusCureTurn);
this.setFrameRate(4); this.setFrameRate(4);
@ -3520,7 +3686,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
isSafeguarded(attacker: Pokemon): boolean { isSafeguarded(attacker: Pokemon): boolean {
const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY; const defendingSide = this.isPlayer() ? ArenaTagSide.PLAYER : ArenaTagSide.ENEMY;
if (this.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, defendingSide)) { if (this.scene.arena.getTagOnSide(ArenaTagType.SAFEGUARD, defendingSide)) {
const bypassed = new Utils.BooleanHolder(false); const bypassed = new BooleanHolder(false);
if (attacker) { if (attacker) {
applyAbAttrs(InfiltratorAbAttr, attacker, null, false, bypassed); applyAbAttrs(InfiltratorAbAttr, attacker, null, false, bypassed);
} }
@ -3707,7 +3873,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const variantColorSet = new Map<integer, integer[]>(); const variantColorSet = new Map<integer, integer[]>();
if (this.shiny && variantColors && variantColors[this.variant]) { if (this.shiny && variantColors && variantColors[this.variant]) {
Object.keys(variantColors[this.variant]).forEach(k => { Object.keys(variantColors[this.variant]).forEach(k => {
variantColorSet.set(Utils.rgbaToInt(Array.from(Object.values(Utils.rgbHexToRgba(k)))), Array.from(Object.values(Utils.rgbHexToRgba(variantColors[this.variant][k])))); variantColorSet.set(rgbaToInt(Array.from(Object.values(rgbHexToRgba(k)))), Array.from(Object.values(rgbHexToRgba(variantColors[this.variant][k]))));
}); });
} }
@ -3716,7 +3882,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const pixel = pixelData[f].slice(i, i + 4); const pixel = pixelData[f].slice(i, i + 4);
let [ r, g, b, a ] = pixel; let [ r, g, b, a ] = pixel;
if (variantColors) { if (variantColors) {
const color = Utils.rgbaToInt([ r, g, b, a ]); const color = rgbaToInt([ r, g, b, a ]);
if (variantColorSet.has(color)) { if (variantColorSet.has(color)) {
const mappedPixel = variantColorSet.get(color); const mappedPixel = variantColorSet.get(color);
if (mappedPixel) { if (mappedPixel) {
@ -3750,7 +3916,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
const variantColorSet = new Map<integer, integer[]>(); const variantColorSet = new Map<integer, integer[]>();
if (this.fusionShiny && variantColors && variantColors[this.fusionVariant]) { if (this.fusionShiny && variantColors && variantColors[this.fusionVariant]) {
Object.keys(variantColors[this.fusionVariant]).forEach(k => { Object.keys(variantColors[this.fusionVariant]).forEach(k => {
variantColorSet.set(Utils.rgbaToInt(Array.from(Object.values(Utils.rgbHexToRgba(k)))), Array.from(Object.values(Utils.rgbHexToRgba(variantColors[this.fusionVariant][k])))); variantColorSet.set(rgbaToInt(Array.from(Object.values(rgbHexToRgba(k)))), Array.from(Object.values(rgbHexToRgba(variantColors[this.fusionVariant][k]))));
}); });
} }
for (let i = 0; i < pixelData[2 + f].length; i += 4) { for (let i = 0; i < pixelData[2 + f].length; i += 4) {
@ -3760,7 +3926,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
} }
let [ r, g, b, a ] = [ pixelData[2 + f][i], pixelData[2 + f][i + 1], pixelData[2 + f][i + 2], pixelData[2 + f][i + 3] ]; let [ r, g, b, a ] = [ pixelData[2 + f][i], pixelData[2 + f][i + 1], pixelData[2 + f][i + 2], pixelData[2 + f][i + 3] ];
if (variantColors) { if (variantColors) {
const color = Utils.rgbaToInt([ r, g, b, a ]); const color = rgbaToInt([ r, g, b, a ]);
if (variantColorSet.has(color)) { if (variantColorSet.has(color)) {
const mappedPixel = variantColorSet.get(color); const mappedPixel = variantColorSet.get(color);
if (mappedPixel) { if (mappedPixel) {
@ -3803,7 +3969,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
}, new Map<number, integer[]>()); }, new Map<number, integer[]>());
hsvColors = Array.from(rgbaColors.keys()).reduce((map: Map<number, number[]>, k: number) => { hsvColors = Array.from(rgbaColors.keys()).reduce((map: Map<number, number[]>, k: number) => {
const rgb = rgbaColors.get(k)!.slice(0, 3); const rgb = rgbaColors.get(k)!.slice(0, 3);
map.set(k, Utils.rgbToHsv(rgb[0], rgb[1], rgb[2])); map.set(k, rgbToHsv(rgb[0], rgb[1], rgb[2]));
return map; return map;
}, new Map<number, number[]>()); }, new Map<number, number[]>());
@ -3870,7 +4036,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
spriteColors.forEach((sc: integer[], i: integer) => { spriteColors.forEach((sc: integer[], i: integer) => {
paletteDeltas.push([]); paletteDeltas.push([]);
for (let p = 0; p < palette.length; p++) { for (let p = 0; p < palette.length; p++) {
paletteDeltas[i].push(Utils.deltaRgb(sc, palette[p])); paletteDeltas[i].push(deltaRgb(sc, palette[p]));
} }
}); });
@ -3903,8 +4069,8 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
* <!-- @import "../battle".Battle --> * <!-- @import "../battle".Battle -->
* This calls either {@linkcode BattleScene.randBattleSeedInt}({@linkcode range}, {@linkcode min}) in `src/battle-scene.ts` * This calls either {@linkcode BattleScene.randBattleSeedInt}({@linkcode range}, {@linkcode min}) in `src/battle-scene.ts`
* which calls {@linkcode Battle.randSeedInt}(`scene`, {@linkcode range}, {@linkcode min}) in `src/battle.ts` * which calls {@linkcode Battle.randSeedInt}(`scene`, {@linkcode range}, {@linkcode min}) in `src/battle.ts`
* which calls {@linkcode Utils.randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts`, * which calls {@linkcode randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts`,
* or it directly calls {@linkcode Utils.randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts` if there is no current battle * or it directly calls {@linkcode randSeedInt randSeedInt}({@linkcode range}, {@linkcode min}) in `src/utils.ts` if there is no current battle
* *
* @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min} * @param range How large of a range of random numbers to choose from. If {@linkcode range} <= 1, returns {@linkcode min}
* @param min The minimum integer to pick, default `0` * @param min The minimum integer to pick, default `0`
@ -3913,7 +4079,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
randSeedInt(range: integer, min: integer = 0): integer { randSeedInt(range: integer, min: integer = 0): integer {
return this.scene.currentBattle return this.scene.currentBattle
? this.scene.randBattleSeedInt(range, min) ? this.scene.randBattleSeedInt(range, min)
: Utils.randSeedInt(range, min); : randSeedInt(range, min);
} }
/** /**
@ -4115,8 +4281,8 @@ export class PlayerPokemon extends Pokemon {
this.scene.gameData.starterData[starterSpeciesId], this.scene.gameData.starterData[starterSpeciesId],
fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null fusionStarterSpeciesId ? this.scene.gameData.starterData[fusionStarterSpeciesId] : null
].filter(d => !!d); ].filter(d => !!d);
const amount = new Utils.IntegerHolder(friendship); const amount = new NumberHolder(friendship);
const starterAmount = new Utils.IntegerHolder(Math.floor(friendship * (this.scene.gameMode.isClassic && friendship > 0 ? CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER : 1) / (fusionStarterSpeciesId ? 2 : 1))); const starterAmount = new NumberHolder(Math.floor(friendship * (this.scene.gameMode.isClassic && friendship > 0 ? CLASSIC_CANDY_FRIENDSHIP_MULTIPLIER : 1) / (fusionStarterSpeciesId ? 2 : 1)));
if (amount.value > 0) { if (amount.value > 0) {
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount); this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, amount);
this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount); this.scene.applyModifier(PokemonFriendshipBoosterModifier, true, this, starterAmount);
@ -4156,7 +4322,7 @@ export class PlayerPokemon extends Pokemon {
pokemon.resetTurnData(); pokemon.resetTurnData();
pokemon.resetStatus(); pokemon.resetStatus();
pokemon.heal(Math.min(Utils.toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp())); pokemon.heal(Math.min(toDmgValue(0.5 * pokemon.getMaxHp()), pokemon.getMaxHp()));
this.scene.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: pokemon.name }), 0, true); this.scene.queueMessage(i18next.t("moveTriggers:revivalBlessing", { pokemonName: pokemon.name }), 0, true);
if (this.scene.currentBattle.double && this.scene.getParty().length > 1) { if (this.scene.currentBattle.double && this.scene.getParty().length > 1) {
@ -4894,7 +5060,7 @@ export class EnemyPokemon extends Pokemon {
//console.log('damage', damage, 'segment', segmentsBypassed + 1, 'segment size', segmentSize, 'damage needed', Math.round(segmentSize * Math.pow(2, segmentsBypassed + 1))); //console.log('damage', damage, 'segment', segmentsBypassed + 1, 'segment size', segmentSize, 'damage needed', Math.round(segmentSize * Math.pow(2, segmentsBypassed + 1)));
} }
damage = Utils.toDmgValue(this.hp - hpThreshold + segmentSize * segmentsBypassed); damage = toDmgValue(this.hp - hpThreshold + segmentSize * segmentsBypassed);
clearedBossSegmentIndex = s - segmentsBypassed; clearedBossSegmentIndex = s - segmentsBypassed;
} }
break; break;
@ -4958,7 +5124,7 @@ export class EnemyPokemon extends Pokemon {
} }
// Pick a random stat from the leftover stats to increase its stages // Pick a random stat from the leftover stats to increase its stages
const randInt = Utils.randSeedInt(totalWeight); const randInt = randSeedInt(totalWeight);
for (const i in statThresholds) { for (const i in statThresholds) {
if (randInt < statThresholds[i]) { if (randInt < statThresholds[i]) {
boostedStat = leftoverStats[i]; boostedStat = leftoverStats[i];
@ -5029,7 +5195,7 @@ export class EnemyPokemon extends Pokemon {
this.metSpecies = this.species.speciesId; this.metSpecies = this.species.speciesId;
const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this); const newPokemon = this.scene.addPlayerPokemon(this.species, this.level, this.abilityIndex, this.formIndex, this.gender, this.shiny, this.variant, this.ivs, this.nature, this);
if (Utils.isBetween(slotIndex, 0, PLAYER_PARTY_MAX_SIZE - 1)) { if (isBetween(slotIndex, 0, PLAYER_PARTY_MAX_SIZE - 1)) {
if (slotIndex === 0) { if (slotIndex === 0) {
newPokemon.setVisible(false); // Hide if replaced with first pokemon newPokemon.setVisible(false); // Hide if replaced with first pokemon
} }
@ -5226,7 +5392,7 @@ export class PokemonMove {
} }
getMovePp(): integer { getMovePp(): integer {
return this.getMove().pp + this.ppUp * Utils.toDmgValue(this.getMove().pp / 5); return this.getMove().pp + this.ppUp * toDmgValue(this.getMove().pp / 5);
} }
getPpRatio(): number { getPpRatio(): number {

View File

@ -1,5 +1,5 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonPrevolutions } from "#balance/pokemon-evolutions";
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species"; import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
import { import {
TrainerConfig, TrainerConfig,
@ -12,7 +12,7 @@ import {
signatureSpecies signatureSpecies
} from "#app/data/trainer-config"; } from "#app/data/trainer-config";
import { EnemyPokemon } from "#app/field/pokemon"; import { EnemyPokemon } from "#app/field/pokemon";
import * as Utils from "#app/utils"; import { randSeedWeightedItem, randSeedItem, randSeedInt } from "#app/utils";
import { PersistentModifier } from "#app/modifier/modifier"; import { PersistentModifier } from "#app/modifier/modifier";
import { trainerNamePools } from "#app/data/trainer-names"; import { trainerNamePools } from "#app/data/trainer-names";
import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag"; import { ArenaTagSide, ArenaTrapTag } from "#app/data/arena-tag";
@ -46,11 +46,11 @@ export default class Trainer extends Phaser.GameObjects.Container {
} }
this.variant = variant; this.variant = variant;
this.partyTemplateIndex = Math.min(partyTemplateIndex !== undefined ? partyTemplateIndex : Utils.randSeedWeightedItem(this.config.partyTemplates.map((_, i) => i)), this.partyTemplateIndex = Math.min(partyTemplateIndex !== undefined ? partyTemplateIndex : randSeedWeightedItem(this.config.partyTemplates.map((_, i) => i)),
this.config.partyTemplates.length - 1); this.config.partyTemplates.length - 1);
if (trainerNamePools.hasOwnProperty(trainerType)) { if (trainerNamePools.hasOwnProperty(trainerType)) {
const namePool = trainerNamePools[trainerType]; const namePool = trainerNamePools[trainerType];
this.name = name || Utils.randSeedItem(Array.isArray(namePool[0]) ? namePool[variant === TrainerVariant.FEMALE ? 1 : 0] : namePool); this.name = name || randSeedItem(Array.isArray(namePool[0]) ? namePool[variant === TrainerVariant.FEMALE ? 1 : 0] : namePool);
if (variant === TrainerVariant.DOUBLE) { if (variant === TrainerVariant.DOUBLE) {
if (this.config.doubleOnly) { if (this.config.doubleOnly) {
if (partnerName) { if (partnerName) {
@ -59,7 +59,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
[ this.name, this.partnerName ] = this.name.split(" & "); [ this.name, this.partnerName ] = this.name.split(" & ");
} }
} else { } else {
this.partnerName = partnerName || Utils.randSeedItem(Array.isArray(namePool[0]) ? namePool[1] : namePool); this.partnerName = partnerName || randSeedItem(Array.isArray(namePool[0]) ? namePool[1] : namePool);
} }
} }
} }
@ -362,7 +362,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
// If useNewSpeciesPool is true, we need to generate a new species from the new species pool, otherwise we generate a random species // If useNewSpeciesPool is true, we need to generate a new species from the new species pool, otherwise we generate a random species
let species = useNewSpeciesPool let species = useNewSpeciesPool
? getPokemonSpecies(newSpeciesPool[Math.floor(Utils.randSeedInt(newSpeciesPool.length))]) ? getPokemonSpecies(newSpeciesPool[Math.floor(randSeedInt(newSpeciesPool.length))])
: template.isSameSpecies(index) && index > offset : template.isSameSpecies(index) && index > offset
? getPokemonSpecies(battle.enemyParty[offset].species.getTrainerSpeciesForLevel(level, false, template.getStrength(offset), this.scene.currentBattle.waveIndex)) ? getPokemonSpecies(battle.enemyParty[offset].species.getTrainerSpeciesForLevel(level, false, template.getStrength(offset), this.scene.currentBattle.waveIndex))
: this.genNewPartyMemberSpecies(level, strength); : this.genNewPartyMemberSpecies(level, strength);
@ -385,7 +385,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
let baseSpecies: PokemonSpecies; let baseSpecies: PokemonSpecies;
if (this.config.speciesPools) { if (this.config.speciesPools) {
const tierValue = Utils.randSeedInt(512); const tierValue = randSeedInt(512);
let tier = tierValue >= 156 ? TrainerPoolTier.COMMON : tierValue >= 32 ? TrainerPoolTier.UNCOMMON : tierValue >= 6 ? TrainerPoolTier.RARE : tierValue >= 1 ? TrainerPoolTier.SUPER_RARE : TrainerPoolTier.ULTRA_RARE; let tier = tierValue >= 156 ? TrainerPoolTier.COMMON : tierValue >= 32 ? TrainerPoolTier.UNCOMMON : tierValue >= 6 ? TrainerPoolTier.RARE : tierValue >= 1 ? TrainerPoolTier.SUPER_RARE : TrainerPoolTier.ULTRA_RARE;
console.log(TrainerPoolTier[tier]); console.log(TrainerPoolTier[tier]);
while (!this.config.speciesPools.hasOwnProperty(tier) || !this.config.speciesPools[tier].length) { while (!this.config.speciesPools.hasOwnProperty(tier) || !this.config.speciesPools[tier].length) {
@ -393,7 +393,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
tier--; tier--;
} }
const tierPool = this.config.speciesPools[tier]; const tierPool = this.config.speciesPools[tier];
baseSpecies = getPokemonSpecies(Utils.randSeedItem(tierPool)); baseSpecies = getPokemonSpecies(randSeedItem(tierPool));
} else { } else {
baseSpecies = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter); baseSpecies = this.scene.randomSpecies(battle.waveIndex, level, false, this.config.speciesFilter);
} }
@ -506,7 +506,7 @@ export default class Trainer extends Phaser.GameObjects.Container {
if (maxScorePartyMemberIndexes.length > 1) { if (maxScorePartyMemberIndexes.length > 1) {
let rand: integer; let rand: integer;
this.scene.executeWithSeedOffset(() => rand = Utils.randSeedInt(maxScorePartyMemberIndexes.length), this.scene.currentBattle.turn << 2); this.scene.executeWithSeedOffset(() => rand = randSeedInt(maxScorePartyMemberIndexes.length), this.scene.currentBattle.turn << 2);
return maxScorePartyMemberIndexes[rand!]; return maxScorePartyMemberIndexes[rand!];
} }

View File

@ -1,11 +1,11 @@
import i18next from "i18next"; import i18next from "i18next";
import { classicFixedBattles, FixedBattleConfig, FixedBattleConfigs } from "./battle"; import { classicFixedBattles, FixedBattleConfig, FixedBattleConfigs } from "./battle";
import BattleScene from "./battle-scene"; import BattleScene from "./battle-scene";
import { allChallenges, applyChallenges, Challenge, ChallengeType, copyChallenge } from "./data/challenge"; import { allChallenges, applyChallenges, Challenge, ChallengeType, copyChallenge } from "#app/data/challenge";
import PokemonSpecies, { allSpecies } from "./data/pokemon-species"; import PokemonSpecies, { allSpecies } from "#app/data/pokemon-species";
import { Arena } from "./field/arena"; import { Arena } from "./field/arena";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import * as Utils from "./utils"; import { randSeedInt, randSeedItem } from "#app/utils";
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";
@ -169,7 +169,7 @@ export class GameMode implements GameModeConfig {
} else if (w < waveIndex) { } else if (w < waveIndex) {
arena.scene.executeWithSeedOffset(() => { arena.scene.executeWithSeedOffset(() => {
const waveTrainerChance = arena.getTrainerChance(); const waveTrainerChance = arena.getTrainerChance();
if (!Utils.randSeedInt(waveTrainerChance)) { if (!randSeedInt(waveTrainerChance)) {
allowTrainerBattle = false; allowTrainerBattle = false;
} }
}, w); }, w);
@ -179,7 +179,7 @@ export class GameMode implements GameModeConfig {
} }
} }
} }
return Boolean(allowTrainerBattle && trainerChance && !Utils.randSeedInt(trainerChance)); return Boolean(allowTrainerBattle && trainerChance && !randSeedInt(trainerChance));
} }
return false; return false;
} }
@ -197,7 +197,7 @@ export class GameMode implements GameModeConfig {
if (this.isDaily && this.isWaveFinal(waveIndex)) { if (this.isDaily && this.isWaveFinal(waveIndex)) {
const allFinalBossSpecies = allSpecies.filter(s => (s.subLegendary || s.legendary || s.mythical) const allFinalBossSpecies = allSpecies.filter(s => (s.subLegendary || s.legendary || s.mythical)
&& s.baseTotal >= 600 && s.speciesId !== Species.ETERNATUS && s.speciesId !== Species.ARCEUS); && s.baseTotal >= 600 && s.speciesId !== Species.ETERNATUS && s.speciesId !== Species.ARCEUS);
return Utils.randSeedItem(allFinalBossSpecies); return randSeedItem(allFinalBossSpecies);
} }
return null; return null;

View File

@ -1,14 +1,14 @@
import Phaser from "phaser"; import Phaser from "phaser";
import * as Utils from "./utils"; import { getEnumValues } from "#app/utils";
import { deepCopy } from "./utils"; import { deepCopy } from "#app/utils";
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 { Mode } from "#app/ui/ui";
import SettingsGamepadUiHandler from "./ui/settings/settings-gamepad-ui-handler"; import SettingsGamepadUiHandler from "#app/ui/settings/settings-gamepad-ui-handler";
import SettingsKeyboardUiHandler from "./ui/settings/settings-keyboard-ui-handler"; import SettingsKeyboardUiHandler from "#app/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";
import { import {
assign, assign,
@ -21,7 +21,7 @@ import { SettingKeyboard } from "#app/system/settings/settings-keyboard";
import TouchControl from "#app/touch-controls"; import TouchControl from "#app/touch-controls";
import { Button } from "#enums/buttons"; import { Button } from "#enums/buttons";
import { Device } from "#enums/devices"; import { Device } from "#enums/devices";
import MoveTouchControlsHandler from "./ui/settings/move-touch-controls-handler"; import MoveTouchControlsHandler from "#app/ui/settings/move-touch-controls-handler";
export interface DeviceMapping { export interface DeviceMapping {
[key: string]: number; [key: string]: number;
@ -112,7 +112,7 @@ export class InputsController {
[Device.KEYBOARD]: "default" [Device.KEYBOARD]: "default"
}; };
for (const b of Utils.getEnumValues(Button)) { for (const b of getEnumValues(Button)) {
this.interactions[b] = { this.interactions[b] = {
pressTime: false, pressTime: false,
isPressed: false, isPressed: false,

View File

@ -4,10 +4,10 @@ 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 * as Utils from "#app/utils"; import { localPing, getEnumValues, verifyLang, getEnumKeys } from "#app/utils";
import { initPokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { initPokemonPrevolutions } from "#balance/pokemon-evolutions";
import { initBiomes } from "#app/data/balance/biomes"; import { initBiomes } from "#balance/biomes";
import { initEggMoves } from "#app/data/balance/egg-moves"; import { initEggMoves } from "#balance/egg-moves";
import { initPokemonForms } from "#app/data/pokemon-forms"; import { initPokemonForms } from "#app/data/pokemon-forms";
import { initSpecies } from "#app/data/pokemon-species"; import { initSpecies } from "#app/data/pokemon-species";
import { initMoves } from "#app/data/move"; import { initMoves } from "#app/data/move";
@ -19,7 +19,7 @@ import i18next from "i18next";
import { initStatsKeys } from "#app/ui/game-stats-ui-handler"; import { initStatsKeys } from "#app/ui/game-stats-ui-handler";
import { initVouchers } from "#app/system/voucher"; import { initVouchers } from "#app/system/voucher";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { initMysteryEncounters } from "#app/data/mystery-encounters/mystery-encounters"; import { initMysteryEncounters } from "#mystery-encounters/mystery-encounters";
export class LoadingScene extends SceneBase { export class LoadingScene extends SceneBase {
public static readonly KEY = "loading"; public static readonly KEY = "loading";
@ -33,7 +33,7 @@ export class LoadingScene extends SceneBase {
} }
preload() { preload() {
Utils.localPing(); localPing();
this.load["manifest"] = this.game["manifest"]; this.load["manifest"] = this.game["manifest"];
this.loadImage("loading_bg", "arenas"); this.loadImage("loading_bg", "arenas");
@ -48,7 +48,7 @@ export class LoadingScene extends SceneBase {
this.loadImage("friendship_overlay", "ui"); this.loadImage("friendship_overlay", "ui");
this.loadImage("cursor", "ui"); this.loadImage("cursor", "ui");
this.loadImage("cursor_reverse", "ui"); this.loadImage("cursor_reverse", "ui");
for (const wv of Utils.getEnumValues(WindowVariant)) { for (const wv of getEnumValues(WindowVariant)) {
for (let w = 1; w <= 5; w++) { for (let w = 1; w <= 5; w++) {
this.loadImage(`window_${w}${getWindowVariantSuffix(wv)}`, "ui/windows"); this.loadImage(`window_${w}${getWindowVariantSuffix(wv)}`, "ui/windows");
} }
@ -168,7 +168,7 @@ export class LoadingScene extends SceneBase {
this.loadImage("default_bg", "arenas"); this.loadImage("default_bg", "arenas");
// Load arena images // Load arena images
Utils.getEnumValues(Biome).map(bt => { getEnumValues(Biome).map(bt => {
const btKey = Biome[bt].toLowerCase(); const btKey = Biome[bt].toLowerCase();
const isBaseAnimated = btKey === "end"; const isBaseAnimated = btKey === "end";
const baseAKey = `${btKey}_a`; const baseAKey = `${btKey}_a`;
@ -230,7 +230,7 @@ export class LoadingScene extends SceneBase {
// Get current lang and load the types atlas for it. English will only load types while all other languages will load types and types_<lang> // Get current lang and load the types atlas for it. English will only load types while all other languages will load types and types_<lang>
const lang = i18next.resolvedLanguage; const lang = i18next.resolvedLanguage;
if (lang !== "en") { if (lang !== "en") {
if (Utils.verifyLang(lang)) { if (verifyLang(lang)) {
this.loadAtlas(`statuses_${lang}`, ""); this.loadAtlas(`statuses_${lang}`, "");
this.loadAtlas(`types_${lang}`, ""); this.loadAtlas(`types_${lang}`, "");
} else { } else {
@ -257,7 +257,7 @@ export class LoadingScene extends SceneBase {
this.loadAtlas("egg_icons", "egg"); this.loadAtlas("egg_icons", "egg");
this.loadAtlas("egg_shard", "egg"); this.loadAtlas("egg_shard", "egg");
this.loadAtlas("egg_lightrays", "egg"); this.loadAtlas("egg_lightrays", "egg");
Utils.getEnumKeys(GachaType).forEach(gt => { getEnumKeys(GachaType).forEach(gt => {
const key = gt.toLowerCase(); const key = gt.toLowerCase();
this.loadImage(`gacha_${key}`, "egg"); this.loadImage(`gacha_${key}`, "egg");
this.loadAtlas(`gacha_underlay_${key}`, "egg"); this.loadAtlas(`gacha_underlay_${key}`, "egg");

View File

@ -1,23 +1,115 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { EvolutionItem, pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { EvolutionItem, pokemonEvolutions } from "#balance/pokemon-evolutions";
import { tmPoolTiers, tmSpecies } from "#app/data/balance/tms"; import { tmPoolTiers, tmSpecies } from "#balance/tms";
import { getBerryEffectDescription, getBerryName } from "#app/data/berry"; import { getBerryEffectDescription, getBerryName } from "#app/data/berry";
import { allMoves, AttackMove, selfStatLowerMoves } from "#app/data/move"; import { allMoves, AttackMove, selfStatLowerMoves } from "#app/data/move";
import { getNatureName, getNatureStatMultiplier, Nature } from "#app/data/nature"; import { getNatureName, getNatureStatMultiplier, Nature } from "#app/data/nature";
import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS, PokeballType } from "#app/data/pokeball"; import { getPokeballCatchMultiplier, getPokeballName, MAX_PER_TYPE_POKEBALLS, PokeballType } from "#app/data/pokeball";
import { FormChangeItem, pokemonFormChanges, SpeciesFormChangeCondition, SpeciesFormChangeItemTrigger } from "#app/data/pokemon-forms"; import {
FormChangeItem,
pokemonFormChanges,
SpeciesFormChangeCondition,
SpeciesFormChangeItemTrigger,
} from "#app/data/pokemon-forms";
import { getStatusEffectDescriptor, StatusEffect } from "#app/data/status-effect"; import { getStatusEffectDescriptor, StatusEffect } from "#app/data/status-effect";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon"; import Pokemon, { EnemyPokemon, PlayerPokemon, PokemonMove } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { AddPokeballModifier, AddVoucherModifier, AttackTypeBoosterModifier, BaseStatModifier, BerryModifier, BoostBugSpawnModifier, BypassSpeedChanceModifier, ContactHeldItemTransferChanceModifier, CritBoosterModifier, DamageMoneyRewardModifier, DoubleBattleChanceBoosterModifier, EnemyAttackStatusEffectChanceModifier, EnemyDamageBoosterModifier, EnemyDamageReducerModifier, EnemyEndureChanceModifier, EnemyFusionChanceModifier, EnemyStatusEffectHealChanceModifier, EnemyTurnHealModifier, EvolutionItemModifier, EvolutionStatBoosterModifier, EvoTrackerModifier, ExpBalanceModifier, ExpBoosterModifier, ExpShareModifier, ExtraModifierModifier, FlinchChanceModifier, FusePokemonModifier, GigantamaxAccessModifier, HealingBoosterModifier, HealShopCostModifier, HiddenAbilityRateBoosterModifier, HitHealModifier, IvScannerModifier, LevelIncrementBoosterModifier, LockModifierTiersModifier, MapModifier, MegaEvolutionAccessModifier, MoneyInterestModifier, MoneyMultiplierModifier, MoneyRewardModifier, MultipleParticipantExpBonusModifier, PokemonAllMovePpRestoreModifier, PokemonBaseStatFlatModifier, PokemonBaseStatTotalModifier, PokemonExpBoosterModifier, PokemonFormChangeItemModifier, PokemonFriendshipBoosterModifier, PokemonHeldItemModifier, PokemonHpRestoreModifier, PokemonIncrementingStatModifier, PokemonInstantReviveModifier, PokemonLevelIncrementModifier, PokemonMoveAccuracyBoosterModifier, PokemonMultiHitModifier, PokemonNatureChangeModifier, PokemonNatureWeightModifier, PokemonPpRestoreModifier, PokemonPpUpModifier, PokemonStatusHealModifier, PreserveBerryModifier, RememberMoveModifier, ResetNegativeStatStageModifier, ShinyRateBoosterModifier, SpeciesCritBoosterModifier, SpeciesStatBoosterModifier, SurviveDamageModifier, SwitchEffectTransferModifier, TempCritBoosterModifier, TempStatStageBoosterModifier, TerastallizeAccessModifier, TerastallizeModifier, TmModifier, TurnHealModifier, TurnHeldItemTransferModifier, TurnStatusEffectModifier, type EnemyPersistentModifier, type Modifier, type PersistentModifier } from "#app/modifier/modifier"; import {
AddPokeballModifier,
AddVoucherModifier,
AttackTypeBoosterModifier,
BaseStatModifier,
BerryModifier,
BoostBugSpawnModifier,
BypassSpeedChanceModifier,
ContactHeldItemTransferChanceModifier,
CritBoosterModifier,
DamageMoneyRewardModifier,
DoubleBattleChanceBoosterModifier,
EnemyAttackStatusEffectChanceModifier,
EnemyDamageBoosterModifier,
EnemyDamageReducerModifier,
EnemyEndureChanceModifier,
EnemyFusionChanceModifier,
EnemyStatusEffectHealChanceModifier,
EnemyTurnHealModifier,
EvolutionItemModifier,
EvolutionStatBoosterModifier,
EvoTrackerModifier,
ExpBalanceModifier,
ExpBoosterModifier,
ExpShareModifier,
ExtraModifierModifier,
FlinchChanceModifier,
FusePokemonModifier,
GigantamaxAccessModifier,
HealingBoosterModifier,
HealShopCostModifier,
HiddenAbilityRateBoosterModifier,
HitHealModifier,
IvScannerModifier,
LevelIncrementBoosterModifier,
LockModifierTiersModifier,
MapModifier,
MegaEvolutionAccessModifier,
MoneyInterestModifier,
MoneyMultiplierModifier,
MoneyRewardModifier,
MultipleParticipantExpBonusModifier,
PokemonAllMovePpRestoreModifier,
PokemonBaseStatFlatModifier,
PokemonBaseStatTotalModifier,
PokemonExpBoosterModifier,
PokemonFormChangeItemModifier,
PokemonFriendshipBoosterModifier,
PokemonHeldItemModifier,
PokemonHpRestoreModifier,
PokemonIncrementingStatModifier,
PokemonInstantReviveModifier,
PokemonLevelIncrementModifier,
PokemonMoveAccuracyBoosterModifier,
PokemonMultiHitModifier,
PokemonNatureChangeModifier,
PokemonNatureWeightModifier,
PokemonPpRestoreModifier,
PokemonPpUpModifier,
PokemonStatusHealModifier,
PreserveBerryModifier,
RememberMoveModifier,
ResetNegativeStatStageModifier,
ShinyRateBoosterModifier,
SpeciesCritBoosterModifier,
SpeciesStatBoosterModifier,
SurviveDamageModifier,
SwitchEffectTransferModifier,
TempCritBoosterModifier,
TempStatStageBoosterModifier,
TerastallizeAccessModifier,
TerastallizeModifier,
TmModifier,
TurnHealModifier,
TurnHeldItemTransferModifier,
TurnStatusEffectModifier,
type EnemyPersistentModifier,
type Modifier,
type PersistentModifier,
} from "#app/modifier/modifier";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { Unlockables } from "#app/system/unlockables"; import { Unlockables } from "#app/system/unlockables";
import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "#app/system/voucher"; import { getVoucherTypeIcon, getVoucherTypeName, VoucherType } from "#app/system/voucher";
import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "#app/ui/party-ui-handler"; import PartyUiHandler, { PokemonMoveSelectFilter, PokemonSelectFilter } from "#app/ui/party-ui-handler";
import { getModifierTierTextTint } from "#app/ui/text"; import { getModifierTierTextTint } from "#app/ui/text";
import { formatMoney, getEnumKeys, getEnumValues, IntegerHolder, NumberHolder, padInt, randSeedInt, randSeedItem } from "#app/utils"; import {
formatMoney,
getEnumKeys,
getEnumValues,
NumberHolder,
padInt,
randSeedInt,
randSeedItem,
} from "#app/utils";
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";
@ -725,7 +817,7 @@ export class MoneyRewardModifierType extends ModifierType {
} }
getDescription(scene: BattleScene): string { getDescription(scene: BattleScene): string {
const moneyAmount = new IntegerHolder(scene.getWaveMoneyAmount(this.moneyMultiplier)); const moneyAmount = new NumberHolder(scene.getWaveMoneyAmount(this.moneyMultiplier));
scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount); scene.applyModifiers(MoneyMultiplierModifier, true, moneyAmount);
const formattedMoney = formatMoney(scene.moneyFormat, moneyAmount.value); const formattedMoney = formatMoney(scene.moneyFormat, moneyAmount.value);

View File

@ -1,19 +1,24 @@
import type BattleScene from "#app/battle-scene"; import type BattleScene from "#app/battle-scene";
import { FusionSpeciesFormEvolution, pokemonEvolutions, pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { FusionSpeciesFormEvolution, pokemonEvolutions, pokemonPrevolutions } from "#balance/pokemon-evolutions";
import { getBerryEffectFunc, getBerryPredicate } from "#app/data/berry"; import { getBerryEffectFunc, getBerryPredicate } from "#app/data/berry";
import { getLevelTotalExp } from "#app/data/exp"; import { getLevelTotalExp } from "#app/data/exp";
import { allMoves } from "#app/data/move"; import { allMoves } from "#app/data/move";
import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball"; import { MAX_PER_TYPE_POKEBALLS } from "#app/data/pokeball";
import { type FormChangeItem, SpeciesFormChangeItemTrigger, SpeciesFormChangeLapseTeraTrigger, SpeciesFormChangeTeraTrigger } from "#app/data/pokemon-forms"; import {
type FormChangeItem,
SpeciesFormChangeItemTrigger,
SpeciesFormChangeLapseTeraTrigger,
SpeciesFormChangeTeraTrigger,
} from "#app/data/pokemon-forms";
import { getStatusEffectHealText } from "#app/data/status-effect"; import { getStatusEffectHealText } from "#app/data/status-effect";
import { Type } from "#app/data/type"; import { Type } from "#app/data/type";
import Pokemon, { type PlayerPokemon } from "#app/field/pokemon"; import Pokemon, { type PlayerPokemon } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { EvolutionPhase } from "#app/phases/evolution-phase"; import { EvolutionPhase } from "#phases/evolution-phase";
import { LearnMovePhase, LearnMoveType } from "#app/phases/learn-move-phase"; import { LearnMovePhase, LearnMoveType } from "#phases/learn-move-phase";
import { LevelUpPhase } from "#app/phases/level-up-phase"; import { LevelUpPhase } from "#phases/level-up-phase";
import { PokemonHealPhase } from "#app/phases/pokemon-heal-phase"; import { PokemonHealPhase } from "#phases/pokemon-heal-phase";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
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";
@ -28,9 +33,27 @@ import { Species } from "#enums/species";
import { type PermanentStat, type TempBattleStat, BATTLE_STATS, Stat, TEMP_BATTLE_STATS } from "#enums/stat"; import { type PermanentStat, type TempBattleStat, BATTLE_STATS, Stat, TEMP_BATTLE_STATS } from "#enums/stat";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import i18next from "i18next"; import i18next from "i18next";
import { type DoubleBattleChanceBoosterModifierType, type EvolutionItemModifierType, type FormChangeItemModifierType, type ModifierOverride, type ModifierType, type PokemonBaseStatTotalModifierType, type PokemonExpBoosterModifierType, type PokemonFriendshipBoosterModifierType, type PokemonMoveAccuracyBoosterModifierType, type PokemonMultiHitModifierType, type TerastallizeModifierType, type TmModifierType, getModifierType, ModifierPoolType, ModifierTypeGenerator, modifierTypes, PokemonHeldItemModifierType } from "./modifier-type"; import {
type DoubleBattleChanceBoosterModifierType,
type EvolutionItemModifierType,
type FormChangeItemModifierType,
type ModifierOverride,
type ModifierType,
type PokemonBaseStatTotalModifierType,
type PokemonExpBoosterModifierType,
type PokemonFriendshipBoosterModifierType,
type PokemonMoveAccuracyBoosterModifierType,
type PokemonMultiHitModifierType,
type TerastallizeModifierType,
type TmModifierType,
getModifierType,
ModifierPoolType,
ModifierTypeGenerator,
modifierTypes,
PokemonHeldItemModifierType,
} from "#app/modifier/modifier-type";
import { Color, ShadowColor } from "#enums/color"; import { Color, ShadowColor } from "#enums/color";
import { FRIENDSHIP_GAIN_FROM_RARE_CANDY } from "#app/data/balance/starters"; import { FRIENDSHIP_GAIN_FROM_RARE_CANDY } from "#balance/starters";
export type ModifierPredicate = (modifier: Modifier) => boolean; export type ModifierPredicate = (modifier: Modifier) => boolean;

View File

@ -9,10 +9,10 @@ import { TimeOfDay } from "#enums/time-of-day";
import { VariantTier } from "#enums/variant-tier"; import { VariantTier } from "#enums/variant-tier";
import { WeatherType } from "#enums/weather-type"; import { WeatherType } from "#enums/weather-type";
import { type PokeballCounts } from "./battle-scene"; import { type PokeballCounts } from "./battle-scene";
import { Gender } from "./data/gender"; import { Gender } from "#app/data/gender";
import { Variant } from "./data/variant"; import { Variant } from "#app/data/variant";
import { type ModifierOverride } from "./modifier/modifier-type"; import { type ModifierOverride } from "#app/modifier/modifier-type";
import { Unlockables } from "./system/unlockables"; import { Unlockables } from "#app/system/unlockables";
import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterType } from "#enums/mystery-encounter-type";
import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier";

View File

@ -1,6 +1,10 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { ModifierTier } from "#app/modifier/modifier-tier"; import { ModifierTier } from "#app/modifier/modifier-tier";
import { regenerateModifierPoolThresholds, ModifierPoolType, getEnemyBuffModifierForWave } from "#app/modifier/modifier-type"; import {
regenerateModifierPoolThresholds,
ModifierPoolType,
getEnemyBuffModifierForWave,
} from "#app/modifier/modifier-type";
import { EnemyPersistentModifier } from "#app/modifier/modifier"; import { EnemyPersistentModifier } from "#app/modifier/modifier";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";

View File

@ -1,9 +1,14 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { getPokeballCatchMultiplier, getPokeballAtlasKey, getPokeballTintColor, doPokeballBounceAnim } from "#app/data/pokeball"; import {
getPokeballCatchMultiplier,
getPokeballAtlasKey,
getPokeballTintColor,
doPokeballBounceAnim,
} from "#app/data/pokeball";
import { getStatusEffectCatchRateMultiplier } from "#app/data/status-effect"; import { getStatusEffectCatchRateMultiplier } from "#app/data/status-effect";
import { PokeballType } from "#app/enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import { StatusEffect } from "#app/enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { addPokeballOpenParticles, addPokeballCaptureStars } from "#app/field/anims"; import { addPokeballOpenParticles, addPokeballCaptureStars } from "#app/field/anims";
import { EnemyPokemon } from "#app/field/pokemon"; import { EnemyPokemon } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
@ -13,8 +18,8 @@ import { PartyUiMode, PartyOption } 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 { Mode } from "#app/ui/ui";
import i18next from "i18next"; import i18next from "i18next";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "#phases/pokemon-phase";
import { VictoryPhase } from "./victory-phase"; import { VictoryPhase } from "#phases/victory-phase";
import { SubstituteTag } from "#app/data/battler-tags"; import { SubstituteTag } from "#app/data/battler-tags";
export class AttemptCapturePhase extends PokemonPhase { export class AttemptCapturePhase extends PokemonPhase {

View File

@ -1,13 +1,13 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { applyAbAttrs, RunSuccessAbAttr } from "#app/data/ability"; import { applyAbAttrs, RunSuccessAbAttr } from "#app/data/ability";
import { Stat } from "#app/enums/stat"; import { Stat } from "#enums/stat";
import { StatusEffect } from "#app/enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import Pokemon, { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon"; import Pokemon, { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
import * as Utils from "#app/utils"; import { NumberHolder } from "#app/utils";
import { BattleEndPhase } from "./battle-end-phase"; import { BattleEndPhase } from "#phases/battle-end-phase";
import { NewBattlePhase } from "./new-battle-phase"; import { NewBattlePhase } from "#phases/new-battle-phase";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "#phases/pokemon-phase";
export class AttemptRunPhase extends PokemonPhase { export class AttemptRunPhase extends PokemonPhase {
constructor(scene: BattleScene, fieldIndex: number) { constructor(scene: BattleScene, fieldIndex: number) {
@ -22,7 +22,7 @@ export class AttemptRunPhase extends PokemonPhase {
const playerPokemon = this.getPokemon(); const playerPokemon = this.getPokemon();
const escapeChance = new Utils.NumberHolder(0); const escapeChance = new NumberHolder(0);
this.attemptRunAway(playerField, enemyField, escapeChance); this.attemptRunAway(playerField, enemyField, escapeChance);
@ -57,7 +57,7 @@ export class AttemptRunPhase extends PokemonPhase {
this.end(); this.end();
} }
attemptRunAway(playerField: PlayerPokemon[], enemyField: EnemyPokemon[], escapeChance: Utils.NumberHolder) { attemptRunAway(playerField: PlayerPokemon[], enemyField: EnemyPokemon[], escapeChance: NumberHolder) {
/** Sum of the speed of all enemy pokemon on the field */ /** Sum of the speed of all enemy pokemon on the field */
const enemySpeed = enemyField.reduce((total: number, enemyPokemon: Pokemon) => total + enemyPokemon.getStat(Stat.SPD), 0); const enemySpeed = enemyField.reduce((total: number, enemyPokemon: Pokemon) => total + enemyPokemon.getStat(Stat.SPD), 0);
/** Sum of the speed of all player pokemon on the field */ /** Sum of the speed of all player pokemon on the field */

View File

@ -1,7 +1,7 @@
import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/ability"; import { applyPostBattleAbAttrs, PostBattleAbAttr } from "#app/data/ability";
import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier"; import { LapsingPersistentModifier, LapsingPokemonHeldItemModifier } from "#app/modifier/modifier";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "#phases/battle-phase";
import { GameOverPhase } from "./game-over-phase"; import { GameOverPhase } from "#phases/game-over-phase";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
export class BattleEndPhase extends BattlePhase { export class BattleEndPhase extends BattlePhase {

View File

@ -4,9 +4,9 @@ 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 * as Utils from "#app/utils"; import { BooleanHolder } from "#app/utils";
import { FieldPhase } from "./field-phase"; import { FieldPhase } from "#phases/field-phase";
import { CommonAnimPhase } from "./common-anim-phase"; import { CommonAnimPhase } from "#phases/common-anim-phase";
/** The phase after attacks where the pokemon eat berries */ /** The phase after attacks where the pokemon eat berries */
export class BerryPhase extends FieldPhase { export class BerryPhase extends FieldPhase {
@ -19,7 +19,7 @@ export class BerryPhase extends FieldPhase {
}, pokemon.isPlayer()); }, pokemon.isPlayer());
if (hasUsableBerry) { if (hasUsableBerry) {
const cancelled = new Utils.BooleanHolder(false); const cancelled = new BooleanHolder(false);
pokemon.getOpponents().map((opp) => applyAbAttrs(PreventBerryUseAbAttr, opp, cancelled)); pokemon.getOpponents().map((opp) => applyAbAttrs(PreventBerryUseAbAttr, opp, cancelled));
if (cancelled.value) { if (cancelled.value) {
@ -42,7 +42,7 @@ export class BerryPhase extends FieldPhase {
this.scene.updateModifiers(pokemon.isPlayer()); this.scene.updateModifiers(pokemon.isPlayer());
applyAbAttrs(HealFromBerryUseAbAttr, pokemon, new Utils.BooleanHolder(false)); applyAbAttrs(HealFromBerryUseAbAttr, pokemon, new BooleanHolder(false));
} }
} }
}); });

View File

@ -1,4 +1,4 @@
import { PostTurnStatusEffectPhase } from "#app/phases/post-turn-status-effect-phase"; import { PostTurnStatusEffectPhase } from "#phases/post-turn-status-effect-phase";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";

View File

@ -1,13 +1,13 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { BattleStyle } from "#app/enums/battle-style"; import { BattleStyle } from "#enums/battle-style";
import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import i18next from "i18next"; import i18next from "i18next";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "#phases/battle-phase";
import { PostSummonPhase } from "./post-summon-phase"; import { PostSummonPhase } from "#phases/post-summon-phase";
import { SummonMissingPhase } from "./summon-missing-phase"; import { SummonMissingPhase } from "#phases/summon-missing-phase";
import { SwitchPhase } from "./switch-phase"; import { SwitchPhase } from "#phases/switch-phase";
import { SwitchType } from "#enums/switch-type"; import { SwitchType } from "#enums/switch-type";
export class CheckSwitchPhase extends BattlePhase { export class CheckSwitchPhase extends BattlePhase {

View File

@ -2,19 +2,19 @@ import BattleScene from "#app/battle-scene";
import { TurnCommand, BattleType } from "#app/battle"; import { TurnCommand, BattleType } from "#app/battle";
import { TrappedTag, EncoreTag } from "#app/data/battler-tags"; import { TrappedTag, EncoreTag } from "#app/data/battler-tags";
import { MoveTargetSet, getMoveTargets } from "#app/data/move"; import { MoveTargetSet, getMoveTargets } from "#app/data/move";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#balance/starters";
import { Abilities } from "#app/enums/abilities"; import { Abilities } from "#enums/abilities";
import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { Biome } from "#app/enums/biome"; import { Biome } from "#enums/biome";
import { Moves } from "#app/enums/moves"; import { Moves } from "#enums/moves";
import { PokeballType } from "#app/enums/pokeball"; import { PokeballType } from "#enums/pokeball";
import { FieldPosition, PlayerPokemon } from "#app/field/pokemon"; import { FieldPosition, PlayerPokemon } 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 { Mode } from "#app/ui/ui";
import i18next from "i18next"; import i18next from "i18next";
import { FieldPhase } from "./field-phase"; import { FieldPhase } from "#phases/field-phase";
import { SelectTargetPhase } from "./select-target-phase"; import { SelectTargetPhase } from "#phases/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";

View File

@ -1,7 +1,7 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims"; import { CommonAnim, CommonBattleAnim } from "#app/data/battle-anims";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "#phases/pokemon-phase";
export class CommonAnimPhase extends PokemonPhase { export class CommonAnimPhase extends PokemonPhase {
private anim: CommonAnim | null; private anim: CommonAnim | null;

View File

@ -1,9 +1,9 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { BattleSpec } from "#app/enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { DamageResult, HitResult } from "#app/field/pokemon"; import { DamageResult, HitResult } from "#app/field/pokemon";
import * as Utils from "#app/utils"; import { fixedInt } from "#app/utils";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "#phases/pokemon-phase";
export class DamagePhase extends PokemonPhase { export class DamagePhase extends PokemonPhase {
private amount: integer; private amount: integer;
@ -25,7 +25,7 @@ export class DamagePhase extends PokemonPhase {
if (this.scene.moveAnimations) { if (this.scene.moveAnimations) {
this.scene.toggleInvert(true); this.scene.toggleInvert(true);
} }
this.scene.time.delayedCall(Utils.fixedInt(1000), () => { this.scene.time.delayedCall(fixedInt(1000), () => {
this.scene.toggleInvert(false); this.scene.toggleInvert(false);
this.applyDamage(); this.applyDamage();
}); });

View File

@ -11,8 +11,8 @@ import PokemonInfoContainer from "#app/ui/pokemon-info-container";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
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 * as Utils from "#app/utils"; import { fixedInt, getFrameMs, randInt } from "#app/utils";
import { EggLapsePhase } from "./egg-lapse-phase"; import { EggLapsePhase } from "#phases/egg-lapse-phase";
import { EggHatchData } from "#app/data/egg-hatch-data"; import { EggHatchData } from "#app/data/egg-hatch-data";
@ -285,15 +285,15 @@ export class EggHatchPhase extends Phase {
this.canSkip = false; this.canSkip = false;
this.hatched = true; this.hatched = true;
if (this.evolutionBgm) { if (this.evolutionBgm) {
SoundFade.fadeOut(this.scene, this.evolutionBgm, Utils.fixedInt(100)); SoundFade.fadeOut(this.scene, this.evolutionBgm, fixedInt(100));
} }
for (let e = 0; e < 5; e++) { for (let e = 0; e < 5; e++) {
this.scene.time.delayedCall(Utils.fixedInt(375 * e), () => this.scene.playSound("se/egg_hatch", { volume: 1 - (e * 0.2) })); this.scene.time.delayedCall(fixedInt(375 * e), () => this.scene.playSound("se/egg_hatch", { volume: 1 - (e * 0.2) }));
} }
this.eggLightraysOverlay.setVisible(true); this.eggLightraysOverlay.setVisible(true);
this.eggLightraysOverlay.play("egg_lightrays"); this.eggLightraysOverlay.play("egg_lightrays");
this.scene.tweens.add({ this.scene.tweens.add({
duration: Utils.fixedInt(125), duration: fixedInt(125),
targets: this.eggHatchOverlay, targets: this.eggHatchOverlay,
alpha: 1, alpha: 1,
ease: "Cubic.easeIn", ease: "Cubic.easeIn",
@ -302,7 +302,7 @@ export class EggHatchPhase extends Phase {
this.canSkip = true; this.canSkip = true;
} }
}); });
this.scene.time.delayedCall(Utils.fixedInt(1500), () => { this.scene.time.delayedCall(fixedInt(1500), () => {
this.canSkip = false; this.canSkip = false;
if (!this.skipped) { if (!this.skipped) {
this.doReveal(); this.doReveal();
@ -335,17 +335,17 @@ export class EggHatchPhase extends Phase {
this.pokemonSprite.setPipelineData("shiny", this.pokemon.shiny); this.pokemonSprite.setPipelineData("shiny", this.pokemon.shiny);
this.pokemonSprite.setPipelineData("variant", this.pokemon.variant); this.pokemonSprite.setPipelineData("variant", this.pokemon.variant);
this.pokemonSprite.setVisible(true); this.pokemonSprite.setVisible(true);
this.scene.time.delayedCall(Utils.fixedInt(250), () => { this.scene.time.delayedCall(fixedInt(250), () => {
this.eggsToHatchCount--; this.eggsToHatchCount--;
this.eggHatchHandler.eventTarget.dispatchEvent(new EggCountChangedEvent(this.eggsToHatchCount)); this.eggHatchHandler.eventTarget.dispatchEvent(new EggCountChangedEvent(this.eggsToHatchCount));
this.pokemon.cry(); this.pokemon.cry();
if (isShiny) { if (isShiny) {
this.scene.time.delayedCall(Utils.fixedInt(500), () => { this.scene.time.delayedCall(fixedInt(500), () => {
this.pokemonShinySparkle.play(`sparkle${this.pokemon.variant ? `_${this.pokemon.variant + 1}` : ""}`); this.pokemonShinySparkle.play(`sparkle${this.pokemon.variant ? `_${this.pokemon.variant + 1}` : ""}`);
this.scene.playSound("se/sparkle"); this.scene.playSound("se/sparkle");
}); });
} }
this.scene.time.delayedCall(Utils.fixedInt(!this.skipped ? !isShiny ? 1250 : 1750 : !isShiny ? 250 : 750), () => { this.scene.time.delayedCall(fixedInt(!this.skipped ? !isShiny ? 1250 : 1750 : !isShiny ? 250 : 750), () => {
this.infoContainer.show(this.pokemon, false, this.skipped ? 2 : 1); this.infoContainer.show(this.pokemon, false, this.skipped ? 2 : 1);
this.scene.playSoundWithoutBgm("evolution_fanfare"); this.scene.playSoundWithoutBgm("evolution_fanfare");
@ -363,7 +363,7 @@ export class EggHatchPhase extends Phase {
}); });
}); });
this.scene.tweens.add({ this.scene.tweens.add({
duration: Utils.fixedInt(this.skipped ? 500 : 3000), duration: fixedInt(this.skipped ? 500 : 3000),
targets: this.eggHatchOverlay, targets: this.eggHatchOverlay,
alpha: 0, alpha: 0,
ease: "Cubic.easeOut" ease: "Cubic.easeOut"
@ -388,9 +388,9 @@ export class EggHatchPhase extends Phase {
doSpray(intensity: integer, offsetY?: number) { doSpray(intensity: integer, offsetY?: number) {
this.scene.tweens.addCounter({ this.scene.tweens.addCounter({
repeat: intensity, repeat: intensity,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
this.doSprayParticle(Utils.randInt(8), offsetY || 0); this.doSprayParticle(randInt(8), offsetY || 0);
} }
}); });
} }
@ -409,12 +409,12 @@ export class EggHatchPhase extends Phase {
let f = 0; let f = 0;
let yOffset = 0; let yOffset = 0;
const speed = 3 - Utils.randInt(8); const speed = 3 - randInt(8);
const amp = 24 + Utils.randInt(32); const amp = 24 + randInt(32);
const particleTimer = this.scene.tweens.addCounter({ const particleTimer = this.scene.tweens.addCounter({
repeat: -1, repeat: -1,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
updateParticle(); updateParticle();
} }

View File

@ -3,11 +3,11 @@ import { Egg, EGG_SEED } from "#app/data/egg";
import { Phase } from "#app/phase"; 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 "#phases/egg-hatch-phase";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import { achvs } from "#app/system/achv"; import { achvs } from "#app/system/achv";
import { PlayerPokemon } from "#app/field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import { EggSummaryPhase } from "./egg-summary-phase"; import { EggSummaryPhase } from "#phases/egg-summary-phase";
import { EggHatchData } from "#app/data/egg-hatch-data"; import { EggHatchData } from "#app/data/egg-hatch-data";
/** /**

View File

@ -4,9 +4,9 @@ import { applyAbAttrs, SyncEncounterNatureAbAttr } from "#app/data/ability";
import { getCharVariantFromDialogue } from "#app/data/dialogue"; import { getCharVariantFromDialogue } from "#app/data/dialogue";
import { TrainerSlot } from "#app/data/trainer-config"; import { TrainerSlot } from "#app/data/trainer-config";
import { getRandomWeatherType } from "#app/data/weather"; import { getRandomWeatherType } from "#app/data/weather";
import { BattleSpec } from "#app/enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { PlayerGender } from "#app/enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { Species } from "#app/enums/species"; import { Species } from "#enums/species";
import { EncounterPhaseEvent } from "#app/events/battle-scene"; import { EncounterPhaseEvent } from "#app/events/battle-scene";
import Pokemon, { FieldPosition } from "#app/field/pokemon"; import Pokemon, { FieldPosition } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
@ -16,26 +16,25 @@ 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 { Mode } from "#app/ui/ui";
import i18next from "i18next"; import i18next from "i18next";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "#phases/battle-phase";
import * as Utils from "#app/utils"; import { randSeedInt, randSeedItem } from "#app/utils";
import { randSeedInt } from "#app/utils"; import { CheckSwitchPhase } from "#phases/check-switch-phase";
import { CheckSwitchPhase } from "./check-switch-phase"; import { GameOverPhase } from "#phases/game-over-phase";
import { GameOverPhase } from "./game-over-phase"; import { PostSummonPhase } from "#phases/post-summon-phase";
import { PostSummonPhase } from "./post-summon-phase"; import { ReturnPhase } from "#phases/return-phase";
import { ReturnPhase } from "./return-phase"; import { ScanIvsPhase } from "#phases/scan-ivs-phase";
import { ScanIvsPhase } from "./scan-ivs-phase"; import { ShinySparklePhase } from "#phases/shiny-sparkle-phase";
import { ShinySparklePhase } from "./shiny-sparkle-phase"; import { SummonPhase } from "#phases/summon-phase";
import { SummonPhase } from "./summon-phase"; import { ToggleDoublePositionPhase } from "#phases/toggle-double-position-phase";
import { ToggleDoublePositionPhase } from "./toggle-double-position-phase";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
import { initEncounterAnims, loadEncounterAnimAssets } from "#app/data/battle-anims"; import { initEncounterAnims, loadEncounterAnimAssets } from "#app/data/battle-anims";
import { MysteryEncounterMode } from "#enums/mystery-encounter-mode"; import { MysteryEncounterMode } from "#enums/mystery-encounter-mode";
import { doTrainerExclamation } from "#app/data/mystery-encounters/utils/encounter-phase-utils"; import { doTrainerExclamation } from "#mystery-encounters/utils/encounter-phase-utils";
import { getEncounterText } from "#app/data/mystery-encounters/utils/encounter-dialogue-utils"; import { getEncounterText } from "#mystery-encounters/utils/encounter-dialogue-utils";
import { MysteryEncounterPhase } from "#app/phases/mystery-encounter-phases"; import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases";
import { getGoldenBugNetSpecies } from "#app/data/mystery-encounters/utils/encounter-pokemon-utils"; import { getGoldenBugNetSpecies } from "#mystery-encounters/utils/encounter-pokemon-utils";
import { Biome } from "#enums/biome"; import { Biome } from "#enums/biome";
import { WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#app/data/mystery-encounters/mystery-encounters"; import { WEIGHT_INCREMENT_ON_SPAWN_MISS } from "#mystery-encounters/mystery-encounters";
export class EncounterPhase extends BattlePhase { export class EncounterPhase extends BattlePhase {
private loaded: boolean; private loaded: boolean;
@ -362,7 +361,7 @@ export class EncounterPhase extends BattlePhase {
doSummon(); doSummon();
} else { } else {
let message: string; let message: string;
this.scene.executeWithSeedOffset(() => message = Utils.randSeedItem(encounterMessages), this.scene.currentBattle.waveIndex); this.scene.executeWithSeedOffset(() => message = randSeedItem(encounterMessages), this.scene.currentBattle.waveIndex);
message = message!; // tell TS compiler it's defined now message = message!; // tell TS compiler it's defined now
const showDialogueAndSummon = () => { const showDialogueAndSummon = () => {
this.scene.ui.showDialogue(message, trainer?.getName(TrainerSlot.NONE, true), null, () => { this.scene.ui.showDialogue(message, trainer?.getName(TrainerSlot.NONE, true), null, () => {

View File

@ -1,5 +1,5 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { PlayerGender } from "#app/enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import { addTextObject, TextStyle } from "#app/ui/text"; import { addTextObject, TextStyle } from "#app/ui/text";
import i18next from "i18next"; import i18next from "i18next";

View File

@ -1,7 +1,7 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { Command } from "#app/ui/command-ui-handler"; import { Command } from "#app/ui/command-ui-handler";
import { FieldPhase } from "./field-phase"; import { FieldPhase } from "#phases/field-phase";
/** /**
* Phase for determining an enemy AI's action for the next turn. * Phase for determining an enemy AI's action for the next turn.

View File

@ -1,6 +1,6 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { EnemyPokemon } from "#app/field/pokemon"; import { EnemyPokemon } from "#app/field/pokemon";
import { PartyMemberPokemonPhase } from "./party-member-pokemon-phase"; import { PartyMemberPokemonPhase } from "#phases/party-member-pokemon-phase";
export abstract class EnemyPartyMemberPokemonPhase extends PartyMemberPokemonPhase { export abstract class EnemyPartyMemberPokemonPhase extends PartyMemberPokemonPhase {
constructor(scene: BattleScene, partyMemberIndex: integer) { constructor(scene: BattleScene, partyMemberIndex: integer) {

View File

@ -1,17 +1,17 @@
import SoundFade from "phaser3-rex-plugins/plugins/soundfade"; import SoundFade from "phaser3-rex-plugins/plugins/soundfade";
import { Phase } from "#app/phase"; import { Phase } from "#app/phase";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { SpeciesFormEvolution } from "#app/data/balance/pokemon-evolutions"; import { SpeciesFormEvolution } from "#balance/pokemon-evolutions";
import EvolutionSceneHandler from "#app/ui/evolution-scene-handler"; import EvolutionSceneHandler from "#app/ui/evolution-scene-handler";
import * as Utils from "#app/utils"; import { fixedInt, getFrameMs, randInt } from "#app/utils";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import { cos, sin } from "#app/field/anims"; import { cos, sin } from "#app/field/anims";
import { PlayerPokemon } from "#app/field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import { getTypeRgb } from "#app/data/type"; import { getTypeRgb } from "#app/data/type";
import i18next from "i18next"; import i18next from "i18next";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { LearnMovePhase } from "#app/phases/learn-move-phase"; import { LearnMovePhase } from "#phases/learn-move-phase";
import { EndEvolutionPhase } from "#app/phases/end-evolution-phase"; import { EndEvolutionPhase } from "#phases/end-evolution-phase";
export class EvolutionPhase extends Phase { export class EvolutionPhase extends Phase {
protected pokemon: PlayerPokemon; protected pokemon: PlayerPokemon;
@ -256,8 +256,8 @@ export class EvolutionPhase extends Phase {
this.scene.playSoundWithoutBgm("evolution_fanfare"); this.scene.playSoundWithoutBgm("evolution_fanfare");
evolvedPokemon.destroy(); evolvedPokemon.destroy();
this.scene.ui.showText(i18next.t("menu:evolutionDone", { pokemonName: preName, evolvedPokemonName: this.pokemon.name }), null, () => this.end(), null, true, Utils.fixedInt(4000)); this.scene.ui.showText(i18next.t("menu:evolutionDone", { pokemonName: preName, evolvedPokemonName: this.pokemon.name }), null, () => this.end(), null, true, fixedInt(4000));
this.scene.time.delayedCall(Utils.fixedInt(4250), () => this.scene.playBgm()); this.scene.time.delayedCall(fixedInt(4250), () => this.scene.playBgm());
}); });
}); });
} }
@ -285,7 +285,7 @@ export class EvolutionPhase extends Phase {
this.scene.tweens.addCounter({ this.scene.tweens.addCounter({
repeat: 64, repeat: 64,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
if (f < 64) { if (f < 64) {
if (!(f & 7)) { if (!(f & 7)) {
@ -304,7 +304,7 @@ export class EvolutionPhase extends Phase {
this.scene.tweens.addCounter({ this.scene.tweens.addCounter({
repeat: 96, repeat: 96,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
if (f < 96) { if (f < 96) {
if (f < 6) { if (f < 6) {
@ -355,7 +355,7 @@ export class EvolutionPhase extends Phase {
this.scene.tweens.addCounter({ this.scene.tweens.addCounter({
repeat: 48, repeat: 48,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
if (!f) { if (!f) {
for (let i = 0; i < 16; i++) { for (let i = 0; i < 16; i++) {
@ -376,14 +376,14 @@ export class EvolutionPhase extends Phase {
this.scene.tweens.addCounter({ this.scene.tweens.addCounter({
repeat: 48, repeat: 48,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
if (!f) { if (!f) {
for (let i = 0; i < 8; i++) { for (let i = 0; i < 8; i++) {
this.doSprayParticle(i); this.doSprayParticle(i);
} }
} else if (f < 50) { } else if (f < 50) {
this.doSprayParticle(Utils.randInt(8)); this.doSprayParticle(randInt(8));
} }
f++; f++;
} }
@ -400,7 +400,7 @@ export class EvolutionPhase extends Phase {
const particleTimer = this.scene.tweens.addCounter({ const particleTimer = this.scene.tweens.addCounter({
repeat: -1, repeat: -1,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
updateParticle(); updateParticle();
} }
@ -437,7 +437,7 @@ export class EvolutionPhase extends Phase {
const particleTimer = this.scene.tweens.addCounter({ const particleTimer = this.scene.tweens.addCounter({
repeat: -1, repeat: -1,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
updateParticle(); updateParticle();
} }
@ -469,7 +469,7 @@ export class EvolutionPhase extends Phase {
const particleTimer = this.scene.tweens.addCounter({ const particleTimer = this.scene.tweens.addCounter({
repeat: -1, repeat: -1,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
updateParticle(); updateParticle();
} }
@ -499,12 +499,12 @@ export class EvolutionPhase extends Phase {
let f = 0; let f = 0;
let yOffset = 0; let yOffset = 0;
const speed = 3 - Utils.randInt(8); const speed = 3 - randInt(8);
const amp = 48 + Utils.randInt(64); const amp = 48 + randInt(64);
const particleTimer = this.scene.tweens.addCounter({ const particleTimer = this.scene.tweens.addCounter({
repeat: -1, repeat: -1,
duration: Utils.getFrameMs(1), duration: getFrameMs(1),
onRepeat: () => { onRepeat: () => {
updateParticle(); updateParticle();
} }

View File

@ -2,9 +2,9 @@ import BattleScene from "#app/battle-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 * as Utils from "#app/utils"; import { NumberHolder } from "#app/utils";
import { PlayerPartyMemberPokemonPhase } from "./player-party-member-pokemon-phase"; import { PlayerPartyMemberPokemonPhase } from "#phases/player-party-member-pokemon-phase";
import { LevelUpPhase } from "./level-up-phase"; import { LevelUpPhase } from "#phases/level-up-phase";
export class ExpPhase extends PlayerPartyMemberPokemonPhase { export class ExpPhase extends PlayerPartyMemberPokemonPhase {
private expValue: number; private expValue: number;
@ -19,7 +19,7 @@ export class ExpPhase extends PlayerPartyMemberPokemonPhase {
super.start(); super.start();
const pokemon = this.getPokemon(); const pokemon = this.getPokemon();
const exp = new Utils.NumberHolder(this.expValue); const exp = new NumberHolder(this.expValue);
this.scene.applyModifiers(ExpBoosterModifier, true, exp); this.scene.applyModifiers(ExpBoosterModifier, true, exp);
exp.value = Math.floor(exp.value); exp.value = Math.floor(exp.value);
this.scene.ui.showText(i18next.t("battle:expGain", { pokemonName: getPokemonNameWithAffix(pokemon), exp: exp.value }), null, () => { this.scene.ui.showText(i18next.t("battle:expGain", { pokemonName: getPokemonNameWithAffix(pokemon), exp: exp.value }), null, () => {

View File

@ -1,26 +1,33 @@
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { BattlerIndex, BattleType } from "#app/battle"; import { BattlerIndex, BattleType } from "#app/battle";
import { applyPostFaintAbAttrs, PostFaintAbAttr, applyPostKnockOutAbAttrs, PostKnockOutAbAttr, applyPostVictoryAbAttrs, PostVictoryAbAttr } from "#app/data/ability"; import {
applyPostFaintAbAttrs,
PostFaintAbAttr,
applyPostKnockOutAbAttrs,
PostKnockOutAbAttr,
applyPostVictoryAbAttrs,
PostVictoryAbAttr,
} from "#app/data/ability";
import { BattlerTagLapseType, DestinyBondTag } from "#app/data/battler-tags"; import { BattlerTagLapseType, DestinyBondTag } from "#app/data/battler-tags";
import { battleSpecDialogue } from "#app/data/dialogue"; import { battleSpecDialogue } from "#app/data/dialogue";
import { allMoves, PostVictoryStatStageChangeAttr } from "#app/data/move"; import { allMoves, PostVictoryStatStageChangeAttr } from "#app/data/move";
import { BattleSpec } from "#app/enums/battle-spec"; import { BattleSpec } from "#enums/battle-spec";
import { StatusEffect } from "#app/enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import Pokemon, { PokemonMove, EnemyPokemon, PlayerPokemon, HitResult } from "#app/field/pokemon"; import Pokemon, { PokemonMove, EnemyPokemon, PlayerPokemon, HitResult } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { PokemonInstantReviveModifier } from "#app/modifier/modifier"; import { PokemonInstantReviveModifier } from "#app/modifier/modifier";
import i18next from "i18next"; import i18next from "i18next";
import { DamagePhase } from "./damage-phase"; import { DamagePhase } from "#phases/damage-phase";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "#phases/pokemon-phase";
import { SwitchSummonPhase } from "./switch-summon-phase"; import { SwitchSummonPhase } from "#phases/switch-summon-phase";
import { ToggleDoublePositionPhase } from "./toggle-double-position-phase"; import { ToggleDoublePositionPhase } from "#phases/toggle-double-position-phase";
import { GameOverPhase } from "./game-over-phase"; import { GameOverPhase } from "#phases/game-over-phase";
import { SwitchPhase } from "./switch-phase"; import { SwitchPhase } from "#phases/switch-phase";
import { VictoryPhase } from "./victory-phase"; import { VictoryPhase } from "#phases/victory-phase";
import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms"; import { SpeciesFormChangeActiveTrigger } from "#app/data/pokemon-forms";
import { SwitchType } from "#enums/switch-type"; import { SwitchType } from "#enums/switch-type";
import { isNullOrUndefined } from "#app/utils"; import { isNullOrUndefined } from "#app/utils";
import { FRIENDSHIP_LOSS_FROM_FAINT } from "#app/data/balance/starters"; import { FRIENDSHIP_LOSS_FROM_FAINT } from "#balance/starters";
export class FaintPhase extends PokemonPhase { export class FaintPhase extends PokemonPhase {
/** /**

View File

@ -1,5 +1,5 @@
import Pokemon from "#app/field/pokemon"; import Pokemon from "#app/field/pokemon";
import { BattlePhase } from "./battle-phase"; import { BattlePhase } from "#phases/battle-phase";
type PokemonFunc = (pokemon: Pokemon) => void; type PokemonFunc = (pokemon: Pokemon) => void;

View File

@ -1,14 +1,14 @@
import BattleScene from "../battle-scene"; import BattleScene from "#app/battle-scene";
import * as Utils from "../utils"; import { fixedInt } from "#app/utils";
import { achvs } from "../system/achv"; import { achvs } from "#app/system/achv";
import { SpeciesFormChange, getSpeciesFormChangeMessage } from "../data/pokemon-forms"; import { SpeciesFormChange, getSpeciesFormChangeMessage } from "#app/data/pokemon-forms";
import { PlayerPokemon } from "../field/pokemon"; import { PlayerPokemon } from "#app/field/pokemon";
import { Mode } from "../ui/ui"; import { Mode } from "#app/ui/ui";
import PartyUiHandler from "../ui/party-ui-handler"; import PartyUiHandler from "#app/ui/party-ui-handler";
import { getPokemonNameWithAffix } from "../messages"; import { getPokemonNameWithAffix } from "#app/messages";
import { EndEvolutionPhase } from "./end-evolution-phase"; import { EndEvolutionPhase } from "#phases/end-evolution-phase";
import { EvolutionPhase } from "./evolution-phase"; import { EvolutionPhase } from "#phases/evolution-phase";
import { BattlerTagType } from "#app/enums/battler-tag-type"; import { BattlerTagType } from "#enums/battler-tag-type";
import { SpeciesFormKey } from "#enums/species-form-key"; import { SpeciesFormKey } from "#enums/species-form-key";
export class FormChangePhase extends EvolutionPhase { export class FormChangePhase extends EvolutionPhase {
@ -134,8 +134,8 @@ export class FormChangePhase extends EvolutionPhase {
this.scene.playSoundWithoutBgm(playEvolutionFanfare ? "evolution_fanfare" : "minor_fanfare"); this.scene.playSoundWithoutBgm(playEvolutionFanfare ? "evolution_fanfare" : "minor_fanfare");
transformedPokemon.destroy(); transformedPokemon.destroy();
this.scene.ui.showText(getSpeciesFormChangeMessage(this.pokemon, this.formChange, preName), null, () => this.end(), null, true, Utils.fixedInt(delay)); this.scene.ui.showText(getSpeciesFormChangeMessage(this.pokemon, this.formChange, preName), null, () => this.end(), null, true, fixedInt(delay));
this.scene.time.delayedCall(Utils.fixedInt(delay + 250), () => this.scene.playBgm()); this.scene.time.delayedCall(fixedInt(delay + 250), () => this.scene.playBgm());
}); });
}); });
} }

View File

@ -2,7 +2,7 @@ import BattleScene from "#app/battle-scene";
import { ModifierTypeFunc } from "#app/modifier/modifier-type"; import { ModifierTypeFunc } from "#app/modifier/modifier-type";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import i18next from "i18next"; import i18next from "i18next";
import { ModifierRewardPhase } from "./modifier-reward-phase"; import { ModifierRewardPhase } from "#phases/modifier-reward-phase";
export class GameOverModifierRewardPhase extends ModifierRewardPhase { export class GameOverModifierRewardPhase extends ModifierRewardPhase {
constructor(scene: BattleScene, modifierTypeFunc: ModifierTypeFunc) { constructor(scene: BattleScene, modifierTypeFunc: ModifierTypeFunc) {

View File

@ -2,24 +2,24 @@ import { clientSessionId } from "#app/account";
import { BattleType } from "#app/battle"; import { BattleType } from "#app/battle";
import BattleScene from "#app/battle-scene"; import BattleScene from "#app/battle-scene";
import { getCharVariantFromDialogue } from "#app/data/dialogue"; import { getCharVariantFromDialogue } from "#app/data/dialogue";
import { pokemonEvolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonEvolutions } from "#balance/pokemon-evolutions";
import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species"; import PokemonSpecies, { getPokemonSpecies } from "#app/data/pokemon-species";
import { trainerConfigs } from "#app/data/trainer-config"; import { trainerConfigs } from "#app/data/trainer-config";
import Pokemon from "#app/field/pokemon"; import Pokemon from "#app/field/pokemon";
import { modifierTypes } from "#app/modifier/modifier-type"; import { modifierTypes } from "#app/modifier/modifier-type";
import { BattlePhase } from "#app/phases/battle-phase"; import { BattlePhase } from "#phases/battle-phase";
import { CheckSwitchPhase } from "#app/phases/check-switch-phase"; import { CheckSwitchPhase } from "#phases/check-switch-phase";
import { EncounterPhase } from "#app/phases/encounter-phase"; import { EncounterPhase } from "#phases/encounter-phase";
import { EndCardPhase } from "#app/phases/end-card-phase"; import { EndCardPhase } from "#phases/end-card-phase";
import { GameOverModifierRewardPhase } from "#app/phases/game-over-modifier-reward-phase"; import { GameOverModifierRewardPhase } from "#phases/game-over-modifier-reward-phase";
import { PostGameOverPhase } from "#app/phases/post-game-over-phase"; import { PostGameOverPhase } from "#phases/post-game-over-phase";
import { RibbonModifierRewardPhase } from "#app/phases/ribbon-modifier-reward-phase"; import { RibbonModifierRewardPhase } from "#phases/ribbon-modifier-reward-phase";
import { SummonPhase } from "#app/phases/summon-phase"; import { SummonPhase } from "#phases/summon-phase";
import { UnlockPhase } from "#app/phases/unlock-phase"; import { UnlockPhase } from "#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 { Mode } from "#app/ui/ui";
import * as Utils from "#app/utils"; import { isLocal, apiFetch } from "#app/utils";
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";
@ -176,8 +176,8 @@ export class GameOverPhase extends BattlePhase {
If Online, execute apiFetch as intended If Online, execute apiFetch as intended
If Offline, execute offlineNewClear(), a localStorage implementation of newClear daily run checks */ If Offline, execute offlineNewClear(), a localStorage implementation of newClear daily run checks */
if (this.victory) { if (this.victory) {
if (!Utils.isLocal) { if (!isLocal) {
Utils.apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true) apiFetch(`savedata/session/newclear?slot=${this.scene.sessionSlotId}&clientSessionId=${clientSessionId}`, true)
.then(response => response.json()) .then(response => response.json())
.then(newClear => doGameOver(newClear)); .then(newClear => doGameOver(newClear));
} else { } else {

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