Merge branch 'beta' into damocleas-starter-shredder

This commit is contained in:
damocleas 2025-01-16 16:27:37 -05:00 committed by GitHub
commit cb489e10d3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 286 additions and 99 deletions

Binary file not shown.

View File

@ -869,6 +869,7 @@
"198": [0, 1, 1], "198": [0, 1, 1],
"203": [0, 1, 1], "203": [0, 1, 1],
"207": [0, 1, 1], "207": [0, 1, 1],
"212": [1, 1, 1],
"215": [0, 1, 1], "215": [0, 1, 1],
"217": [1, 1, 1], "217": [1, 1, 1],
"229": [0, 1, 1], "229": [0, 1, 1],
@ -1778,6 +1779,7 @@
"198": [0, 1, 1], "198": [0, 1, 1],
"203": [0, 1, 1], "203": [0, 1, 1],
"207": [0, 1, 1], "207": [0, 1, 1],
"212": [1, 1, 1],
"215": [0, 1, 1], "215": [0, 1, 1],
"217": [1, 1, 1], "217": [1, 1, 1],
"229": [0, 1, 1], "229": [0, 1, 1],

View File

@ -0,0 +1,41 @@
{
"0": {
"632929": "215a2d",
"f76b6b": "8cce73",
"a52929": "2f794e",
"101010": "101010",
"d63a3a": "4a9c53",
"9494a5": "9494a5",
"ffffff": "ffffff",
"b5b5ce": "b5b5ce",
"3a3a4a": "3a3a4a",
"9c6b21": "9c6b21",
"dec510": "dec510"
},
"1": {
"632929": "2f2962",
"f76b6b": "639cf7",
"a52929": "29429c",
"101010": "101010",
"d63a3a": "4263ef",
"9494a5": "6262a4",
"ffffff": "ffffff",
"b5b5ce": "b5b5ce",
"3a3a4a": "3c3c50",
"9c6b21": "131387",
"dec510": "10bdde"
},
"2": {
"632929": "645117",
"f76b6b": "c59f29",
"a52929": "b88619",
"101010": "101010",
"d63a3a": "ffca2a",
"9494a5": "3c4543",
"ffffff": "ffffff",
"b5b5ce": "b5b5ce",
"3a3a4a": "282d2c",
"9c6b21": "9c6b21",
"dec510": "dec510"
}
}

View File

@ -0,0 +1,41 @@
{
"0": {
"632929": "215a2d",
"f76b6b": "8cce73",
"101010": "101010",
"3a3a4a": "3a3a4a",
"ffffff": "ffffff",
"d63a3a": "4a9c53",
"b5b5ce": "b5b5ce",
"9494a5": "9494a5",
"a52929": "2f794e",
"dec510": "dec510",
"9c6b21": "9c6b21"
},
"1": {
"632929": "2f2962",
"f76b6b": "639cf7",
"101010": "101010",
"3a3a4a": "3c3c50",
"ffffff": "ffffff",
"d63a3a": "4263ef",
"b5b5ce": "b5b5ce",
"9494a5": "6262a4",
"a52929": "29429c",
"dec510": "10bdde",
"9c6b21": "131387"
},
"2": {
"632929": "645117",
"f76b6b": "c59f29",
"101010": "101010",
"3a3a4a": "282d2c",
"ffffff": "ffffff",
"d63a3a": "ffca2a",
"b5b5ce": "b5b5ce",
"9494a5": "3c4543",
"a52929": "b88619",
"dec510": "dec510",
"9c6b21": "9c6b21"
}
}

@ -1 +1 @@
Subproject commit 4928231e22a06dce2b55d9b04cd2b283c2ee4afb Subproject commit acad8499a4ca488a9871902de140f635235f309a

View File

@ -363,28 +363,30 @@ export default class BattleScene extends SceneBase {
/** /**
* Load the variant assets for the given sprite and stores them in {@linkcode variantColorCache} * Load the variant assets for the given sprite and stores them in {@linkcode variantColorCache}
*/ */
loadPokemonVariantAssets(spriteKey: string, fileRoot: string, variant?: Variant) { public async loadPokemonVariantAssets(spriteKey: string, fileRoot: string, variant?: Variant): Promise<void> {
const useExpSprite = this.experimentalSprites && this.hasExpSprite(spriteKey); const useExpSprite = this.experimentalSprites && this.hasExpSprite(spriteKey);
if (useExpSprite) { if (useExpSprite) {
fileRoot = `exp/${fileRoot}`; fileRoot = `exp/${fileRoot}`;
} }
let variantConfig = variantData; let variantConfig = variantData;
fileRoot.split("/").map(p => variantConfig ? variantConfig = variantConfig[p] : null); fileRoot.split("/").map((p) => (variantConfig ? (variantConfig = variantConfig[p]) : null));
const variantSet = variantConfig as VariantSet; const variantSet = variantConfig as VariantSet;
if (variantSet && (variant !== undefined && variantSet[variant] === 1)) {
const populateVariantColors = (key: string): Promise<void> => { return new Promise<void>((resolve) => {
return new Promise(resolve => { if (variantSet && variant !== undefined && variantSet[variant] === 1) {
if (variantColorCache.hasOwnProperty(key)) { if (variantColorCache.hasOwnProperty(spriteKey)) {
return resolve(); return resolve();
} }
this.cachedFetch(`./images/pokemon/variant/${fileRoot}.json`).then(res => res.json()).then(c => { this.cachedFetch(`./images/pokemon/variant/${fileRoot}.json`)
variantColorCache[key] = c; .then((res) => res.json())
.then((c) => {
variantColorCache[spriteKey] = c;
resolve(); resolve();
}); });
}); } else {
}; resolve();
populateVariantColors(spriteKey);
} }
});
} }
async preload() { async preload() {
@ -1191,6 +1193,9 @@ export default class BattleScene extends SceneBase {
onComplete: () => { onComplete: () => {
this.clearPhaseQueue(); this.clearPhaseQueue();
this.ui.freeUIData();
this.uiContainer.remove(this.ui, true);
this.uiContainer.destroy();
this.children.removeAll(true); this.children.removeAll(true);
this.game.domContainer.innerHTML = ""; this.game.domContainer.innerHTML = "";
this.launchBattle(); this.launchBattle();

View File

@ -88,6 +88,11 @@ export enum ChallengeType {
* Modifies what weight AI pokemon have when generating movesets. UNIMPLEMENTED. * Modifies what weight AI pokemon have when generating movesets. UNIMPLEMENTED.
*/ */
MOVE_WEIGHT, MOVE_WEIGHT,
/**
* Modifies what the pokemon stats for Flip Stat Mode.
*/
FLIP_STAT,
} }
/** /**
@ -405,6 +410,16 @@ export abstract class Challenge {
applyMoveWeight(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean { applyMoveWeight(pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, level: Utils.IntegerHolder): boolean {
return false; return false;
} }
/**
* An apply function for FlipStats. Derived classes should alter this.
* @param pokemon {@link Pokemon} What pokemon would learn the move.
* @param baseStats What are the stats to flip.
* @returns {@link boolean} Whether this function did anything.
*/
applyFlipStat(pokemon: Pokemon, baseStats: number[]) {
return false;
}
} }
type ChallengeCondition = (data: GameData) => boolean; type ChallengeCondition = (data: GameData) => boolean;
@ -705,6 +720,33 @@ export class InverseBattleChallenge extends Challenge {
} }
} }
/**
* Implements a flip stat challenge.
*/
export class FlipStatChallenge extends Challenge {
constructor() {
super(Challenges.FLIP_STAT, 1);
}
override applyFlipStat(pokemon: Pokemon, baseStats: number[]) {
const origStats = Utils.deepCopy(baseStats);
baseStats[0] = origStats[5];
baseStats[1] = origStats[4];
baseStats[2] = origStats[3];
baseStats[3] = origStats[2];
baseStats[4] = origStats[1];
baseStats[5] = origStats[0];
return true;
}
static loadChallenge(source: FlipStatChallenge | any): FlipStatChallenge {
const newChallenge = new FlipStatChallenge();
newChallenge.value = source.value;
newChallenge.severity = source.severity;
return newChallenge;
}
}
/** /**
* Lowers the amount of starter points available. * Lowers the amount of starter points available.
*/ */
@ -890,6 +932,9 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
* @returns True if any challenge was successfully applied. * @returns True if any challenge was successfully applied.
*/ */
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_WEIGHT, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, weight: Utils.IntegerHolder): boolean; export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.MOVE_WEIGHT, pokemon: Pokemon, moveSource: MoveSourceType, move: Moves, weight: Utils.IntegerHolder): boolean;
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType.FLIP_STAT, pokemon: Pokemon, baseStats: number[]): boolean;
export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean { export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType, ...args: any[]): boolean {
let ret = false; let ret = false;
gameMode.challenges.forEach(c => { gameMode.challenges.forEach(c => {
@ -934,6 +979,9 @@ export function applyChallenges(gameMode: GameMode, challengeType: ChallengeType
case ChallengeType.MOVE_WEIGHT: case ChallengeType.MOVE_WEIGHT:
ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]); ret ||= c.applyMoveWeight(args[0], args[1], args[2], args[3]);
break; break;
case ChallengeType.FLIP_STAT:
ret ||= c.applyFlipStat(args[0], args[1]);
break;
} }
} }
}); });
@ -959,6 +1007,8 @@ export function copyChallenge(source: Challenge | any): Challenge {
return FreshStartChallenge.loadChallenge(source); return FreshStartChallenge.loadChallenge(source);
case Challenges.INVERSE_BATTLE: case Challenges.INVERSE_BATTLE:
return InverseBattleChallenge.loadChallenge(source); return InverseBattleChallenge.loadChallenge(source);
case Challenges.FLIP_STAT:
return FlipStatChallenge.loadChallenge(source);
} }
throw new Error("Unknown challenge copied"); throw new Error("Unknown challenge copied");
} }
@ -971,5 +1021,6 @@ export function initChallenges() {
new SingleTypeChallenge(), new SingleTypeChallenge(),
new FreshStartChallenge(), new FreshStartChallenge(),
new InverseBattleChallenge(), new InverseBattleChallenge(),
new FlipStatChallenge()
); );
} }

View File

@ -7878,31 +7878,6 @@ export class LastResortAttr extends MoveAttr {
} }
} }
/**
* The move only works if the target has a transferable held item
* @extends MoveAttr
* @see {@linkcode getCondition}
*/
export class AttackedByItemAttr extends MoveAttr {
/**
* @returns the {@linkcode MoveConditionFunc} for this {@linkcode Move}
*/
getCondition(): MoveConditionFunc {
return (user: Pokemon, target: Pokemon, move: Move) => {
const heldItems = target.getHeldItems().filter(i => i.isTransferable);
if (heldItems.length === 0) {
return false;
}
const itemName = heldItems[0]?.type?.name ?? "item";
globalScene.queueMessage(i18next.t("moveTriggers:attackedByItem", { pokemonName: getPokemonNameWithAffix(target), itemName: itemName }));
return true;
};
}
}
export class VariableTargetAttr extends MoveAttr { export class VariableTargetAttr extends MoveAttr {
private targetChangeFunc: (user: Pokemon, target: Pokemon, move: Move) => number; private targetChangeFunc: (user: Pokemon, target: Pokemon, move: Move) => number;
@ -7976,6 +7951,18 @@ const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Po
const failIfGhostTypeCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => !target.isOfType(Type.GHOST); const failIfGhostTypeCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => !target.isOfType(Type.GHOST);
const failIfNoTargetHeldItemsCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => target.getHeldItems().filter(i => i.isTransferable)?.length > 0;
const attackedByItemMessageFunc = (user: Pokemon, target: Pokemon, move: Move) => {
const heldItems = target.getHeldItems().filter(i => i.isTransferable);
if (heldItems.length === 0) {
return "";
}
const itemName = heldItems[0]?.type?.name ?? "item";
const message: string = i18next.t("moveTriggers:attackedByItem", { pokemonName: getPokemonNameWithAffix(target), itemName: itemName });
return message;
};
export type MoveAttrFilter = (attr: MoveAttr) => boolean; export type MoveAttrFilter = (attr: MoveAttr) => boolean;
function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon | null, target: Pokemon | null, move: Move, args: any[]): Promise<void> { function applyMoveAttrsInternal(attrFilter: MoveAttrFilter, user: Pokemon | null, target: Pokemon | null, move: Move, args: any[]): Promise<void> {
@ -10641,7 +10628,8 @@ export function initMoves() {
new AttackMove(Moves.LASH_OUT, Type.DARK, MoveCategory.PHYSICAL, 75, 100, 5, -1, 0, 8) new AttackMove(Moves.LASH_OUT, Type.DARK, MoveCategory.PHYSICAL, 75, 100, 5, -1, 0, 8)
.attr(MovePowerMultiplierAttr, (user, _target, _move) => user.turnData.statStagesDecreased ? 2 : 1), .attr(MovePowerMultiplierAttr, (user, _target, _move) => user.turnData.statStagesDecreased ? 2 : 1),
new AttackMove(Moves.POLTERGEIST, Type.GHOST, MoveCategory.PHYSICAL, 110, 90, 5, -1, 0, 8) new AttackMove(Moves.POLTERGEIST, Type.GHOST, MoveCategory.PHYSICAL, 110, 90, 5, -1, 0, 8)
.attr(AttackedByItemAttr) .condition(failIfNoTargetHeldItemsCondition)
.attr(PreMoveMessageAttr, attackedByItemMessageFunc)
.makesContact(false), .makesContact(false),
new StatusMove(Moves.CORROSIVE_GAS, Type.POISON, 100, 40, -1, 0, 8) new StatusMove(Moves.CORROSIVE_GAS, Type.POISON, 100, 40, -1, 0, 8)
.target(MoveTarget.ALL_NEAR_OTHERS) .target(MoveTarget.ALL_NEAR_OTHERS)

View File

@ -516,8 +516,7 @@ export abstract class PokemonSpeciesForm {
globalScene.anims.get(spriteKey).frameRate = 10; globalScene.anims.get(spriteKey).frameRate = 10;
} }
const spritePath = this.getSpriteAtlasPath(female, formIndex, shiny, variant).replace("variant/", "").replace(/_[1-3]$/, ""); const spritePath = this.getSpriteAtlasPath(female, formIndex, shiny, variant).replace("variant/", "").replace(/_[1-3]$/, "");
globalScene.loadPokemonVariantAssets(spriteKey, spritePath, variant); globalScene.loadPokemonVariantAssets(spriteKey, spritePath, variant).then(() => resolve());
resolve();
}); });
if (startLoad) { if (startLoad) {
if (!globalScene.load.isLoading()) { if (!globalScene.load.isLoading()) {
@ -948,19 +947,6 @@ export class PokemonForm extends PokemonSpeciesForm {
} }
} }
export const noStarterFormKeys: string[] = [
SpeciesFormKey.MEGA,
SpeciesFormKey.MEGA_X,
SpeciesFormKey.MEGA_Y,
SpeciesFormKey.PRIMAL,
SpeciesFormKey.ORIGIN,
SpeciesFormKey.THERIAN,
SpeciesFormKey.GIGANTAMAX,
SpeciesFormKey.GIGANTAMAX_RAPID,
SpeciesFormKey.GIGANTAMAX_SINGLE,
SpeciesFormKey.ETERNAMAX
].map(k => k.toString());
/** /**
* Method to get the daily list of starters with Pokerus. * Method to get the daily list of starters with Pokerus.
* @returns A list of starters with Pokerus * @returns A list of starters with Pokerus

View File

@ -5,4 +5,5 @@ export enum Challenges {
LOWER_STARTER_POINTS, LOWER_STARTER_POINTS,
FRESH_START, FRESH_START,
INVERSE_BATTLE, INVERSE_BATTLE,
FLIP_STAT,
} }

View File

@ -215,11 +215,12 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
resolve(); resolve();
} }
const shinyPromises: Promise<void>[] = [];
this.spriteConfigs.forEach((config) => { this.spriteConfigs.forEach((config) => {
if (config.isPokemon) { if (config.isPokemon) {
globalScene.loadPokemonAtlas(config.spriteKey, config.fileRoot); globalScene.loadPokemonAtlas(config.spriteKey, config.fileRoot);
if (config.isShiny) { if (config.isShiny) {
globalScene.loadPokemonVariantAssets(config.spriteKey, config.fileRoot, config.variant); shinyPromises.push(globalScene.loadPokemonVariantAssets(config.spriteKey, config.fileRoot, config.variant));
} }
} else if (config.isItem) { } else if (config.isItem) {
globalScene.loadAtlas("items", ""); globalScene.loadAtlas("items", "");
@ -254,7 +255,7 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
return true; return true;
}); });
resolve(); Promise.all(shinyPromises).then(() => resolve());
}); });
if (!globalScene.load.isLoading()) { if (!globalScene.load.isLoading()) {

View File

@ -1057,6 +1057,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
calculateBaseStats(): number[] { calculateBaseStats(): number[] {
const baseStats = this.getSpeciesForm(true).baseStats.slice(0); const baseStats = this.getSpeciesForm(true).baseStats.slice(0);
applyChallenges(globalScene.gameMode, ChallengeType.FLIP_STAT, this, baseStats);
// Shuckle Juice // Shuckle Juice
globalScene.applyModifiers(PokemonBaseStatTotalModifier, this.isPlayer(), this, baseStats); globalScene.applyModifiers(PokemonBaseStatTotalModifier, this.isPlayer(), this, baseStats);
// Old Gateau // Old Gateau

View File

@ -319,6 +319,7 @@ export class LoadingScene extends SceneBase {
this.loadSe("pb_move"); this.loadSe("pb_move");
this.loadSe("pb_catch"); this.loadSe("pb_catch");
this.loadSe("pb_lock"); this.loadSe("pb_lock");
this.loadSe("crit_throw");
this.loadSe("pb_tray_enter"); this.loadSe("pb_tray_enter");
this.loadSe("pb_tray_ball"); this.loadSe("pb_tray_ball");

View File

@ -64,7 +64,7 @@ export class AttemptCapturePhase extends PokemonPhase {
this.pokeball.setOrigin(0.5, 0.625); this.pokeball.setOrigin(0.5, 0.625);
globalScene.field.add(this.pokeball); globalScene.field.add(this.pokeball);
globalScene.playSound("se/pb_throw", isCritical ? { rate: 0.2 } : undefined); // Crit catch throws are higher pitched globalScene.playSound(isCritical ? "se/crit_throw" : "se/pb_throw");
globalScene.time.delayedCall(300, () => { globalScene.time.delayedCall(300, () => {
globalScene.field.moveBelow(this.pokeball as Phaser.GameObjects.GameObject, pokemon); globalScene.field.moveBelow(this.pokeball as Phaser.GameObjects.GameObject, pokemon);
}); });

View File

@ -5,7 +5,7 @@ import i18next from "i18next";
import * as Utils from "../utils"; import * as Utils from "../utils";
import { PlayerGender } from "#enums/player-gender"; import { PlayerGender } from "#enums/player-gender";
import type { Challenge } from "#app/data/challenge"; import type { Challenge } from "#app/data/challenge";
import { FreshStartChallenge, SingleGenerationChallenge, SingleTypeChallenge, InverseBattleChallenge } from "#app/data/challenge"; import { FlipStatChallenge, FreshStartChallenge, SingleGenerationChallenge, SingleTypeChallenge, InverseBattleChallenge } from "#app/data/challenge";
import type { ConditionFn } from "#app/@types/common"; import type { ConditionFn } from "#app/@types/common";
import { Stat, getShortenedStatKey } from "#app/enums/stat"; import { Stat, getShortenedStatKey } from "#app/enums/stat";
import { Challenges } from "#app/enums/challenges"; import { Challenges } from "#app/enums/challenges";
@ -280,6 +280,10 @@ export function getAchievementDescription(localizationKey: string): string {
return i18next.t("achv:FRESH_START.description", { context: genderStr }); return i18next.t("achv:FRESH_START.description", { context: genderStr });
case "INVERSE_BATTLE": case "INVERSE_BATTLE":
return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr }); return i18next.t("achv:INVERSE_BATTLE.description", { context: genderStr });
case "FLIP_STATS":
return i18next.t("achv:FLIP_STATS.description", { context: genderStr });
case "FLIP_INVERSE":
return i18next.t("achv:FLIP_INVERSE.description", { context: genderStr });
case "BREEDERS_IN_SPACE": case "BREEDERS_IN_SPACE":
return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr }); return i18next.t("achv:BREEDERS_IN_SPACE.description", { context: genderStr });
default: default:
@ -288,6 +292,7 @@ export function getAchievementDescription(localizationKey: string): string {
} }
export const achvs = { export const achvs = {
_10K_MONEY: new MoneyAchv("10K_MONEY", "", 10000, "nugget", 10), _10K_MONEY: new MoneyAchv("10K_MONEY", "", 10000, "nugget", 10),
_100K_MONEY: new MoneyAchv("100K_MONEY", "", 100000, "big_nugget", 25).setSecret(true), _100K_MONEY: new MoneyAchv("100K_MONEY", "", 100000, "big_nugget", 25).setSecret(true),
@ -330,35 +335,37 @@ export const achvs = {
PERFECT_IVS: new Achv("PERFECT_IVS", "", "PERFECT_IVS.description", "blunder_policy", 100), PERFECT_IVS: new Achv("PERFECT_IVS", "", "PERFECT_IVS.description", "blunder_policy", 100),
CLASSIC_VICTORY: new Achv("CLASSIC_VICTORY", "", "CLASSIC_VICTORY.description", "relic_crown", 150, (_) => globalScene.gameData.gameStats.sessionsWon === 0), CLASSIC_VICTORY: new Achv("CLASSIC_VICTORY", "", "CLASSIC_VICTORY.description", "relic_crown", 150, (_) => globalScene.gameData.gameStats.sessionsWon === 0),
UNEVOLVED_CLASSIC_VICTORY: new Achv("UNEVOLVED_CLASSIC_VICTORY", "", "UNEVOLVED_CLASSIC_VICTORY.description", "eviolite", 175, (_) => globalScene.getPlayerParty().some(p => p.getSpeciesForm(true).speciesId in pokemonEvolutions)), UNEVOLVED_CLASSIC_VICTORY: new Achv("UNEVOLVED_CLASSIC_VICTORY", "", "UNEVOLVED_CLASSIC_VICTORY.description", "eviolite", 175, (_) => globalScene.getPlayerParty().some(p => p.getSpeciesForm(true).speciesId in pokemonEvolutions)),
MONO_GEN_ONE_VICTORY: new ChallengeAchv("MONO_GEN_ONE", "", "MONO_GEN_ONE.description", "ribbon_gen1", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 1 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_ONE_VICTORY: new ChallengeAchv("MONO_GEN_ONE", "", "MONO_GEN_ONE.description", "ribbon_gen1", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 1 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_TWO_VICTORY: new ChallengeAchv("MONO_GEN_TWO", "", "MONO_GEN_TWO.description", "ribbon_gen2", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 2 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_TWO_VICTORY: new ChallengeAchv("MONO_GEN_TWO", "", "MONO_GEN_TWO.description", "ribbon_gen2", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 2 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_THREE_VICTORY: new ChallengeAchv("MONO_GEN_THREE", "", "MONO_GEN_THREE.description", "ribbon_gen3", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 3 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_THREE_VICTORY: new ChallengeAchv("MONO_GEN_THREE", "", "MONO_GEN_THREE.description", "ribbon_gen3", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 3 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_FOUR_VICTORY: new ChallengeAchv("MONO_GEN_FOUR", "", "MONO_GEN_FOUR.description", "ribbon_gen4", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 4 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_FOUR_VICTORY: new ChallengeAchv("MONO_GEN_FOUR", "", "MONO_GEN_FOUR.description", "ribbon_gen4", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 4 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_FIVE_VICTORY: new ChallengeAchv("MONO_GEN_FIVE", "", "MONO_GEN_FIVE.description", "ribbon_gen5", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 5 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_FIVE_VICTORY: new ChallengeAchv("MONO_GEN_FIVE", "", "MONO_GEN_FIVE.description", "ribbon_gen5", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 5 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_SIX_VICTORY: new ChallengeAchv("MONO_GEN_SIX", "", "MONO_GEN_SIX.description", "ribbon_gen6", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 6 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_SIX_VICTORY: new ChallengeAchv("MONO_GEN_SIX", "", "MONO_GEN_SIX.description", "ribbon_gen6", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 6 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_SEVEN_VICTORY: new ChallengeAchv("MONO_GEN_SEVEN", "", "MONO_GEN_SEVEN.description", "ribbon_gen7", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 7 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_SEVEN_VICTORY: new ChallengeAchv("MONO_GEN_SEVEN", "", "MONO_GEN_SEVEN.description", "ribbon_gen7", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 7 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_EIGHT_VICTORY: new ChallengeAchv("MONO_GEN_EIGHT", "", "MONO_GEN_EIGHT.description", "ribbon_gen8", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 8 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_EIGHT_VICTORY: new ChallengeAchv("MONO_GEN_EIGHT", "", "MONO_GEN_EIGHT.description", "ribbon_gen8", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 8 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GEN_NINE_VICTORY: new ChallengeAchv("MONO_GEN_NINE", "", "MONO_GEN_NINE.description", "ribbon_gen9", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 9 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GEN_NINE_VICTORY: new ChallengeAchv("MONO_GEN_NINE", "", "MONO_GEN_NINE.description", "ribbon_gen9", 100, (c) => c instanceof SingleGenerationChallenge && c.value === 9 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_NORMAL: new ChallengeAchv("MONO_NORMAL", "", "MONO_NORMAL.description", "silk_scarf", 100, (c) => c instanceof SingleTypeChallenge && c.value === 1 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_NORMAL: new ChallengeAchv("MONO_NORMAL", "", "MONO_NORMAL.description", "silk_scarf", 100, (c) => c instanceof SingleTypeChallenge && c.value === 1 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_FIGHTING: new ChallengeAchv("MONO_FIGHTING", "", "MONO_FIGHTING.description", "black_belt", 100, (c) => c instanceof SingleTypeChallenge && c.value === 2 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_FIGHTING: new ChallengeAchv("MONO_FIGHTING", "", "MONO_FIGHTING.description", "black_belt", 100, (c) => c instanceof SingleTypeChallenge && c.value === 2 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_FLYING: new ChallengeAchv("MONO_FLYING", "", "MONO_FLYING.description", "sharp_beak", 100, (c) => c instanceof SingleTypeChallenge && c.value === 3 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_FLYING: new ChallengeAchv("MONO_FLYING", "", "MONO_FLYING.description", "sharp_beak", 100, (c) => c instanceof SingleTypeChallenge && c.value === 3 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_POISON: new ChallengeAchv("MONO_POISON", "", "MONO_POISON.description", "poison_barb", 100, (c) => c instanceof SingleTypeChallenge && c.value === 4 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_POISON: new ChallengeAchv("MONO_POISON", "", "MONO_POISON.description", "poison_barb", 100, (c) => c instanceof SingleTypeChallenge && c.value === 4 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GROUND: new ChallengeAchv("MONO_GROUND", "", "MONO_GROUND.description", "soft_sand", 100, (c) => c instanceof SingleTypeChallenge && c.value === 5 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GROUND: new ChallengeAchv("MONO_GROUND", "", "MONO_GROUND.description", "soft_sand", 100, (c) => c instanceof SingleTypeChallenge && c.value === 5 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_ROCK: new ChallengeAchv("MONO_ROCK", "", "MONO_ROCK.description", "hard_stone", 100, (c) => c instanceof SingleTypeChallenge && c.value === 6 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_ROCK: new ChallengeAchv("MONO_ROCK", "", "MONO_ROCK.description", "hard_stone", 100, (c) => c instanceof SingleTypeChallenge && c.value === 6 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_BUG: new ChallengeAchv("MONO_BUG", "", "MONO_BUG.description", "silver_powder", 100, (c) => c instanceof SingleTypeChallenge && c.value === 7 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_BUG: new ChallengeAchv("MONO_BUG", "", "MONO_BUG.description", "silver_powder", 100, (c) => c instanceof SingleTypeChallenge && c.value === 7 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GHOST: new ChallengeAchv("MONO_GHOST", "", "MONO_GHOST.description", "spell_tag", 100, (c) => c instanceof SingleTypeChallenge && c.value === 8 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GHOST: new ChallengeAchv("MONO_GHOST", "", "MONO_GHOST.description", "spell_tag", 100, (c) => c instanceof SingleTypeChallenge && c.value === 8 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_STEEL: new ChallengeAchv("MONO_STEEL", "", "MONO_STEEL.description", "metal_coat", 100, (c) => c instanceof SingleTypeChallenge && c.value === 9 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_STEEL: new ChallengeAchv("MONO_STEEL", "", "MONO_STEEL.description", "metal_coat", 100, (c) => c instanceof SingleTypeChallenge && c.value === 9 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_FIRE: new ChallengeAchv("MONO_FIRE", "", "MONO_FIRE.description", "charcoal", 100, (c) => c instanceof SingleTypeChallenge && c.value === 10 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_FIRE: new ChallengeAchv("MONO_FIRE", "", "MONO_FIRE.description", "charcoal", 100, (c) => c instanceof SingleTypeChallenge && c.value === 10 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_WATER: new ChallengeAchv("MONO_WATER", "", "MONO_WATER.description", "mystic_water", 100, (c) => c instanceof SingleTypeChallenge && c.value === 11 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_WATER: new ChallengeAchv("MONO_WATER", "", "MONO_WATER.description", "mystic_water", 100, (c) => c instanceof SingleTypeChallenge && c.value === 11 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_GRASS: new ChallengeAchv("MONO_GRASS", "", "MONO_GRASS.description", "miracle_seed", 100, (c) => c instanceof SingleTypeChallenge && c.value === 12 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_GRASS: new ChallengeAchv("MONO_GRASS", "", "MONO_GRASS.description", "miracle_seed", 100, (c) => c instanceof SingleTypeChallenge && c.value === 12 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_ELECTRIC: new ChallengeAchv("MONO_ELECTRIC", "", "MONO_ELECTRIC.description", "magnet", 100, (c) => c instanceof SingleTypeChallenge && c.value === 13 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_ELECTRIC: new ChallengeAchv("MONO_ELECTRIC", "", "MONO_ELECTRIC.description", "magnet", 100, (c) => c instanceof SingleTypeChallenge && c.value === 13 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_PSYCHIC: new ChallengeAchv("MONO_PSYCHIC", "", "MONO_PSYCHIC.description", "twisted_spoon", 100, (c) => c instanceof SingleTypeChallenge && c.value === 14 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_PSYCHIC: new ChallengeAchv("MONO_PSYCHIC", "", "MONO_PSYCHIC.description", "twisted_spoon", 100, (c) => c instanceof SingleTypeChallenge && c.value === 14 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_ICE: new ChallengeAchv("MONO_ICE", "", "MONO_ICE.description", "never_melt_ice", 100, (c) => c instanceof SingleTypeChallenge && c.value === 15 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_ICE: new ChallengeAchv("MONO_ICE", "", "MONO_ICE.description", "never_melt_ice", 100, (c) => c instanceof SingleTypeChallenge && c.value === 15 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_DRAGON: new ChallengeAchv("MONO_DRAGON", "", "MONO_DRAGON.description", "dragon_fang", 100, (c) => c instanceof SingleTypeChallenge && c.value === 16 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_DRAGON: new ChallengeAchv("MONO_DRAGON", "", "MONO_DRAGON.description", "dragon_fang", 100, (c) => c instanceof SingleTypeChallenge && c.value === 16 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_DARK: new ChallengeAchv("MONO_DARK", "", "MONO_DARK.description", "black_glasses", 100, (c) => c instanceof SingleTypeChallenge && c.value === 17 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_DARK: new ChallengeAchv("MONO_DARK", "", "MONO_DARK.description", "black_glasses", 100, (c) => c instanceof SingleTypeChallenge && c.value === 17 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
MONO_FAIRY: new ChallengeAchv("MONO_FAIRY", "", "MONO_FAIRY.description", "fairy_feather", 100, (c) => c instanceof SingleTypeChallenge && c.value === 18 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), MONO_FAIRY: new ChallengeAchv("MONO_FAIRY", "", "MONO_FAIRY.description", "fairy_feather", 100, (c) => c instanceof SingleTypeChallenge && c.value === 18 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
FRESH_START: new ChallengeAchv("FRESH_START", "", "FRESH_START.description", "reviver_seed", 100, (c) => c instanceof FreshStartChallenge && c.value > 0 && !globalScene.gameMode.challenges.some(c => c.id === Challenges.INVERSE_BATTLE && c.value > 0)), FRESH_START: new ChallengeAchv("FRESH_START", "", "FRESH_START.description", "reviver_seed", 100, (c) => c instanceof FreshStartChallenge && c.value > 0 && !globalScene.gameMode.challenges.some(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
INVERSE_BATTLE: new ChallengeAchv("INVERSE_BATTLE", "", "INVERSE_BATTLE.description", "inverse", 100, c => c instanceof InverseBattleChallenge && c.value > 0), INVERSE_BATTLE: new ChallengeAchv("INVERSE_BATTLE", "", "INVERSE_BATTLE.description", "inverse", 100, (c) => c instanceof InverseBattleChallenge && c.value > 0),
FLIP_STATS: new ChallengeAchv("FLIP_STATS", "", "FLIP_STATS.description", "dubious_disc", 100, (c) => c instanceof FlipStatChallenge && c.value > 0),
FLIP_INVERSE: new ChallengeAchv("FLIP_INVERSE", "", "FLIP_INVERSE.description", "cracked_pot", 100, (c) => c instanceof FlipStatChallenge && c.value > 0 && globalScene.gameMode.challenges.every(c => [ Challenges.INVERSE_BATTLE, Challenges.FLIP_STAT ].includes(c.id) && c.value > 0)),
BREEDERS_IN_SPACE: new Achv("BREEDERS_IN_SPACE", "", "BREEDERS_IN_SPACE.description", "moon_stone", 50).setSecret(), BREEDERS_IN_SPACE: new Achv("BREEDERS_IN_SPACE", "", "BREEDERS_IN_SPACE.description", "moon_stone", 50).setSecret(),
}; };

View File

@ -6,7 +6,7 @@ import type { EnemyPokemon, PlayerPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions"; import { pokemonPrevolutions } from "#app/data/balance/pokemon-evolutions";
import type PokemonSpecies from "#app/data/pokemon-species"; import type PokemonSpecies from "#app/data/pokemon-species";
import { allSpecies, getPokemonSpecies, noStarterFormKeys } from "#app/data/pokemon-species"; import { allSpecies, getPokemonSpecies } from "#app/data/pokemon-species";
import { speciesStarterCosts } from "#app/data/balance/starters"; import { speciesStarterCosts } from "#app/data/balance/starters";
import * as Utils from "#app/utils"; import * as Utils from "#app/utils";
import Overrides from "#app/overrides"; import Overrides from "#app/overrides";
@ -1619,9 +1619,6 @@ export class GameData {
const dexEntry = this.dexData[species.speciesId]; const dexEntry = this.dexData[species.speciesId];
const caughtAttr = dexEntry.caughtAttr; const caughtAttr = dexEntry.caughtAttr;
const formIndex = pokemon.formIndex; const formIndex = pokemon.formIndex;
if (noStarterFormKeys.includes(pokemon.getFormKey())) {
pokemon.formIndex = 0;
}
const dexAttr = pokemon.getDexAttr(); const dexAttr = pokemon.getDexAttr();
pokemon.formIndex = formIndex; pokemon.formIndex = formIndex;

View File

@ -364,6 +364,8 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
success = this.setCursor(0); success = this.setCursor(0);
} else if (this.rowCursor < this.shopOptionsRows.length + 1) { } else if (this.rowCursor < this.shopOptionsRows.length + 1) {
success = this.setRowCursor(this.rowCursor + 1); success = this.setRowCursor(this.rowCursor + 1);
} else {
success = this.setRowCursor(0);
} }
break; break;
case Button.DOWN: case Button.DOWN:
@ -371,13 +373,15 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
success = this.setRowCursor(this.rowCursor - 1); success = this.setRowCursor(this.rowCursor - 1);
} else if (this.lockRarityButtonContainer.visible && this.cursor === 0) { } else if (this.lockRarityButtonContainer.visible && this.cursor === 0) {
success = this.setCursor(3); success = this.setCursor(3);
} else {
success = this.setRowCursor(this.shopOptionsRows.length + 1);
} }
break; break;
case Button.LEFT: case Button.LEFT:
if (!this.rowCursor) { if (!this.rowCursor) {
switch (this.cursor) { switch (this.cursor) {
case 0: case 0:
success = false; success = this.setCursor(2);
break; break;
case 1: case 1:
if (this.lockRarityButtonContainer.visible) { if (this.lockRarityButtonContainer.visible) {
@ -395,11 +399,21 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
success = false; success = false;
} }
break; break;
case 3:
if (this.lockRarityButtonContainer.visible) {
success = this.setCursor(2);
} else {
success = false;
}
} }
} else if (this.cursor) { } else if (this.cursor) {
success = this.setCursor(this.cursor - 1); success = this.setCursor(this.cursor - 1);
} else if (this.rowCursor === 1 && this.rerollButtonContainer.visible) { } else {
success = this.setRowCursor(0); if (this.rowCursor === 1 && this.options.length === 0) {
success = false;
} else {
success = this.setCursor(this.getRowItems(this.rowCursor) - 1);
}
} }
break; break;
case Button.RIGHT: case Button.RIGHT:
@ -416,7 +430,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
success = this.setCursor(2); success = this.setCursor(2);
break; break;
case 2: case 2:
success = false; success = this.setCursor(0);
break; break;
case 3: case 3:
if (this.transferButtonContainer.visible) { if (this.transferButtonContainer.visible) {
@ -428,8 +442,12 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
} }
} else if (this.cursor < this.getRowItems(this.rowCursor) - 1) { } else if (this.cursor < this.getRowItems(this.rowCursor) - 1) {
success = this.setCursor(this.cursor + 1); success = this.setCursor(this.cursor + 1);
} else if (this.rowCursor === 1 && this.transferButtonContainer.visible) { } else {
if (this.rowCursor === 1 && this.options.length === 0) {
success = this.setRowCursor(0); success = this.setRowCursor(0);
} else {
success = this.setCursor(0);
}
} }
break; break;
} }
@ -519,6 +537,14 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler {
newCursor = 2; newCursor = 2;
} }
} }
// Allows to find lock rarity button when looping from the top
if (rowCursor === 0 && lastRowCursor > 1 && newCursor === 0 && this.lockRarityButtonContainer.visible) {
newCursor = 3;
}
// Allows to loop to top when lock rarity button is shown
if (rowCursor === this.shopOptionsRows.length + 1 && lastRowCursor === 0 && this.cursor === 3) {
newCursor = 0;
}
this.cursor = -1; this.cursor = -1;
this.setCursor(newCursor); this.setCursor(newCursor);
return true; return true;

View File

@ -157,6 +157,12 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
success = (this.cursor === 0) ? this.setCursor(this.cursor) : this.setCursor(this.cursor - 1, cursorPosition); success = (this.cursor === 0) ? this.setCursor(this.cursor) : this.setCursor(this.cursor - 1, cursorPosition);
} else if (this.scrollCursor) { } else if (this.scrollCursor) {
success = this.setScrollCursor(this.scrollCursor - 1, cursorPosition); success = this.setScrollCursor(this.scrollCursor - 1, cursorPosition);
} else if ((this.cursor === 0) && (this.scrollCursor === 0)) {
this.setScrollCursor(SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN);
// Revert to avoid an extra session slot sticking out
this.revertSessionSlot(SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN);
this.setCursor(SLOTS_ON_SCREEN - 1);
success = true;
} }
break; break;
case Button.DOWN: case Button.DOWN:
@ -164,6 +170,11 @@ export default class SaveSlotSelectUiHandler extends MessageUiHandler {
success = this.setCursor(this.cursor + 1, cursorPosition); success = this.setCursor(this.cursor + 1, cursorPosition);
} else if (this.scrollCursor < SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN) { } else if (this.scrollCursor < SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN) {
success = this.setScrollCursor(this.scrollCursor + 1, cursorPosition); success = this.setScrollCursor(this.scrollCursor + 1, cursorPosition);
} else if ((this.cursor === SLOTS_ON_SCREEN - 1) && (this.scrollCursor === SESSION_SLOTS_COUNT - SLOTS_ON_SCREEN)) {
this.setScrollCursor(0);
this.revertSessionSlot(SLOTS_ON_SCREEN - 1);
this.setCursor(0);
success = true;
} }
break; break;
case Button.RIGHT: case Button.RIGHT:

View File

@ -89,6 +89,13 @@ export class NavigationManager {
} }
} }
/**
* Removes menus from the manager in preparation for reset
*/
public clearNavigationMenus() {
this.navigationMenus.length = 0;
}
} }
export default class NavigationMenu extends Phaser.GameObjects.Container { export default class NavigationMenu extends Phaser.GameObjects.Container {

View File

@ -2698,6 +2698,11 @@ export default class StarterSelectUiHandler extends MessageUiHandler {
this.updateScroll(); this.updateScroll();
}; };
override destroy(): void {
// Without this the reference gets hung up and no startercontainers get GCd
this.starterContainers = [];
}
updateScroll = () => { updateScroll = () => {
const maxColumns = 9; const maxColumns = 9;
const maxRows = 9; const maxRows = 9;

View File

@ -62,4 +62,9 @@ export default abstract class UiHandler {
clear() { clear() {
this.active = false; this.active = false;
} }
/**
* To be implemented by individual handlers when necessary to free memory
* Called when {@linkcode BattleScene} is reset
*/
destroy(): void {}
} }

View File

@ -53,6 +53,7 @@ import TestDialogueUiHandler from "#app/ui/test-dialogue-ui-handler";
import AutoCompleteUiHandler from "./autocomplete-ui-handler"; import AutoCompleteUiHandler from "./autocomplete-ui-handler";
import { Device } from "#enums/devices"; import { Device } from "#enums/devices";
import MysteryEncounterUiHandler from "./mystery-encounter-ui-handler"; import MysteryEncounterUiHandler from "./mystery-encounter-ui-handler";
import { NavigationManager } from "./settings/navigationMenu";
export enum Mode { export enum Mode {
MESSAGE, MESSAGE,
@ -614,4 +615,14 @@ export default class UI extends Phaser.GameObjects.Container {
return globalScene.inputMethod; return globalScene.inputMethod;
} }
} }
/**
* Attempts to free memory held by UI handlers
* and clears menus from {@linkcode NavigationManager} to prepare for reset
*/
public freeUIData(): void {
this.handlers.forEach(h => h.destroy());
this.handlers = [];
NavigationManager.getInstance().clearNavigationMenus();
}
} }