diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 21ddc902691..b4435ec5b26 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -2,7 +2,7 @@ import Phaser from "phaser"; import UI from "./ui/ui"; import { NextEncounterPhase, NewBiomeEncounterPhase, SelectBiomePhase, MessagePhase, TurnInitPhase, ReturnPhase, LevelCapPhase, ShowTrainerPhase, LoginPhase, MovePhase, TitlePhase, SwitchPhase } from "./phases"; import Pokemon, { PlayerPokemon, EnemyPokemon } from "./field/pokemon"; -import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies, initSpecies } from "./data/pokemon-species"; +import PokemonSpecies, { PokemonSpeciesFilter, allSpecies, getPokemonSpecies } from "./data/pokemon-species"; import * as Utils from "./utils"; import { Modifier, ModifierBar, ConsumablePokemonModifier, ConsumableModifier, PokemonHpRestoreModifier, HealingBoosterModifier, PersistentModifier, PokemonHeldItemModifier, ModifierPredicate, DoubleBattleChanceBoosterModifier, FusePokemonModifier, PokemonFormChangeItemModifier, TerastallizeModifier, overrideModifiers, overrideHeldItems } from "./modifier/modifier"; import { PokeballType } from "./data/pokeball"; @@ -15,10 +15,9 @@ import { GameData, PlayerGender } from "./system/game-data"; import { TextStyle, addTextObject } from "./ui/text"; import { Moves } from "./data/enums/moves"; import { allMoves } from "./data/move"; -import { initMoves } from "./data/move"; import { ModifierPoolType, getDefaultModifierTypeForTier, getEnemyModifierTypesForWave, getLuckString, getLuckTextTint, getModifierPoolForType, getPartyLuckValue } from "./modifier/modifier-type"; import AbilityBar from "./ui/ability-bar"; -import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs, initAbilities } from "./data/ability"; +import { BlockItemTheftAbAttr, DoubleBattleChanceAbAttr, IncrementMovePriorityAbAttr, applyAbAttrs } from "./data/ability"; import { allAbilities } from "./data/ability"; import Battle, { BattleType, FixedBattleConfig, fixedBattles } from "./battle"; import { GameMode, GameModes, gameModes } from "./game-mode"; @@ -187,11 +186,6 @@ export default class BattleScene extends SceneBase { constructor() { super("battle"); - - initSpecies(); - initMoves(); - initAbilities(); - this.phaseQueue = []; this.phaseQueuePrepend = []; this.phaseQueuePrependSpliceIndex = -1; diff --git a/src/data/biomes.ts b/src/data/biomes.ts index fc8f20db586..01e6233978c 100644 --- a/src/data/biomes.ts +++ b/src/data/biomes.ts @@ -5,7 +5,7 @@ import beautify from "json-beautify"; import { TrainerType } from "./enums/trainer-type"; import { TimeOfDay } from "./enums/time-of-day"; import { Biome } from "./enums/biome"; -import { SpeciesFormEvolution } from "./pokemon-evolutions"; +import {pokemonEvolutions, SpeciesFormEvolution} from "./pokemon-evolutions"; export function getBiomeName(biome: Biome | -1) { if (biome === -1) { @@ -2012,7 +2012,7 @@ export const biomeTrainerPools: BiomeTrainerPools = { } }; -{ +export function initBiomes() { const pokemonBiomes = [ [ Species.BULBASAUR, Type.GRASS, Type.POISON, [ [ Biome.GRASS, BiomePoolTier.RARE ] @@ -7677,130 +7677,126 @@ export const biomeTrainerPools: BiomeTrainerPools = { 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 ]; - import("./pokemon-evolutions").then(pe => { - const pokemonEvolutions = pe.pokemonEvolutions; - for (const biome of Utils.getEnumValues(Biome)) { - biomePokemonPools[biome] = {}; - biomeTrainerPools[biome] = {}; + for (const biome of Utils.getEnumValues(Biome)) { + biomePokemonPools[biome] = {}; + biomeTrainerPools[biome] = {}; - for (const tier of Utils.getEnumValues(BiomePoolTier)) { - biomePokemonPools[biome][tier] = {}; - biomeTrainerPools[biome][tier] = []; + for (const tier of Utils.getEnumValues(BiomePoolTier)) { + biomePokemonPools[biome][tier] = {}; + biomeTrainerPools[biome][tier] = []; - for (const tod of Utils.getEnumValues(TimeOfDay)) { - biomePokemonPools[biome][tier][tod] = []; - } + for (const tod of Utils.getEnumValues(TimeOfDay)) { + biomePokemonPools[biome][tier][tod] = []; } } + } - for (const pb of pokemonBiomes) { - const speciesId = pb[0] as Species; - const biomeEntries = pb[3] as (Biome | BiomePoolTier)[][]; + for (const pb of pokemonBiomes) { + const speciesId = pb[0] as Species; + const biomeEntries = pb[3] as (Biome | BiomePoolTier)[][]; - const speciesEvolutions: SpeciesFormEvolution[] = pokemonEvolutions.hasOwnProperty(speciesId) - ? pokemonEvolutions[speciesId] - : []; + const speciesEvolutions: SpeciesFormEvolution[] = pokemonEvolutions.hasOwnProperty(speciesId) + ? pokemonEvolutions[speciesId] + : []; - if (!biomeEntries.filter(b => b[0] !== Biome.END).length && !speciesEvolutions.filter(es => !!((pokemonBiomes.find(p => p[0] === es.speciesId))[3] as any[]).filter(b => b[0] !== Biome.END).length).length) { - uncatchableSpecies.push(speciesId); - } - - for (const b of biomeEntries) { - const biome = b[0]; - const tier = b[1]; - const timesOfDay = b.length > 2 - ? Array.isArray(b[2]) - ? b[2] - : [ b[2] ] - : [ TimeOfDay.ALL ]; - - for (const tod of timesOfDay) { - if (!biomePokemonPools.hasOwnProperty(biome) || !biomePokemonPools[biome].hasOwnProperty(tier) || !biomePokemonPools[biome][tier].hasOwnProperty(tod)) { - continue; - } - - const biomeTierPool = biomePokemonPools[biome][tier][tod]; - - let treeIndex = -1; - let arrayIndex = 0; - - for (let t = 0; t < biomeTierPool.length; t++) { - const existingSpeciesIds = biomeTierPool[t] as unknown as Species[]; - for (let es = 0; es < existingSpeciesIds.length; es++) { - const existingSpeciesId = existingSpeciesIds[es]; - if (pokemonEvolutions.hasOwnProperty(existingSpeciesId) && (pokemonEvolutions[existingSpeciesId] as SpeciesFormEvolution[]).find(ese => ese.speciesId === speciesId)) { - treeIndex = t; - arrayIndex = es + 1; - break; - } else if (speciesEvolutions && speciesEvolutions.find(se => se.speciesId === existingSpeciesId)) { - treeIndex = t; - arrayIndex = es; - break; - } - } - if (treeIndex > -1) { - break; - } - } - - if (treeIndex > -1) { - (biomeTierPool[treeIndex] as unknown as Species[]).splice(arrayIndex, 0, speciesId); - } else { - (biomeTierPool as unknown as Species[][]).push([ speciesId ]); - } - } - } + if (!biomeEntries.filter(b => b[0] !== Biome.END).length && !speciesEvolutions.filter(es => !!((pokemonBiomes.find(p => p[0] === es.speciesId))[3] as any[]).filter(b => b[0] !== Biome.END).length).length) { + uncatchableSpecies.push(speciesId); } - for (const b of Object.keys(biomePokemonPools)) { - for (const t of Object.keys(biomePokemonPools[b])) { - const tier = parseInt(t) as BiomePoolTier; - for (const tod of Object.keys(biomePokemonPools[b][t])) { - const biomeTierTimePool = biomePokemonPools[b][t][tod]; - for (let e = 0; e < biomeTierTimePool.length; e++) { - const entry = biomeTierTimePool[e]; - if (entry.length === 1) { - biomeTierTimePool[e] = entry[0]; - } else { - const newEntry = { - 1: [ entry[0] ] - }; - for (let s = 1; s < entry.length; s++) { - const speciesId = entry[s]; - const prevolution = entry.map(s => pokemonEvolutions[s]).flat().find(e => e && e.speciesId === speciesId); - const level = prevolution.level - (prevolution.level === 1 ? 1 : 0) + (prevolution.wildDelay * 10) - (tier >= BiomePoolTier.BOSS ? 10 : 0); - if (!newEntry.hasOwnProperty(level)) { - newEntry[level] = [ speciesId ]; - } else { - newEntry[level].push(speciesId); - } - } - biomeTierTimePool[e] = newEntry; - } - } - } - } - } + for (const b of biomeEntries) { + const biome = b[0]; + const tier = b[1]; + const timesOfDay = b.length > 2 + ? Array.isArray(b[2]) + ? b[2] + : [ b[2] ] + : [ TimeOfDay.ALL ]; - for (const tb of trainerBiomes) { - const trainerType = tb[0] as TrainerType; - const biomeEntries = tb[1] as BiomePoolTier[][]; - - for (const b of biomeEntries) { - const biome = b[0]; - const tier = b[1]; - - if (!biomeTrainerPools.hasOwnProperty(biome) || !biomeTrainerPools[biome].hasOwnProperty(tier)) { + for (const tod of timesOfDay) { + if (!biomePokemonPools.hasOwnProperty(biome) || !biomePokemonPools[biome].hasOwnProperty(tier) || !biomePokemonPools[biome][tier].hasOwnProperty(tod)) { continue; } - const biomeTierPool = biomeTrainerPools[biome][tier]; - biomeTierPool.push(trainerType); + const biomeTierPool = biomePokemonPools[biome][tier][tod]; + + let treeIndex = -1; + let arrayIndex = 0; + + for (let t = 0; t < biomeTierPool.length; t++) { + const existingSpeciesIds = biomeTierPool[t] as unknown as Species[]; + for (let es = 0; es < existingSpeciesIds.length; es++) { + const existingSpeciesId = existingSpeciesIds[es]; + if (pokemonEvolutions.hasOwnProperty(existingSpeciesId) && (pokemonEvolutions[existingSpeciesId] as SpeciesFormEvolution[]).find(ese => ese.speciesId === speciesId)) { + treeIndex = t; + arrayIndex = es + 1; + break; + } else if (speciesEvolutions && speciesEvolutions.find(se => se.speciesId === existingSpeciesId)) { + treeIndex = t; + arrayIndex = es; + break; + } + } + if (treeIndex > -1) { + break; + } + } + + if (treeIndex > -1) { + (biomeTierPool[treeIndex] as unknown as Species[]).splice(arrayIndex, 0, speciesId); + } else { + (biomeTierPool as unknown as Species[][]).push([ speciesId ]); + } } } + } + + for (const b of Object.keys(biomePokemonPools)) { + for (const t of Object.keys(biomePokemonPools[b])) { + const tier = parseInt(t) as BiomePoolTier; + for (const tod of Object.keys(biomePokemonPools[b][t])) { + const biomeTierTimePool = biomePokemonPools[b][t][tod]; + for (let e = 0; e < biomeTierTimePool.length; e++) { + const entry = biomeTierTimePool[e]; + if (entry.length === 1) { + biomeTierTimePool[e] = entry[0]; + } else { + const newEntry = { + 1: [ entry[0] ] + }; + for (let s = 1; s < entry.length; s++) { + const speciesId = entry[s]; + const prevolution = entry.map(s => pokemonEvolutions[s]).flat().find(e => e && e.speciesId === speciesId); + const level = prevolution.level - (prevolution.level === 1 ? 1 : 0) + (prevolution.wildDelay * 10) - (tier >= BiomePoolTier.BOSS ? 10 : 0); + if (!newEntry.hasOwnProperty(level)) { + newEntry[level] = [ speciesId ]; + } else { + newEntry[level].push(speciesId); + } + } + biomeTierTimePool[e] = newEntry; + } + } + } + } + } + + for (const tb of trainerBiomes) { + const trainerType = tb[0] as TrainerType; + const biomeEntries = tb[1] as BiomePoolTier[][]; + + for (const b of biomeEntries) { + const biome = b[0]; + const tier = b[1]; + + if (!biomeTrainerPools.hasOwnProperty(biome) || !biomeTrainerPools[biome].hasOwnProperty(tier)) { + continue; + } + + const biomeTierPool = biomeTrainerPools[biome][tier]; + biomeTierPool.push(trainerType); + } + } - //outputPools(); - }); // used in a commented code // eslint-disable-next-line @typescript-eslint/no-unused-vars diff --git a/src/data/egg-moves.ts b/src/data/egg-moves.ts index dfe5dba477e..bed989849d9 100644 --- a/src/data/egg-moves.ts +++ b/src/data/egg-moves.ts @@ -608,9 +608,11 @@ function parseEggMoves(content: string): void { console.log(output); } -const eggMovesStr = ""; -if (eggMovesStr) { - setTimeout(() => { - parseEggMoves(eggMovesStr); - }, 1000); +export function initEggMoves() { + const eggMovesStr = ""; + if (eggMovesStr) { + setTimeout(() => { + parseEggMoves(eggMovesStr); + }, 1000); + } } diff --git a/src/data/pokemon-evolutions.ts b/src/data/pokemon-evolutions.ts index 3465b5bb152..15193327547 100644 --- a/src/data/pokemon-evolutions.ts +++ b/src/data/pokemon-evolutions.ts @@ -1619,7 +1619,7 @@ interface PokemonPrevolutions { export const pokemonPrevolutions: PokemonPrevolutions = {}; -{ +export function initPokemonPrevolutions(): void { const megaFormKeys = [ SpeciesFormKey.MEGA, "", SpeciesFormKey.MEGA_X, "", SpeciesFormKey.MEGA_Y ].map(sfk => sfk as string); const prevolutionKeys = Object.keys(pokemonEvolutions); prevolutionKeys.forEach(pk => { diff --git a/src/data/pokemon-forms.ts b/src/data/pokemon-forms.ts index 63bd5c08810..3a3971d4fa1 100644 --- a/src/data/pokemon-forms.ts +++ b/src/data/pokemon-forms.ts @@ -729,7 +729,7 @@ export const pokemonFormChanges: PokemonFormChanges = { ] }; -{ +export function initPokemonForms() { const formChangeKeys = Object.keys(pokemonFormChanges); formChangeKeys.forEach(pk => { const formChanges = pokemonFormChanges[pk]; diff --git a/src/data/trainer-config.ts b/src/data/trainer-config.ts index 518cc31fd5b..1dcf0efa7b8 100644 --- a/src/data/trainer-config.ts +++ b/src/data/trainer-config.ts @@ -1051,6 +1051,6 @@ export const trainerConfigs: TrainerConfigs = { }), }; -(function () { +export function initTrainerTypeDialogue() { initTrainerTypeDialogue(); -})(); +} diff --git a/src/loading-scene.ts b/src/loading-scene.ts index b14b0527569..975175e9d25 100644 --- a/src/loading-scene.ts +++ b/src/loading-scene.ts @@ -9,6 +9,14 @@ import { WindowVariant, getWindowVariantSuffix } from "./ui/ui-theme"; import { isMobile } from "./touch-controls"; import * as Utils from "./utils"; import { initI18n } from "./plugins/i18n"; +import {initStatsKeys} from "#app/ui/game-stats-ui-handler"; +import {initPokemonPrevolutions} from "#app/data/pokemon-evolutions"; +import {initBiomes} from "#app/data/biomes"; +import {initEggMoves} from "#app/data/egg-moves"; +import {initPokemonForms} from "#app/data/pokemon-forms"; +import {initSpecies} from "#app/data/pokemon-species"; +import {initMoves} from "#app/data/move"; +import {initAbilities} from "#app/data/ability"; export class LoadingScene extends SceneBase { constructor() { @@ -284,6 +292,15 @@ export class LoadingScene extends SceneBase { this.load.plugin("rextexteditplugin", "https://raw.githubusercontent.com/rexrainbow/phaser3-rex-notes/master/dist/rextexteditplugin.min.js", true); this.loadLoadingScreen(); + + initStatsKeys(); + initPokemonPrevolutions(); + initBiomes(); + initEggMoves(); + initPokemonForms(); + initSpecies(); + initMoves(); + initAbilities(); } loadLoadingScreen() { diff --git a/src/test/achievement.test.ts b/src/test/achievement.test.ts new file mode 100644 index 00000000000..a27c2d90154 --- /dev/null +++ b/src/test/achievement.test.ts @@ -0,0 +1,9 @@ +import {describe, expect, it} from "vitest"; +import {MoneyAchv} from "#app/system/achv"; + +describe("check some Achievement related stuff", () => { + it ("should check Achievement creation", () => { + const ach = new MoneyAchv("Achievement", 1000, null, 100); + expect(ach.name).toBe("Achievement"); + }); +}); diff --git a/src/test/debugImports.test.ts b/src/test/debugImports.test.ts new file mode 100644 index 00000000000..c164813a3cd --- /dev/null +++ b/src/test/debugImports.test.ts @@ -0,0 +1,35 @@ +import { describe, expect, it} from "vitest"; +import {initStatsKeys} from "#app/ui/game-stats-ui-handler"; + +async function importModule() { + try { + initStatsKeys(); + const { PokemonMove } = await import("#app/field/pokemon"); + const { Species } = await import("#app/data/enums/species"); + return { + PokemonMove, + Species, + }; + // Dynamically import the module + } catch (error) { + // Log the error stack trace + console.error("Error during import:", error.stack); + // Rethrow the error to ensure the test fails + throw error; + } +} + +describe("tests to debug the import, with trace", () => { + it("import PokemonMove module", async () => { + const module = await importModule(); + // Example assertion + expect(module.PokemonMove).toBeDefined(); + }); + + it("import Species module", async () => { + const module = await importModule(); + // Example assertion + expect(module.Species).toBeDefined(); + }); +}); + diff --git a/src/test/pokemon.test.ts b/src/test/pokemon.test.ts new file mode 100644 index 00000000000..d1f7da45256 --- /dev/null +++ b/src/test/pokemon.test.ts @@ -0,0 +1,57 @@ +import {describe, expect, it} from "vitest"; +import {getPokemonSpecies} from "#app/data/pokemon-species"; +import {PokemonMove} from "#app/field/pokemon"; +import {Species} from "#app/data/enums/species"; +import {Moves} from "#app/data/enums/moves"; +import PokemonData from "#app/system/pokemon-data"; + +describe("some tests related to PokemonData and Species", () => { + it("should create a species", () => { + const species = getPokemonSpecies(Species.MEW); + expect(species).not.toBeNull(); + }); + + it("should create a pokemon", () => { + const pokemon = new PokemonData({ + species: Species.MEW, + level: 1, + }); + expect(pokemon).not.toBeNull(); + expect(pokemon.level).toEqual(1); + expect(pokemon.species).toEqual(Species.MEW); + }); + + it("should generate a moveset", () => { + const pokemon = new PokemonData({ + species: Species.MEW, + level: 1, + }); + expect(pokemon.moveset[0].moveId).toBe(Moves.TACKLE); + expect(pokemon.moveset[1].moveId).toBe(Moves.GROWL); + }); + + it("should create an ennemypokemon", () => { + const ennemyPokemon = new PokemonData({ + species: Species.MEWTWO, + level: 100, + }); + expect(ennemyPokemon).not.toBeNull(); + expect(ennemyPokemon.level).toEqual(100); + expect(ennemyPokemon.species).toEqual(Species.MEWTWO); + }); + + it("should create an ennemypokemon with specified moveset", () => { + const ennemyPokemon = new PokemonData({ + species: Species.MEWTWO, + level: 100, + moveset: [ + new PokemonMove(Moves.ACID), + new PokemonMove(Moves.ACROBATICS), + new PokemonMove(Moves.FOCUS_ENERGY), + ] + }); + expect(ennemyPokemon.moveset[0].moveId).toBe(Moves.ACID); + expect(ennemyPokemon.moveset[1].moveId).toBe(Moves.ACROBATICS); + expect(ennemyPokemon.moveset[2].moveId).toBe(Moves.FOCUS_ENERGY); + }); +}); diff --git a/src/test/vitest.setup.ts b/src/test/vitest.setup.ts index d0141ca9fc3..f17a16caf14 100644 --- a/src/test/vitest.setup.ts +++ b/src/test/vitest.setup.ts @@ -1,2 +1,19 @@ import "vitest-canvas-mock"; import "#app/test/phaser.setup"; +import {initStatsKeys} from "#app/ui/game-stats-ui-handler"; +import {initPokemonPrevolutions} from "#app/data/pokemon-evolutions"; +import {initBiomes} from "#app/data/biomes"; +import {initEggMoves} from "#app/data/egg-moves"; +import {initPokemonForms} from "#app/data/pokemon-forms"; +import {initSpecies} from "#app/data/pokemon-species"; +import {initMoves} from "#app/data/move"; +import {initAbilities} from "#app/data/ability"; + +initStatsKeys(); +initPokemonPrevolutions(); +initBiomes(); +initEggMoves(); +initPokemonForms(); +initSpecies(); +initMoves(); +initAbilities(); diff --git a/src/ui/game-stats-ui-handler.ts b/src/ui/game-stats-ui-handler.ts index 2293cd7cf46..b4823010734 100644 --- a/src/ui/game-stats-ui-handler.ts +++ b/src/ui/game-stats-ui-handler.ts @@ -230,7 +230,7 @@ export default class GameStatsUiHandler extends UiHandler { } } -(function () { +export function initStatsKeys() { const statKeys = Object.keys(displayStats); for (const key of statKeys) { @@ -256,4 +256,4 @@ export default class GameStatsUiHandler extends UiHandler { (displayStats[key] as DisplayStat).label = Utils.toReadableString(`${splittableKey[0].toUpperCase()}${splittableKey.slice(1)}`); } } -})(); +} diff --git a/vitest.config.js b/vitest.config.js index 5a7babd4232..c73476431dd 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -14,6 +14,7 @@ export default defineConfig(({ mode }) => { } }, threads: false, + trace: true, environmentOptions: { jsdom: { resources: 'usable',