mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-02 06:22:15 +02:00
Fixed migrate script, re-added deprecated attributes out of necessity
This commit is contained in:
parent
9e65d0a07b
commit
68adbcbe83
@ -7,17 +7,21 @@ import type { Nature } from "#enums/nature";
|
||||
* Includes abilities, nature, changed types, etc.
|
||||
*/
|
||||
export class CustomPokemonData {
|
||||
public spriteScale: number;
|
||||
public spriteScale = 1;
|
||||
public ability: Abilities | -1;
|
||||
public passive: Abilities | -1;
|
||||
public nature: Nature | -1;
|
||||
public types: PokemonType[];
|
||||
/** Deprecated but needed for session save migration */
|
||||
// TODO: Remove this once pre-session migration is implemented
|
||||
public hitsRecCount: number | null = null;
|
||||
|
||||
constructor(data?: CustomPokemonData | Partial<CustomPokemonData>) {
|
||||
this.spriteScale = data?.spriteScale ?? -1;
|
||||
this.spriteScale = data?.spriteScale ?? 1;
|
||||
this.ability = data?.ability ?? -1;
|
||||
this.passive = data?.passive ?? -1;
|
||||
this.nature = data?.nature ?? -1;
|
||||
this.types = data?.types ?? [];
|
||||
this.hitsRecCount = data?.hitsRecCount ?? null;
|
||||
}
|
||||
}
|
||||
|
@ -1183,12 +1183,10 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
formKey === "ruchbah-starmobile" ||
|
||||
formKey === "caph-starmobile"
|
||||
) {
|
||||
// G-Max and starmobiles have flat 1.5x scale
|
||||
return 1.5;
|
||||
}
|
||||
if (this.customPokemonData.spriteScale > 0) {
|
||||
return this.customPokemonData.spriteScale;
|
||||
}
|
||||
return 1;
|
||||
return this.customPokemonData.spriteScale;
|
||||
}
|
||||
|
||||
/** Resets the pokemon's field sprite properties, including position, alpha, and scale */
|
||||
|
@ -1194,13 +1194,18 @@ export class GameData {
|
||||
}
|
||||
}
|
||||
|
||||
// load modifier data
|
||||
|
||||
if (globalScene.modifiers.length) {
|
||||
console.warn("Existing modifiers not cleared on session load, deleting...");
|
||||
globalScene.modifiers = [];
|
||||
}
|
||||
for (const modifierData of sessionData.modifiers) {
|
||||
const modifier = modifierData.toModifier(Modifier[modifierData.className]);
|
||||
if (modifier) {
|
||||
globalScene.addModifier(modifier, true);
|
||||
}
|
||||
}
|
||||
|
||||
globalScene.updateModifiers(true);
|
||||
|
||||
for (const enemyModifierData of sessionData.enemyModifiers) {
|
||||
@ -1338,12 +1343,12 @@ export class GameData {
|
||||
}
|
||||
|
||||
parseSessionData(dataStr: string): SessionSaveData {
|
||||
// TODO: Add add `null`/`undefined` to the corresponding type signatures for this
|
||||
// TODO: Add `null`/`undefined` to the corresponding type signatures for this
|
||||
// (or prevent them from being null)
|
||||
// If the value is able to *not exist*, it should say so in the code
|
||||
|
||||
const sessionData = JSON.parse(dataStr, (k: string, v: any) => {
|
||||
// TODO: Move this into migrate script
|
||||
// TODO: Add pre-parse migrate scripts
|
||||
switch (k) {
|
||||
case "party":
|
||||
case "enemyParty": {
|
||||
@ -1452,7 +1457,7 @@ export class GameData {
|
||||
encrypt(JSON.stringify(sessionData), bypassLogin),
|
||||
);
|
||||
|
||||
console.debug("Session data saved");
|
||||
console.debug("Session data saved!");
|
||||
|
||||
if (!bypassLogin && sync) {
|
||||
pokerogueApi.savedata.updateAll(request).then(error => {
|
||||
|
@ -69,6 +69,12 @@ export default class PokemonData {
|
||||
public customPokemonData: CustomPokemonData;
|
||||
public fusionCustomPokemonData: CustomPokemonData;
|
||||
|
||||
// Deprecated attributes, needed for now to allow SessionData migration (see PR#4619 comments)
|
||||
// TODO: Remove these once pre-session migration is implemented
|
||||
public natureOverride: Nature | -1;
|
||||
public mysteryEncounterPokemonData: CustomPokemonData | null;
|
||||
public fusionMysteryEncounterPokemonData: CustomPokemonData | null;
|
||||
|
||||
/**
|
||||
* Construct a new {@linkcode PokemonData} instance out of a {@linkcode Pokemon}
|
||||
* or JSON representation thereof.
|
||||
@ -114,6 +120,15 @@ export default class PokemonData {
|
||||
this.isTerastallized = !!source.isTerastallized;
|
||||
this.stellarTypesBoosted = source.stellarTypesBoosted ?? [];
|
||||
|
||||
// Deprecated, but needed for session data migration
|
||||
this.natureOverride = source.natureOverride;
|
||||
this.mysteryEncounterPokemonData = source.mysteryEncounterPokemonData
|
||||
? new CustomPokemonData(source.mysteryEncounterPokemonData)
|
||||
: null;
|
||||
this.fusionMysteryEncounterPokemonData = source.fusionMysteryEncounterPokemonData
|
||||
? new CustomPokemonData(source.fusionMysteryEncounterPokemonData)
|
||||
: null;
|
||||
|
||||
this.fusionSpecies = sourcePokemon?.fusionSpecies?.speciesId ?? source.fusionSpecies;
|
||||
this.fusionFormIndex = source.fusionFormIndex;
|
||||
this.fusionAbilityIndex = source.fusionAbilityIndex;
|
||||
|
@ -27,14 +27,17 @@ const migratePartyData: SessionSaveMigrator = {
|
||||
// only edit summondata moveset if exists
|
||||
pkmnData.summonData.moveset &&= pkmnData.summonData.moveset.filter(m => !!m);
|
||||
|
||||
if (
|
||||
pkmnData.customPokemonData &&
|
||||
"hitsRecCount" in pkmnData.customPokemonData &&
|
||||
typeof pkmnData.customPokemonData["hitsRecCount"] === "number"
|
||||
) {
|
||||
// transfer old hit count stat to battleData.
|
||||
// No need to reset it as new Pokemon
|
||||
pkmnData.battleData.hitCount = pkmnData.customPokemonData["hitsRecCount"];
|
||||
if (pkmnData.customPokemonData) {
|
||||
// revert all "-1" sprite scales to a minimum value of 1
|
||||
pkmnData.customPokemonData.spriteScale = Math.max(1, pkmnData.customPokemonData.spriteScale);
|
||||
if (
|
||||
"hitsRecCount" in pkmnData.customPokemonData &&
|
||||
typeof pkmnData.customPokemonData["hitsRecCount"] === "number"
|
||||
) {
|
||||
// transfer old hit count stat to battleData.
|
||||
pkmnData.battleData.hitCount = pkmnData.customPokemonData["hitsRecCount"];
|
||||
pkmnData.customPokemonData["hitsRecCount"] = null;
|
||||
}
|
||||
}
|
||||
return pkmnData;
|
||||
};
|
||||
|
@ -82,14 +82,15 @@ describe("Abilities - Harvest", () => {
|
||||
.weather(WeatherType.NONE); // clear weather so we can control when harvest rolls succeed
|
||||
await game.classicMode.startBattle([Species.MILOTIC]);
|
||||
|
||||
const player = game.scene.getPlayerPokemon();
|
||||
const milotic = game.scene.getPlayerPokemon()!;
|
||||
expect(milotic).toBeDefined();
|
||||
|
||||
// Chug a few berries without harvest (should get tracked)
|
||||
game.move.select(Moves.SPLASH);
|
||||
await game.forceEnemyMove(Moves.NUZZLE);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(player?.battleData.berriesEaten).toEqual(expect.arrayContaining([BerryType.ENIGMA, BerryType.LUM]));
|
||||
expect(milotic.battleData.berriesEaten).toEqual(expect.arrayContaining([BerryType.ENIGMA, BerryType.LUM]));
|
||||
expect(getPlayerBerries()).toHaveLength(2);
|
||||
|
||||
// Give ourselves harvest and disable enemy neut gas,
|
||||
@ -97,10 +98,12 @@ describe("Abilities - Harvest", () => {
|
||||
game.override.ability(Abilities.HARVEST);
|
||||
game.move.select(Moves.GASTRO_ACID);
|
||||
await game.forceEnemyMove(Moves.NUZZLE);
|
||||
|
||||
await game.phaseInterceptor.to("TurnEndPhase", false);
|
||||
vi.spyOn(Phaser.Math.RND, "realInRange").mockReturnValue(0);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(player?.battleData.berriesEaten).toEqual(
|
||||
expect(milotic.battleData.berriesEaten).toEqual(
|
||||
expect.arrayContaining([BerryType.ENIGMA, BerryType.LUM, BerryType.ENIGMA, BerryType.LUM]),
|
||||
);
|
||||
expect(getPlayerBerries()).toHaveLength(0);
|
||||
@ -112,11 +115,11 @@ describe("Abilities - Harvest", () => {
|
||||
vi.spyOn(Phaser.Math.RND, "realInRange").mockReturnValue(1);
|
||||
await game.toNextTurn();
|
||||
|
||||
expect(player?.battleData.berriesEaten).toHaveLength(3);
|
||||
expect(milotic?.battleData.berriesEaten).toHaveLength(3);
|
||||
expect(getPlayerBerries()).toHaveLength(1);
|
||||
});
|
||||
|
||||
it("remembers berries eaten array across waves and save/reload", async () => {
|
||||
it("remembers berries eaten array across waves", async () => {
|
||||
game.override
|
||||
.startingHeldItems([{ name: "BERRY", type: BerryType.PETAYA, count: 2 }])
|
||||
.ability(Abilities.BALL_FETCH); // don't actually need harvest for this test
|
||||
@ -132,20 +135,17 @@ describe("Abilities - Harvest", () => {
|
||||
|
||||
// ate 1 berry without recovering (no harvest)
|
||||
expect(regieleki.battleData.berriesEaten).toEqual([BerryType.PETAYA]);
|
||||
expect(getPlayerBerries()).toEqual([expect.objectContaining({ berryType: BerryType.PETAYA, stackCount: 1 })]);
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.SPATK)).toBe(1);
|
||||
expectBerriesContaining({ name: "BERRY", count: 1, type: BerryType.PETAYA });
|
||||
expect(regieleki.getStatStage(Stat.SPATK)).toBe(1);
|
||||
|
||||
await game.toNextWave();
|
||||
|
||||
expect(regieleki.battleData.berriesEaten).toEqual([BerryType.PETAYA]);
|
||||
|
||||
await game.reload.reloadSession();
|
||||
|
||||
const regielekiReloaded = game.scene.getPlayerPokemon()!;
|
||||
expect(regielekiReloaded.battleData.berriesEaten).toEqual([BerryType.PETAYA]);
|
||||
expectBerriesContaining({ name: "BERRY", count: 1, type: BerryType.PETAYA });
|
||||
expect(regieleki.getStatStage(Stat.SPATK)).toBe(1);
|
||||
});
|
||||
|
||||
it("keeps berries eaten across reloads", async () => {
|
||||
it("keeps harvested berries across reloads", async () => {
|
||||
game.override
|
||||
.startingHeldItems([{ name: "BERRY", type: BerryType.PETAYA, count: 1 }])
|
||||
.moveset([Moves.SPLASH, Moves.EARTHQUAKE])
|
||||
@ -172,12 +172,13 @@ describe("Abilities - Harvest", () => {
|
||||
await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]);
|
||||
await game.toNextWave();
|
||||
|
||||
expect(getPlayerBerries()).toEqual([expect.objectContaining({ berryType: BerryType.PETAYA, stackCount: 1 })]);
|
||||
expectBerriesContaining({ name: "BERRY", count: 1, type: BerryType.PETAYA });
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.SPATK)).toBe(1);
|
||||
|
||||
await game.reload.reloadSession();
|
||||
|
||||
expect(getPlayerBerries()).toEqual([expect.objectContaining({ berryType: BerryType.PETAYA, stackCount: 1 })]);
|
||||
expect(regieleki.battleData.berriesEaten).toEqual([]);
|
||||
expectBerriesContaining({ name: "BERRY", count: 1, type: BerryType.PETAYA });
|
||||
expect(game.scene.getPlayerPokemon()?.getStatStage(Stat.SPATK)).toBe(1);
|
||||
});
|
||||
|
||||
|
@ -46,6 +46,16 @@ export class ReloadHelper extends GameManagerHelper {
|
||||
scene.unshiftPhase(titlePhase);
|
||||
this.game.endPhase(); // End the currently ongoing battle
|
||||
|
||||
// remove all persistent mods before loading
|
||||
// TODO: Look into why these aren't removed before load
|
||||
if (this.game.scene.modifiers.length) {
|
||||
console.log(
|
||||
"Removing %d modifiers from scene on load...",
|
||||
this.game.scene.modifiers.length,
|
||||
this.game.scene.modifiers,
|
||||
);
|
||||
this.game.scene.modifiers = [];
|
||||
}
|
||||
titlePhase.loadSaveSlot(-1); // Load the desired session data
|
||||
this.game.phaseInterceptor.shift(); // Loading the save slot also ended TitlePhase, clean it up
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user