Saving and loading starter preferences as intended without conflicts

This commit is contained in:
Wlowscha 2025-08-16 21:34:05 +02:00
parent 1ddcca7da5
commit 344ec58a5b
No known key found for this signature in database
GPG Key ID: 3C8F1AD330565D04

View File

@ -400,6 +400,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
private starterSelectCallback: StarterSelectCallback | null; private starterSelectCallback: StarterSelectCallback | null;
private starterPreferences: StarterPreferences; private starterPreferences: StarterPreferences;
private originalStarterPreferences: StarterPreferences;
protected blockInput = false; protected blockInput = false;
@ -1126,10 +1127,6 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
show(args: any[]): boolean { show(args: any[]): boolean {
if (!this.starterPreferences) {
// starterPreferences haven't been loaded yet
this.starterPreferences = loadStarterPreferences();
}
this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers this.moveInfoOverlay.clear(); // clear this when removing a menu; the cancel button doesn't seem to trigger this automatically on controllers
this.pokerusSpecies = getPokerusStarters(); this.pokerusSpecies = getPokerusStarters();
@ -1139,12 +1136,20 @@ export class StarterSelectUiHandler extends MessageUiHandler {
this.starterSelectContainer.setVisible(true); this.starterSelectContainer.setVisible(true);
this.starterPreferences = loadStarterPreferences();
this.originalStarterPreferences = loadStarterPreferences();
this.allSpecies.forEach((species, s) => { this.allSpecies.forEach((species, s) => {
const icon = this.starterContainers[s].icon; const icon = this.starterContainers[s].icon;
const { dexEntry } = this.getSpeciesData(species.speciesId); const { dexEntry } = this.getSpeciesData(species.speciesId);
// Initialize the StarterAttributes for this species // Initialize the StarterAttributes for this species
this.starterPreferences[species.speciesId] = this.initStarterPrefs(species); this.starterPreferences[species.speciesId] = this.initStarterPrefs(species, this.starterPreferences);
this.originalStarterPreferences[species.speciesId] = this.initStarterPrefs(
species,
this.originalStarterPreferences,
true,
);
if (dexEntry.caughtAttr) { if (dexEntry.caughtAttr) {
icon.clearTint(); icon.clearTint();
@ -1179,10 +1184,14 @@ export class StarterSelectUiHandler extends MessageUiHandler {
* @param species The species to get Starter Preferences for * @param species The species to get Starter Preferences for
* @returns StarterAttributes for the species * @returns StarterAttributes for the species
*/ */
initStarterPrefs(species: PokemonSpecies): StarterAttributes { initStarterPrefs(
const starterAttributes = this.starterPreferences[species.speciesId]; species: PokemonSpecies,
const dexEntry = globalScene.gameData.dexData[species.speciesId]; preferences: StarterPreferences,
const starterData = globalScene.gameData.starterData[species.speciesId]; ignoreChallenge = false,
): StarterAttributes {
const starterAttributes = preferences[species.speciesId];
const { dexEntry, starterDataEntry } = this.getSpeciesData(species.speciesId, !ignoreChallenge);
const starterData = starterDataEntry;
// no preferences or Pokemon wasn't caught, return empty attribute // no preferences or Pokemon wasn't caught, return empty attribute
if (!starterAttributes || !dexEntry.caughtAttr) { if (!starterAttributes || !dexEntry.caughtAttr) {
@ -1782,9 +1791,11 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
} else { } else {
let starterContainer: StarterContainer; let starterContainer: StarterContainer;
const starterData = globalScene.gameData.starterData[this.lastSpecies.speciesId]; const { starterDataEntry } = this.getSpeciesData(this.lastSpecies.speciesId);
const starterData = starterDataEntry;
// prepare persistent starter data to store changes // prepare persistent starter data to store changes
let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId]; let starterAttributes = this.starterPreferences[this.lastSpecies.speciesId];
const originalStarterAttributes = this.originalStarterPreferences[this.lastSpecies.speciesId];
// this gets the correct pokemon cursor depending on whether you're in the starter screen or the party icons // this gets the correct pokemon cursor depending on whether you're in the starter screen or the party icons
if (!this.starterIconsCursorObj.visible) { if (!this.starterIconsCursorObj.visible) {
@ -2000,6 +2011,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] = {}; starterAttributes = this.starterPreferences[this.lastSpecies.speciesId] = {};
} }
starterAttributes.nature = n; starterAttributes.nature = n;
originalStarterAttributes.nature = starterAttributes.nature;
this.clearText(); this.clearText();
ui.setMode(UiMode.STARTER_SELECT); ui.setMode(UiMode.STARTER_SELECT);
// set nature for starter // set nature for starter
@ -2068,6 +2080,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
label: i18next.t("starterSelectUiHandler:addToFavorites"), label: i18next.t("starterSelectUiHandler:addToFavorites"),
handler: () => { handler: () => {
starterAttributes.favorite = true; starterAttributes.favorite = true;
originalStarterAttributes.favorite = true;
// if the starter container not exists, it means the species is not in the filtered starters // if the starter container not exists, it means the species is not in the filtered starters
if (starterContainer) { if (starterContainer) {
starterContainer.favoriteIcon.setVisible(starterAttributes.favorite); starterContainer.favoriteIcon.setVisible(starterAttributes.favorite);
@ -2081,6 +2094,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
label: i18next.t("starterSelectUiHandler:removeFromFavorites"), label: i18next.t("starterSelectUiHandler:removeFromFavorites"),
handler: () => { handler: () => {
starterAttributes.favorite = false; starterAttributes.favorite = false;
originalStarterAttributes.favorite = false;
// if the starter container not exists, it means the species is not in the filtered starters // if the starter container not exists, it means the species is not in the filtered starters
if (starterContainer) { if (starterContainer) {
starterContainer.favoriteIcon.setVisible(starterAttributes.favorite); starterContainer.favoriteIcon.setVisible(starterAttributes.favorite);
@ -2103,6 +2117,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
(sanitizedName: string) => { (sanitizedName: string) => {
ui.playSelect(); ui.playSelect();
starterAttributes.nickname = sanitizedName; starterAttributes.nickname = sanitizedName;
originalStarterAttributes.nickname = sanitizedName;
const name = decodeURIComponent(escape(atob(starterAttributes.nickname))); const name = decodeURIComponent(escape(atob(starterAttributes.nickname)));
if (name.length > 0) { if (name.length > 0) {
this.pokemonNameText.setText(name); this.pokemonNameText.setText(name);
@ -2329,6 +2344,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)).setTint(tint).setVisible(true); this.pokemonShinyIcon.setFrame(getVariantIcon(newVariant)).setTint(tint).setVisible(true);
starterAttributes.shiny = true; starterAttributes.shiny = true;
originalStarterAttributes.shiny = true;
} else { } else {
// If shiny, we update the variant // If shiny, we update the variant
let newVariant = props.variant; let newVariant = props.variant;
@ -2352,6 +2368,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
} while (newVariant !== props.variant); } while (newVariant !== props.variant);
starterAttributes.variant = newVariant; // store the selected variant starterAttributes.variant = newVariant; // store the selected variant
originalStarterAttributes.variant = newVariant;
if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.NON_SHINY && newVariant <= props.variant) { if (this.speciesStarterDexEntry!.caughtAttr & DexAttr.NON_SHINY && newVariant <= props.variant) {
// If we have run out of variants, go back to non shiny // If we have run out of variants, go back to non shiny
this.setSpeciesDetails(this.lastSpecies, { this.setSpeciesDetails(this.lastSpecies, {
@ -2361,6 +2378,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
this.pokemonShinyIcon.setVisible(false); this.pokemonShinyIcon.setVisible(false);
success = true; success = true;
starterAttributes.shiny = false; starterAttributes.shiny = false;
originalStarterAttributes.shiny = false;
} else { } else {
// If going to a higher variant, or only shiny forms are caught, go to next variant // If going to a higher variant, or only shiny forms are caught, go to next variant
this.setSpeciesDetails(this.lastSpecies, { this.setSpeciesDetails(this.lastSpecies, {
@ -2389,7 +2407,9 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
} while (newFormIndex !== props.formIndex); } while (newFormIndex !== props.formIndex);
starterAttributes.form = newFormIndex; // store the selected form starterAttributes.form = newFormIndex; // store the selected form
originalStarterAttributes.form = newFormIndex;
starterAttributes.tera = this.lastSpecies.forms[newFormIndex].type1; starterAttributes.tera = this.lastSpecies.forms[newFormIndex].type1;
originalStarterAttributes.tera = starterAttributes.tera;
this.setSpeciesDetails(this.lastSpecies, { this.setSpeciesDetails(this.lastSpecies, {
formIndex: newFormIndex, formIndex: newFormIndex,
teraType: starterAttributes.tera, teraType: starterAttributes.tera,
@ -2400,6 +2420,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
case Button.CYCLE_GENDER: case Button.CYCLE_GENDER:
if (this.canCycleGender) { if (this.canCycleGender) {
starterAttributes.female = !props.female; starterAttributes.female = !props.female;
originalStarterAttributes.female = starterAttributes.female;
this.setSpeciesDetails(this.lastSpecies, { this.setSpeciesDetails(this.lastSpecies, {
female: !props.female, female: !props.female,
}); });
@ -2409,7 +2430,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
case Button.CYCLE_ABILITY: case Button.CYCLE_ABILITY:
if (this.canCycleAbility) { if (this.canCycleAbility) {
const abilityCount = this.lastSpecies.getAbilityCount(); const abilityCount = this.lastSpecies.getAbilityCount();
const abilityAttr = globalScene.gameData.starterData[this.lastSpecies.speciesId].abilityAttr; const abilityAttr = starterDataEntry.abilityAttr;
const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1; const hasAbility1 = abilityAttr & AbilityAttr.ABILITY_1;
let newAbilityIndex = this.abilityCursor; let newAbilityIndex = this.abilityCursor;
do { do {
@ -2431,6 +2452,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
} while (newAbilityIndex !== this.abilityCursor); } while (newAbilityIndex !== this.abilityCursor);
starterAttributes.ability = newAbilityIndex; // store the selected ability starterAttributes.ability = newAbilityIndex; // store the selected ability
originalStarterAttributes.ability = newAbilityIndex;
const { visible: tooltipVisible } = globalScene.ui.getTooltip(); const { visible: tooltipVisible } = globalScene.ui.getTooltip();
@ -2452,6 +2474,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0]; const newNature = natures[natureIndex < natures.length - 1 ? natureIndex + 1 : 0];
// store cycled nature as default // store cycled nature as default
starterAttributes.nature = newNature as unknown as number; starterAttributes.nature = newNature as unknown as number;
originalStarterAttributes.nature = starterAttributes.nature;
this.setSpeciesDetails(this.lastSpecies, { this.setSpeciesDetails(this.lastSpecies, {
natureIndex: newNature, natureIndex: newNature,
}); });
@ -2463,11 +2486,13 @@ export class StarterSelectUiHandler extends MessageUiHandler {
const speciesForm = getPokemonSpeciesForm(this.lastSpecies.speciesId, starterAttributes.form ?? 0); const speciesForm = getPokemonSpeciesForm(this.lastSpecies.speciesId, starterAttributes.form ?? 0);
if (speciesForm.type1 === this.teraCursor && !isNullOrUndefined(speciesForm.type2)) { if (speciesForm.type1 === this.teraCursor && !isNullOrUndefined(speciesForm.type2)) {
starterAttributes.tera = speciesForm.type2!; starterAttributes.tera = speciesForm.type2!;
originalStarterAttributes.form = starterAttributes.tera;
this.setSpeciesDetails(this.lastSpecies, { this.setSpeciesDetails(this.lastSpecies, {
teraType: speciesForm.type2!, teraType: speciesForm.type2!,
}); });
} else { } else {
starterAttributes.tera = speciesForm.type1; starterAttributes.tera = speciesForm.type1;
originalStarterAttributes.form = starterAttributes.tera;
this.setSpeciesDetails(this.lastSpecies, { this.setSpeciesDetails(this.lastSpecies, {
teraType: speciesForm.type1, teraType: speciesForm.type1,
}); });
@ -2714,16 +2739,16 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
const updatedMoveset = starterMoveset.slice() as StarterMoveset; const updatedMoveset = starterMoveset.slice() as StarterMoveset;
const formIndex = globalScene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor).formIndex; const formIndex = globalScene.gameData.getSpeciesDexAttrProps(this.lastSpecies, this.dexAttrCursor).formIndex;
const starterData = globalScene.gameData.starterData[speciesId]; const { starterDataEntry } = this.getSpeciesData(this.lastSpecies.speciesId);
// species has different forms // species has different forms
if (pokemonFormLevelMoves.hasOwnProperty(speciesId)) { if (pokemonFormLevelMoves.hasOwnProperty(speciesId)) {
// Species has forms with different movesets // Species has forms with different movesets
if (!starterData.moveset || Array.isArray(starterData.moveset)) { if (!starterDataEntry.moveset || Array.isArray(starterDataEntry.moveset)) {
starterData.moveset = {}; starterDataEntry.moveset = {};
} }
starterData.moveset[formIndex] = updatedMoveset; starterDataEntry.moveset[formIndex] = updatedMoveset;
} else { } else {
starterData.moveset = updatedMoveset; starterDataEntry.moveset = updatedMoveset;
} }
this.setSpeciesDetails(this.lastSpecies, { forSeen: false }); this.setSpeciesDetails(this.lastSpecies, { forSeen: false });
@ -3669,14 +3694,18 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
} }
getSpeciesData(speciesId: SpeciesId): { dexEntry: DexEntry; starterDataEntry: StarterDataEntry } { getSpeciesData(
speciesId: SpeciesId,
applyChallenge = true,
): { dexEntry: DexEntry; starterDataEntry: StarterDataEntry } {
const dexEntry = globalScene.gameData.dexData[speciesId]; const dexEntry = globalScene.gameData.dexData[speciesId];
const starterDataEntry = globalScene.gameData.starterData[speciesId]; const starterDataEntry = globalScene.gameData.starterData[speciesId];
const copiedDexEntry = { ...dexEntry }; const copiedDexEntry = { ...dexEntry };
const copiedStarterDataEntry = { ...starterDataEntry }; const copiedStarterDataEntry = { ...starterDataEntry };
applyChallenges(ChallengeType.STARTER_SELECT_MODIFY, copiedDexEntry, copiedStarterDataEntry); if (applyChallenge) {
applyChallenges(ChallengeType.STARTER_SELECT_MODIFY, copiedDexEntry, copiedStarterDataEntry);
}
return { dexEntry: { ...copiedDexEntry }, starterDataEntry: { ...copiedStarterDataEntry } }; return { dexEntry: { ...copiedDexEntry }, starterDataEntry: { ...copiedStarterDataEntry } };
} }
@ -3760,7 +3789,6 @@ export class StarterSelectUiHandler extends MessageUiHandler {
const { dexEntry, starterDataEntry } = this.getSpeciesData(species.speciesId); const { dexEntry, starterDataEntry } = this.getSpeciesData(species.speciesId);
const caughtAttr = dexEntry.caughtAttr || BigInt(0); const caughtAttr = dexEntry.caughtAttr || BigInt(0);
const abilityAttr = starterDataEntry.abilityAttr; const abilityAttr = starterDataEntry.abilityAttr;
console.log("I HAVE APPLIED, ", starterDataEntry.eggMoves);
if (!caughtAttr) { if (!caughtAttr) {
const props = globalScene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId)); const props = globalScene.gameData.getSpeciesDexAttrProps(species, this.getCurrentDexProps(species.speciesId));
@ -3903,7 +3931,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
.setColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD)) .setColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD))
.setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true)); .setShadowColor(this.getTextColor(!isHidden ? TextStyle.SUMMARY_ALT : TextStyle.SUMMARY_GOLD, true));
const passiveAttr = globalScene.gameData.starterData[species.speciesId].passiveAttr; const passiveAttr = starterDataEntry.passiveAttr;
const passiveAbility = allAbilities[this.lastSpecies.getPassiveAbility(formIndex)]; const passiveAbility = allAbilities[this.lastSpecies.getPassiveAbility(formIndex)];
if (this.pokemonAbilityText.visible) { if (this.pokemonAbilityText.visible) {
@ -3984,13 +4012,13 @@ export class StarterSelectUiHandler extends MessageUiHandler {
this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] > 0 && lm[0] <= 5).map(lm => lm[1])); this.speciesStarterMoves.push(...levelMoves.filter(lm => lm[0] > 0 && lm[0] <= 5).map(lm => lm[1]));
if (speciesEggMoves.hasOwnProperty(species.speciesId)) { if (speciesEggMoves.hasOwnProperty(species.speciesId)) {
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
if (globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em)) { if (starterDataEntry.eggMoves & (1 << em)) {
this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]); this.speciesStarterMoves.push(speciesEggMoves[species.speciesId][em]);
} }
} }
} }
const speciesMoveData = globalScene.gameData.starterData[species.speciesId].moveset; const speciesMoveData = starterDataEntry.moveset;
const moveData: StarterMoveset | null = speciesMoveData const moveData: StarterMoveset | null = speciesMoveData
? Array.isArray(speciesMoveData) ? Array.isArray(speciesMoveData)
? speciesMoveData ? speciesMoveData
@ -3998,9 +4026,7 @@ export class StarterSelectUiHandler extends MessageUiHandler {
: null; : null;
const availableStarterMoves = this.speciesStarterMoves.concat( const availableStarterMoves = this.speciesStarterMoves.concat(
speciesEggMoves.hasOwnProperty(species.speciesId) speciesEggMoves.hasOwnProperty(species.speciesId)
? speciesEggMoves[species.speciesId].filter( ? speciesEggMoves[species.speciesId].filter((_: any, em: number) => starterDataEntry.eggMoves & (1 << em))
(_: any, em: number) => globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em),
)
: [], : [],
); );
this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m => this.starterMoveset = (moveData || (this.speciesStarterMoves.slice(0, 4) as StarterMoveset)).filter(m =>
@ -4062,10 +4088,15 @@ export class StarterSelectUiHandler extends MessageUiHandler {
} }
const hasEggMoves = species && speciesEggMoves.hasOwnProperty(species.speciesId); const hasEggMoves = species && speciesEggMoves.hasOwnProperty(species.speciesId);
let eggMoves = 0;
if (species) {
const { starterDataEntry } = this.getSpeciesData(this.lastSpecies.speciesId);
eggMoves = starterDataEntry.eggMoves;
}
for (let em = 0; em < 4; em++) { for (let em = 0; em < 4; em++) {
const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null; const eggMove = hasEggMoves ? allMoves[speciesEggMoves[species.speciesId][em]] : null;
const eggMoveUnlocked = eggMove && globalScene.gameData.starterData[species.speciesId].eggMoves & (1 << em); const eggMoveUnlocked = eggMove && eggMoves & (1 << em);
this.pokemonEggMoveBgs[em].setFrame( this.pokemonEggMoveBgs[em].setFrame(
PokemonType[eggMove ? eggMove.type : PokemonType.UNKNOWN].toString().toLowerCase(), PokemonType[eggMove ? eggMove.type : PokemonType.UNKNOWN].toString().toLowerCase(),
); );
@ -4335,14 +4366,12 @@ export class StarterSelectUiHandler extends MessageUiHandler {
originalStarterSelectCallback?.( originalStarterSelectCallback?.(
new Array(this.starterSpecies.length).fill(0).map((_, i) => { new Array(this.starterSpecies.length).fill(0).map((_, i) => {
const starterSpecies = thisObj.starterSpecies[i]; const starterSpecies = thisObj.starterSpecies[i];
const { starterDataEntry } = this.getSpeciesData(starterSpecies.speciesId);
return { return {
species: starterSpecies, species: starterSpecies,
dexAttr: thisObj.starterAttr[i], dexAttr: thisObj.starterAttr[i],
abilityIndex: thisObj.starterAbilityIndexes[i], abilityIndex: thisObj.starterAbilityIndexes[i],
passive: !( passive: !(starterDataEntry.passiveAttr ^ (PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)),
globalScene.gameData.starterData[starterSpecies.speciesId].passiveAttr ^
(PassiveAttr.ENABLED | PassiveAttr.UNLOCKED)
),
nature: thisObj.starterNatures[i] as Nature, nature: thisObj.starterNatures[i] as Nature,
teraType: thisObj.starterTeras[i] as PokemonType, teraType: thisObj.starterTeras[i] as PokemonType,
moveset: thisObj.starterMovesets[i], moveset: thisObj.starterMovesets[i],
@ -4519,7 +4548,8 @@ export class StarterSelectUiHandler extends MessageUiHandler {
clear(): void { clear(): void {
super.clear(); super.clear();
saveStarterPreferences(this.starterPreferences); saveStarterPreferences(this.originalStarterPreferences);
this.clearStarterPreferences();
this.cursor = -1; this.cursor = -1;
this.hideInstructions(); this.hideInstructions();
this.activeTooltip = undefined; this.activeTooltip = undefined;
@ -4562,5 +4592,6 @@ export class StarterSelectUiHandler extends MessageUiHandler {
*/ */
clearStarterPreferences() { clearStarterPreferences() {
this.starterPreferences = {}; this.starterPreferences = {};
this.originalStarterPreferences = {};
} }
} }