pokerogue/src/system/version_migration/versions/v1_7_0.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

86 lines
3.0 KiB
TypeScript

import type { SessionSaveMigrator } from "#app/@types/SessionSaveMigrator";
import type { SystemSaveMigrator } from "#app/@types/SystemSaveMigrator";
import { getPokemonSpeciesForm } from "#app/data/pokemon-species";
import { getPokemonSpecies } from "#app/utils/pokemon-utils";
import { globalScene } from "#app/global-scene";
import type { SessionSaveData, SystemSaveData } from "#app/system/game-data";
import { DexAttr } from "#enums/dex-attr";
import { isNullOrUndefined } from "#app/utils/common";
/**
* If a starter is caught, but the only forms registered as caught are not starterSelectable,
* unlock the default form.
* @param data - {@linkcode SystemSaveData}
*/
const migrateUnselectableForms: SystemSaveMigrator = {
version: "1.7.0",
migrate: (data: SystemSaveData): void => {
if (data.starterData && data.dexData) {
Object.keys(data.starterData).forEach(sd => {
const caughtAttr = data.dexData[sd]?.caughtAttr;
const speciesNumber = Number(sd);
if (!speciesNumber) {
// An unknown bug at some point in time caused some accounts to have starter data for pokedex number 0 which crashes
return;
}
const species = getPokemonSpecies(speciesNumber);
if (caughtAttr && species.forms?.length > 1) {
const selectableForms = species.forms.filter(
(form, formIndex) => form.isStarterSelectable && caughtAttr & globalScene.gameData.getFormAttr(formIndex),
);
if (selectableForms.length === 0) {
data.dexData[sd].caughtAttr += DexAttr.DEFAULT_FORM;
}
}
});
}
},
};
export const systemMigrators: Readonly<SystemSaveMigrator[]> = [migrateUnselectableForms] as const;
const migrateTera: SessionSaveMigrator = {
version: "1.7.0",
migrate: (data: SessionSaveData): void => {
for (let i = 0; i < data.modifiers.length; ) {
if (data.modifiers[i].className === "TerastallizeModifier") {
data.party.forEach(p => {
if (p.id === data.modifiers[i].args[0]) {
p.teraType = data.modifiers[i].args[1];
}
});
data.modifiers.splice(i, 1);
} else {
i++;
}
}
for (let i = 0; i < data.enemyModifiers.length; ) {
if (data.enemyModifiers[i].className === "TerastallizeModifier") {
data.enemyParty.forEach(p => {
if (p.id === data.enemyModifiers[i].args[0]) {
p.teraType = data.enemyModifiers[i].args[1];
}
});
data.enemyModifiers.splice(i, 1);
} else {
i++;
}
}
data.party.forEach(p => {
if (isNullOrUndefined(p.teraType)) {
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
}
});
data.enemyParty.forEach(p => {
if (isNullOrUndefined(p.teraType)) {
p.teraType = getPokemonSpeciesForm(p.species, p.formIndex).type1;
}
});
},
};
export const sessionMigrators: Readonly<SessionSaveMigrator[]> = [migrateTera] as const;