pokerogue/test/testUtils/gameManagerUtils.ts
AJ Fontaine e3108603e3
[Refactor] Rework evolution conditions and descriptions (#5679)
* Refactor evo conditions and descriptions

* Fix test

* Fix Shedinja

* Simplify Gimmighoul evolution

* Primeape and Stantler evolve by using their move 10 times

* Basculin white stripe evolves by taking 294 recoil damage

* Primeape and Stantler use modifiers for tracking

* Basculin uses modifier too

* Remove evo count from pokemon data

* No more evo counter data, Gallade/Froslass

* Fix allmoves import

* Clamperl

* Struggle shouldn't count for Basc recoil

* Change to nicer type

* Apply Benjie's suggestions

Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com>

* Address formatting

* Undo new evolution changes

* Remove unused imports

* Fix speciesid

* Fixed up descriptions a little

* Change a key name

* Fix Gimmighoul

* Apply Biome

* Apply Biome unsafe fixes

* Review suggestions

- Convert `EvoCondKey` enum to `const` object

- Use early returns in `SpeciesEvolutionCondition#description`
and `SpeciesFormEvolution#description`

- Replace `!!x.find` with `x.some`
and `y.indexOf() > -1` with `y.includes()`

- Implement `coerceArray`

- Fix Shelmet evolution condition
checking for Shelmet and not Karrablast

- Remove unnecessary type casting in `battle-scene.ts`

* Remove leftover enforce func loop

* Fix circular imports issue

- `getPokemonSpecies` moved to `src/utils/pokemon-utils.ts`
- `allSpecies` moved to `src/data/data-lists.ts`

---------

Co-authored-by: Sirz Benjie <142067137+SirzBenjie@users.noreply.github.com>
Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
2025-06-16 05:57:51 -07:00

137 lines
4.9 KiB
TypeScript

import Battle from "#app/battle";
import { BattleType } from "#enums/battle-type";
import type BattleScene from "#app/battle-scene";
import { getDailyRunStarters } from "#app/data/daily-run";
import { Gender } from "#app/data/gender";
import { getPokemonSpeciesForm } from "#app/data/pokemon-species";
import { getPokemonSpecies } from "#app/utils/pokemon-utils";
import { PlayerPokemon } from "#app/field/pokemon";
import { getGameMode } from "#app/game-mode";
import { GameModes } from "#enums/game-modes";
import type { StarterMoveset } from "#app/system/game-data";
import type { Starter } from "#app/ui/starter-select-ui-handler";
import { MoveId } from "#enums/move-id";
import type { SpeciesId } from "#enums/species-id";
/** Function to convert Blob to string */
export function blobToString(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
resolve(reader.result);
};
reader.onerror = () => {
reject(new Error("Error reading Blob as string"));
};
reader.readAsText(blob);
});
}
export function holdOn(ms: number) {
return new Promise(resolve => setTimeout(resolve, ms));
}
export function generateStarter(scene: BattleScene, species?: SpeciesId[]): Starter[] {
const seed = "test";
const starters = getTestRunStarters(seed, species);
const startingLevel = scene.gameMode.getStartingLevel();
for (const starter of starters) {
const starterProps = scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr);
const starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0));
const starterGender =
starter.species.malePercent !== null ? (!starterProps.female ? Gender.MALE : Gender.FEMALE) : Gender.GENDERLESS;
const starterPokemon = scene.addPlayerPokemon(
starter.species,
startingLevel,
starter.abilityIndex,
starterFormIndex,
starterGender,
starterProps.shiny,
starterProps.variant,
undefined,
starter.nature,
);
const moveset: MoveId[] = [];
starterPokemon.moveset.forEach(move => {
moveset.push(move!.getMove().id);
});
starter.moveset = moveset as StarterMoveset;
}
return starters;
}
function getTestRunStarters(seed: string, species?: SpeciesId[]): Starter[] {
if (!species) {
return getDailyRunStarters(seed);
}
const starters: Starter[] = [];
const startingLevel = getGameMode(GameModes.CLASSIC).getStartingLevel();
for (const specie of species) {
const starterSpeciesForm = getPokemonSpeciesForm(specie, 0);
const starterSpecies = getPokemonSpecies(starterSpeciesForm.speciesId);
const pokemon = new PlayerPokemon(starterSpecies, startingLevel, undefined, 0);
const starter: Starter = {
species: starterSpecies,
dexAttr: pokemon.getDexAttr(),
abilityIndex: pokemon.abilityIndex,
passive: false,
nature: pokemon.getNature(),
pokerus: pokemon.pokerus,
};
starters.push(starter);
}
return starters;
}
export function waitUntil(truth): Promise<unknown> {
return new Promise(resolve => {
const interval = setInterval(() => {
if (truth()) {
clearInterval(interval);
resolve(true);
}
}, 1000);
});
}
/** Get the index of `move` from the moveset of the pokemon on the player's field at location `pokemonIndex`. */
export function getMovePosition(scene: BattleScene, pokemonIndex: 0 | 1, move: MoveId): number {
const playerPokemon = scene.getPlayerField()[pokemonIndex];
const moveSet = playerPokemon.getMoveset();
const index = moveSet.findIndex(m => m.moveId === move && m.ppUsed < m.getMovePp());
console.log(`Move position for ${MoveId[move]} (=${move}):`, index);
return index;
}
/**
* Useful for populating party, wave index, etc. without having to spin up and run through an entire EncounterPhase
*/
export function initSceneWithoutEncounterPhase(scene: BattleScene, species?: SpeciesId[]): void {
const starters = generateStarter(scene, species);
starters.forEach(starter => {
const starterProps = scene.gameData.getSpeciesDexAttrProps(starter.species, starter.dexAttr);
const starterFormIndex = Math.min(starterProps.formIndex, Math.max(starter.species.forms.length - 1, 0));
const starterGender = Gender.MALE;
const starterIvs = scene.gameData.dexData[starter.species.speciesId].ivs.slice(0);
const starterPokemon = scene.addPlayerPokemon(
starter.species,
scene.gameMode.getStartingLevel(),
starter.abilityIndex,
starterFormIndex,
starterGender,
starterProps.shiny,
starterProps.variant,
starterIvs,
starter.nature,
);
starter.moveset && starterPokemon.tryPopulateMoveset(starter.moveset);
scene.getPlayerParty().push(starterPokemon);
});
scene.currentBattle = new Battle(getGameMode(GameModes.CLASSIC), 5, BattleType.WILD, undefined, false);
}