mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-23 15:59:26 +02:00
Clean Up & Organize Version Migration
This commit is contained in:
parent
dad81f3631
commit
3cc0232cae
@ -44,7 +44,7 @@ import { WeatherType } from "#app/enums/weather-type";
|
||||
import { TerrainType } from "#app/data/terrain";
|
||||
import { ReloadSessionPhase } from "#app/phases/reload-session-phase";
|
||||
import { RUN_HISTORY_LIMIT } from "#app/ui/run-history-ui-handler";
|
||||
import { applySessionDataPatches, applySettingsDataPatches, applySystemDataPatches } from "./version-converter";
|
||||
import { SessionVersionConverter, SettingsVersionConverter, SystemVersionConverter } from "./version_migration/version_converter";
|
||||
import { MysteryEncounterSaveData } from "../data/mystery-encounters/mystery-encounter-save-data";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
|
||||
@ -463,7 +463,7 @@ export class GameData {
|
||||
localStorage.setItem(lsItemKey, "");
|
||||
}
|
||||
|
||||
applySystemDataPatches(systemData);
|
||||
new SystemVersionConverter(systemData, systemData.gameVersion);
|
||||
|
||||
this.trainerId = systemData.trainerId;
|
||||
this.secretId = systemData.secretId;
|
||||
@ -838,7 +838,7 @@ export class GameData {
|
||||
|
||||
const settings = JSON.parse(localStorage.getItem("settings")!); // TODO: is this bang correct?
|
||||
|
||||
applySettingsDataPatches(settings);
|
||||
new SettingsVersionConverter(settings);
|
||||
|
||||
for (const setting of Object.keys(settings)) {
|
||||
setSetting(this.scene, setting, settings[setting]);
|
||||
@ -1270,7 +1270,7 @@ export class GameData {
|
||||
return v;
|
||||
}) as SessionSaveData;
|
||||
|
||||
applySessionDataPatches(sessionData);
|
||||
new SessionVersionConverter(sessionData, sessionData.gameVersion);
|
||||
|
||||
return sessionData;
|
||||
}
|
||||
|
@ -1,141 +0,0 @@
|
||||
import { allSpecies } from "#app/data/pokemon-species";
|
||||
import { AbilityAttr, defaultStarterSpecies, DexAttr, SessionSaveData, SystemSaveData } from "./game-data";
|
||||
import { SettingKeys } from "./settings/settings";
|
||||
|
||||
const LATEST_VERSION = "1.0.5";
|
||||
|
||||
export function applySessionDataPatches(data: SessionSaveData) {
|
||||
const curVersion = data.gameVersion;
|
||||
if (curVersion !== LATEST_VERSION) {
|
||||
switch (curVersion) {
|
||||
case "1.0.0":
|
||||
case "1.0.1":
|
||||
case "1.0.2":
|
||||
case "1.0.3":
|
||||
case "1.0.4":
|
||||
// --- PATCHES ---
|
||||
|
||||
// Fix Battle Items, Vitamins, and Lures
|
||||
data.modifiers.forEach((m) => {
|
||||
if (m.className === "PokemonBaseStatModifier") {
|
||||
m.className = "BaseStatModifier";
|
||||
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
|
||||
m.className = "ResetNegativeStatStageModifier";
|
||||
} else if (m.className === "TempBattleStatBoosterModifier") {
|
||||
m.className = "TempStatStageBoosterModifier";
|
||||
m.typeId = "TEMP_STAT_STAGE_BOOSTER";
|
||||
|
||||
// Migration from TempBattleStat to Stat
|
||||
const newStat = m.typePregenArgs[0] + 1;
|
||||
m.typePregenArgs[0] = newStat;
|
||||
|
||||
// From [ stat, battlesLeft ] to [ stat, maxBattles, battleCount ]
|
||||
m.args = [ newStat, 5, m.args[1] ];
|
||||
} else if (m.className === "DoubleBattleChanceBoosterModifier" && m.args.length === 1) {
|
||||
let maxBattles: number;
|
||||
switch (m.typeId) {
|
||||
case "MAX_LURE":
|
||||
maxBattles = 30;
|
||||
break;
|
||||
case "SUPER_LURE":
|
||||
maxBattles = 15;
|
||||
break;
|
||||
default:
|
||||
maxBattles = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
// From [ battlesLeft ] to [ maxBattles, battleCount ]
|
||||
m.args = [ maxBattles, m.args[0] ];
|
||||
}
|
||||
});
|
||||
|
||||
data.enemyModifiers.forEach((m) => {
|
||||
if (m.className === "PokemonBaseStatModifier") {
|
||||
m.className = "BaseStatModifier";
|
||||
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
|
||||
m.className = "ResetNegativeStatStageModifier";
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
data.gameVersion = LATEST_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
export function applySystemDataPatches(data: SystemSaveData) {
|
||||
const curVersion = data.gameVersion;
|
||||
if (curVersion !== LATEST_VERSION) {
|
||||
switch (curVersion) {
|
||||
case "1.0.0":
|
||||
case "1.0.1":
|
||||
case "1.0.2":
|
||||
case "1.0.3":
|
||||
case "1.0.4":
|
||||
// --- LEGACY PATCHES ---
|
||||
if (data.starterData) {
|
||||
// Migrate ability starter data if empty for caught species
|
||||
Object.keys(data.starterData).forEach(sd => {
|
||||
if (data.dexData[sd]?.caughtAttr && (data.starterData[sd] && !data.starterData[sd].abilityAttr)) {
|
||||
data.starterData[sd].abilityAttr = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Fix Legendary Stats
|
||||
if (data.gameStats && (data.gameStats.legendaryPokemonCaught !== undefined && data.gameStats.subLegendaryPokemonCaught === undefined)) {
|
||||
data.gameStats.subLegendaryPokemonSeen = 0;
|
||||
data.gameStats.subLegendaryPokemonCaught = 0;
|
||||
data.gameStats.subLegendaryPokemonHatched = 0;
|
||||
allSpecies.filter(s => s.subLegendary).forEach(s => {
|
||||
const dexEntry = data.dexData[s.speciesId];
|
||||
data.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount;
|
||||
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0);
|
||||
data.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount;
|
||||
data.gameStats.legendaryPokemonCaught = Math.max(data.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0);
|
||||
data.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount;
|
||||
data.gameStats.legendaryPokemonHatched = Math.max(data.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0);
|
||||
});
|
||||
data.gameStats.subLegendaryPokemonSeen = Math.max(data.gameStats.subLegendaryPokemonSeen, data.gameStats.subLegendaryPokemonCaught);
|
||||
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen, data.gameStats.legendaryPokemonCaught);
|
||||
data.gameStats.mythicalPokemonSeen = Math.max(data.gameStats.mythicalPokemonSeen, data.gameStats.mythicalPokemonCaught);
|
||||
}
|
||||
|
||||
// --- PATCHES ---
|
||||
|
||||
// Fix Starter Data
|
||||
for (const starterId of defaultStarterSpecies) {
|
||||
if (data.starterData[starterId]?.abilityAttr) {
|
||||
data.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1;
|
||||
}
|
||||
if (data.dexData[starterId]?.caughtAttr) {
|
||||
data.dexData[starterId].caughtAttr |= DexAttr.FEMALE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data.gameVersion = LATEST_VERSION;
|
||||
}
|
||||
}
|
||||
|
||||
export function applySettingsDataPatches(settings: Object) {
|
||||
const curVersion = settings.hasOwnProperty("gameVersion") ? settings["gameVersion"] : "1.0.0";
|
||||
if (curVersion !== LATEST_VERSION) {
|
||||
switch (curVersion) {
|
||||
case "1.0.0":
|
||||
case "1.0.1":
|
||||
case "1.0.2":
|
||||
case "1.0.3":
|
||||
case "1.0.4":
|
||||
// --- PATCHES ---
|
||||
|
||||
// Fix Reward Cursor Target
|
||||
if (settings.hasOwnProperty("REROLL_TARGET") && !settings.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) {
|
||||
settings[SettingKeys.Shop_Cursor_Target] = settings["REROLL_TARGET"];
|
||||
delete settings["REROLL_TARGET"];
|
||||
localStorage.setItem("settings", JSON.stringify(settings));
|
||||
}
|
||||
}
|
||||
// Note that the current game version will be written at `saveSettings`
|
||||
}
|
||||
}
|
61
src/system/version_migration/v1_0_4/session_migrators.ts
Normal file
61
src/system/version_migration/v1_0_4/session_migrators.ts
Normal file
@ -0,0 +1,61 @@
|
||||
import { SessionSaveData } from "../../game-data";
|
||||
|
||||
/**
|
||||
* Converts old lapsing modifiers (battle items, lures, and Dire Hit) and
|
||||
* other miscellaneous modifiers (vitamins, White Herb) to any new class
|
||||
* names and/or change in reload arguments.
|
||||
* @param data {@linkcode SessionSaveData}
|
||||
*/
|
||||
export function migrateModifiers(data: SessionSaveData) {
|
||||
data.modifiers.forEach((m) => {
|
||||
if (m.className === "PokemonBaseStatModifier") {
|
||||
m.className = "BaseStatModifier";
|
||||
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
|
||||
m.className = "ResetNegativeStatStageModifier";
|
||||
} else if (m.className === "TempBattleStatBoosterModifier") {
|
||||
const maxBattles = 5;
|
||||
// Dire Hit no longer a part of the TempBattleStatBoosterModifierTypeGenerator
|
||||
if (m.typeId !== "DIRE_HIT") {
|
||||
m.className = "TempStatStageBoosterModifier";
|
||||
m.typeId = "TEMP_STAT_STAGE_BOOSTER";
|
||||
|
||||
// Migration from TempBattleStat to Stat
|
||||
const newStat = m.typePregenArgs[0] + 1;
|
||||
m.typePregenArgs[0] = newStat;
|
||||
|
||||
// From [ stat, battlesLeft ] to [ stat, maxBattles, battleCount ]
|
||||
m.args = [ newStat, maxBattles, Math.min(m.args[1], maxBattles) ];
|
||||
} else {
|
||||
m.className = "TempCritBoosterModifier";
|
||||
m.typePregenArgs = [];
|
||||
|
||||
// From [ stat, battlesLeft ] to [ maxBattles, battleCount ]
|
||||
m.args = [ maxBattles, Math.min(m.args[1], maxBattles) ];
|
||||
}
|
||||
} else if (m.className === "DoubleBattleChanceBoosterModifier" && m.args.length === 1) {
|
||||
let maxBattles: number;
|
||||
switch (m.typeId) {
|
||||
case "MAX_LURE":
|
||||
maxBattles = 30;
|
||||
break;
|
||||
case "SUPER_LURE":
|
||||
maxBattles = 15;
|
||||
break;
|
||||
default:
|
||||
maxBattles = 10;
|
||||
break;
|
||||
}
|
||||
|
||||
// From [ battlesLeft ] to [ maxBattles, battleCount ]
|
||||
m.args = [ maxBattles, m.args[0] ];
|
||||
}
|
||||
});
|
||||
|
||||
data.enemyModifiers.forEach((m) => {
|
||||
if (m.className === "PokemonBaseStatModifier") {
|
||||
m.className = "BaseStatModifier";
|
||||
} else if (m.className === "PokemonResetNegativeStatStageModifier") {
|
||||
m.className = "ResetNegativeStatStageModifier";
|
||||
}
|
||||
});
|
||||
}
|
14
src/system/version_migration/v1_0_4/settings_migrators.ts
Normal file
14
src/system/version_migration/v1_0_4/settings_migrators.ts
Normal file
@ -0,0 +1,14 @@
|
||||
import { SettingKeys } from "../../settings/settings";
|
||||
|
||||
/**
|
||||
* Migrate from "REROLL_TARGET" property to {@linkcode
|
||||
* SettingKeys.Shop_Cursor_Target}.
|
||||
* @param data the `settings` object
|
||||
*/
|
||||
export function fixRerollTarget(data: Object) {
|
||||
if (data.hasOwnProperty("REROLL_TARGET") && !data.hasOwnProperty(SettingKeys.Shop_Cursor_Target)) {
|
||||
data[SettingKeys.Shop_Cursor_Target] = data["REROLL_TARGET"];
|
||||
delete data["REROLL_TARGET"];
|
||||
localStorage.setItem("settings", JSON.stringify(data));
|
||||
}
|
||||
}
|
56
src/system/version_migration/v1_0_4/system_migrators.ts
Normal file
56
src/system/version_migration/v1_0_4/system_migrators.ts
Normal file
@ -0,0 +1,56 @@
|
||||
import { AbilityAttr, defaultStarterSpecies, DexAttr, SystemSaveData } from "../../game-data";
|
||||
import { allSpecies } from "../../../data/pokemon-species";
|
||||
|
||||
/**
|
||||
* Migrate ability starter data if empty for caught species
|
||||
* @param data {@linkcode SystemSaveData}
|
||||
*/
|
||||
export function migrateAbilityData(data: SystemSaveData) {
|
||||
if (data.starterData && data.dexData) {
|
||||
// Migrate ability starter data if empty for caught species
|
||||
Object.keys(data.starterData).forEach(sd => {
|
||||
if (data.dexData[sd]?.caughtAttr && (data.starterData[sd] && !data.starterData[sd].abilityAttr)) {
|
||||
data.starterData[sd].abilityAttr = 1;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Populate legendary Pokémon statistics if they are missing
|
||||
* @param data {@linkcode SystemSaveData}
|
||||
*/
|
||||
export function fixLegendaryStats(data: SystemSaveData) {
|
||||
if (data.gameStats && (data.gameStats.legendaryPokemonCaught !== undefined && data.gameStats.subLegendaryPokemonCaught === undefined)) {
|
||||
data.gameStats.subLegendaryPokemonSeen = 0;
|
||||
data.gameStats.subLegendaryPokemonCaught = 0;
|
||||
data.gameStats.subLegendaryPokemonHatched = 0;
|
||||
allSpecies.filter(s => s.subLegendary).forEach(s => {
|
||||
const dexEntry = data.dexData[s.speciesId];
|
||||
data.gameStats.subLegendaryPokemonSeen += dexEntry.seenCount;
|
||||
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen - dexEntry.seenCount, 0);
|
||||
data.gameStats.subLegendaryPokemonCaught += dexEntry.caughtCount;
|
||||
data.gameStats.legendaryPokemonCaught = Math.max(data.gameStats.legendaryPokemonCaught - dexEntry.caughtCount, 0);
|
||||
data.gameStats.subLegendaryPokemonHatched += dexEntry.hatchedCount;
|
||||
data.gameStats.legendaryPokemonHatched = Math.max(data.gameStats.legendaryPokemonHatched - dexEntry.hatchedCount, 0);
|
||||
});
|
||||
data.gameStats.subLegendaryPokemonSeen = Math.max(data.gameStats.subLegendaryPokemonSeen, data.gameStats.subLegendaryPokemonCaught);
|
||||
data.gameStats.legendaryPokemonSeen = Math.max(data.gameStats.legendaryPokemonSeen, data.gameStats.legendaryPokemonCaught);
|
||||
data.gameStats.mythicalPokemonSeen = Math.max(data.gameStats.mythicalPokemonSeen, data.gameStats.mythicalPokemonCaught);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlock all starters' first ability and female gender option
|
||||
* @param data {@linkcode SystemSaveData}
|
||||
*/
|
||||
export function fixStarterData(data: SystemSaveData) {
|
||||
for (const starterId of defaultStarterSpecies) {
|
||||
if (data.starterData[starterId]?.abilityAttr) {
|
||||
data.starterData[starterId].abilityAttr |= AbilityAttr.ABILITY_1;
|
||||
}
|
||||
if (data.dexData[starterId]?.caughtAttr) {
|
||||
data.dexData[starterId].caughtAttr |= DexAttr.FEMALE;
|
||||
}
|
||||
}
|
||||
}
|
100
src/system/version_migration/version_converter.ts
Normal file
100
src/system/version_migration/version_converter.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import { SessionSaveData, SystemSaveData } from "../game-data";
|
||||
import { version } from "../../../package.json";
|
||||
|
||||
// --- v1.0.4 (and below) PATCHES --- //
|
||||
import * as v1_0_4SessionData from "./v1_0_4/session_migrators";
|
||||
import * as v1_0_4SystemData from "./v1_0_4/system_migrators";
|
||||
import * as v1_0_4SettingsData from "./v1_0_4/settings_migrators";
|
||||
|
||||
const LATEST_VERSION = version.split(".").map(value => parseInt(value));
|
||||
|
||||
export abstract class VersionConverter {
|
||||
constructor(data: any, gameVersion: string) {
|
||||
const curVersion = gameVersion.split(".").map(value => parseInt(value));
|
||||
if (!curVersion.every((value, index) => value === LATEST_VERSION[index])) {
|
||||
this.applyPatches(data, curVersion);
|
||||
}
|
||||
}
|
||||
|
||||
callMigrators(data: any, migrationObject: Object) {
|
||||
const migrators = Object.values(migrationObject);
|
||||
for (const migrate of migrators) {
|
||||
migrate(data);
|
||||
}
|
||||
}
|
||||
|
||||
abstract applyPatches(data: any, curVersion: number[]): void;
|
||||
}
|
||||
|
||||
export class SessionVersionConverter extends VersionConverter {
|
||||
constructor(data: SessionSaveData, gameVersion: string) {
|
||||
super(data, gameVersion);
|
||||
}
|
||||
|
||||
applyPatches(data: SessionSaveData, curVersion: number[]): void {
|
||||
const [ curMajor, curMinor, curPatch ] = curVersion;
|
||||
|
||||
switch (curMajor) {
|
||||
case 1:
|
||||
switch (curMinor) {
|
||||
case 0:
|
||||
if (curPatch <= 4) {
|
||||
console.log("Applying v1.0.4 session data migration!");
|
||||
this.callMigrators(data, v1_0_4SessionData);
|
||||
}
|
||||
default:
|
||||
}
|
||||
default:
|
||||
}
|
||||
console.log(`Session data successfully migrated to v${version}!`);
|
||||
}
|
||||
}
|
||||
|
||||
export class SystemVersionConverter extends VersionConverter {
|
||||
constructor(data: SystemSaveData, gameVersion: string) {
|
||||
super(data, gameVersion);
|
||||
}
|
||||
|
||||
applyPatches(data: SystemSaveData, curVersion: number[]): void {
|
||||
const [ curMajor, curMinor, curPatch ] = curVersion;
|
||||
|
||||
switch (curMajor) {
|
||||
case 1:
|
||||
switch (curMinor) {
|
||||
case 0:
|
||||
if (curPatch <= 4) {
|
||||
console.log("Applying v1.0.4 system data migraton!");
|
||||
this.callMigrators(data, v1_0_4SystemData);
|
||||
}
|
||||
default:
|
||||
}
|
||||
default:
|
||||
}
|
||||
console.log(`System data successfully migrated to v${version}!`);
|
||||
}
|
||||
}
|
||||
|
||||
export class SettingsVersionConverter extends VersionConverter {
|
||||
constructor(data: SystemSaveData) {
|
||||
const gameVersion = data.hasOwnProperty("gameVersion") ? data["gameVersion"] : "1.0.0";
|
||||
super(data, gameVersion);
|
||||
}
|
||||
|
||||
applyPatches(data: Object, curVersion: number[]): void {
|
||||
const [ curMajor, curMinor, curPatch ] = curVersion;
|
||||
|
||||
switch (curMajor) {
|
||||
case 1:
|
||||
switch (curMinor) {
|
||||
case 0:
|
||||
if (curPatch <= 4) {
|
||||
console.log("Applying v1.0.4 settings data migraton!");
|
||||
this.callMigrators(data, v1_0_4SettingsData);
|
||||
}
|
||||
default:
|
||||
}
|
||||
default:
|
||||
}
|
||||
console.log(`System data successfully migrated to v${version}!`);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user