diff --git a/src/battle-scene.ts b/src/battle-scene.ts index 516662617f1..8665f1e97e5 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -1674,7 +1674,12 @@ export default class BattleScene extends SceneBase { this.scoreText.setVisible(this.gameMode.isDaily); } - updateAndShowText(duration: integer): void { + /** + * Displays the current luck value. + * @param duration The time for this label to fade in, if it is not already visible. + * @param isDaily If true, hides the label. (This is done because Luck does not apply in Daily Mode anymore) + */ + updateAndShowText(duration: number, isDaily?: boolean): void { const labels = [ this.luckLabelText, this.luckText ]; labels.forEach(t => t.setAlpha(0)); const luckValue = getPartyLuckValue(this.getParty()); @@ -1685,12 +1690,16 @@ export default class BattleScene extends SceneBase { this.luckText.setTint(0xffef5c, 0x47ff69, 0x6b6bff, 0xff6969); } this.luckLabelText.setX((this.game.canvas.width / 6) - 2 - (this.luckText.displayWidth + 2)); + if (isDaily) { + // Hide luck label + labels.forEach(t => t.setVisible(false)); + } this.tweens.add({ targets: labels, duration: duration, alpha: 1, onComplete: () => { - labels.forEach(t => t.setVisible(true)); + labels.forEach(t => t.setVisible(!isDaily)); } }); } diff --git a/src/modifier/modifier-type.ts b/src/modifier/modifier-type.ts index a23a9c5ece2..859779977d5 100644 --- a/src/modifier/modifier-type.ts +++ b/src/modifier/modifier-type.ts @@ -1699,7 +1699,8 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.FORM_CHANGE_ITEM, (party: Pokemon[]) => Math.min(Math.ceil(party[0].scene.currentBattle.waveIndex / 50), 4) * 6, 24), new WeightedModifierType(modifierTypes.AMULET_COIN, skipInLastClassicWaveOrDefault(3)), new WeightedModifierType(modifierTypes.EVIOLITE, (party: Pokemon[]) => { - if (!party[0].scene.gameMode.isFreshStartChallenge() && party[0].scene.gameData.unlocks[Unlockables.EVIOLITE]) { + const { gameMode, gameData } = party[0].scene; + if (gameMode.isDaily || (!gameMode.isFreshStartChallenge() && gameData.isUnlocked(Unlockables.EVIOLITE))) { return party.some(p => ((p.getSpeciesForm(true).speciesId in pokemonEvolutions) || (p.isFusion() && (p.getFusionSpeciesForm(true).speciesId in pokemonEvolutions))) && !p.getHeldItems().some(i => i instanceof Modifiers.EvolutionStatBoosterModifier)) ? 10 : 0; } return 0; @@ -1777,7 +1778,7 @@ const modifierPool: ModifierPool = { new WeightedModifierType(modifierTypes.MULTI_LENS, 18), new WeightedModifierType(modifierTypes.VOUCHER_PREMIUM, (party: Pokemon[], rerollCount: integer) => !party[0].scene.gameMode.isDaily && !party[0].scene.gameMode.isEndless && !party[0].scene.gameMode.isSplicedOnly ? Math.max(5 - rerollCount * 2, 0) : 0, 5), new WeightedModifierType(modifierTypes.DNA_SPLICERS, (party: Pokemon[]) => !party[0].scene.gameMode.isSplicedOnly && party.filter(p => !p.fusionSpecies).length > 1 ? 24 : 0, 24), - new WeightedModifierType(modifierTypes.MINI_BLACK_HOLE, (party: Pokemon[]) => (!party[0].scene.gameMode.isFreshStartChallenge() && party[0].scene.gameData.unlocks[Unlockables.MINI_BLACK_HOLE]) ? 1 : 0, 1), + new WeightedModifierType(modifierTypes.MINI_BLACK_HOLE, (party: Pokemon[]) => (party[0].scene.gameMode.isDaily || (!party[0].scene.gameMode.isFreshStartChallenge() && party[0].scene.gameData.isUnlocked(Unlockables.MINI_BLACK_HOLE))) ? 1 : 0, 1), ].map(m => { m.setTier(ModifierTier.MASTER); return m; }) @@ -1969,9 +1970,13 @@ export function getModifierPoolForType(poolType: ModifierPoolType): ModifierPool } const tierWeights = [ 768 / 1024, 195 / 1024, 48 / 1024, 12 / 1024, 1 / 1024 ]; +export const itemPoolChecks: Map = new Map(); export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: ModifierPoolType, rerollCount: integer = 0) { const pool = getModifierPoolForType(poolType); + itemPoolChecks.forEach((v, k) => { + itemPoolChecks.set(k, false); + }); const ignoredIndexes = {}; const modifierTableData = {}; @@ -2008,6 +2013,9 @@ export function regenerateModifierPoolThresholds(party: Pokemon[], poolType: Mod ignoredIndexes[t].push(i++); return total; } + if (itemPoolChecks.has(modifierType.modifierType.id as ModifierTypeKeys)) { + itemPoolChecks.set(modifierType.modifierType.id as ModifierTypeKeys, true); + } thresholds.set(total, i++); return total; }, 0); @@ -2410,8 +2418,16 @@ export class ModifierTypeOption { } } +/** + * Calculates the team's luck value. + * @param party The player's party. + * @returns A value between 0 and 14, or 0 if the player is in Daily Run mode. + */ export function getPartyLuckValue(party: Pokemon[]): integer { - const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? p.getLuck() : 0) + if (party[0].scene.gameMode.isDaily) { + return 0; + } + const luck = Phaser.Math.Clamp(party.map(p => p.isAllowedInBattle() ? (p.scene.gameMode.isDaily ? 0 : p.getLuck()) : 0) .reduce((total: integer, value: integer) => total += value, 0), 0, 14); return luck || 0; } diff --git a/src/overrides.ts b/src/overrides.ts index 35ca299721b..852961db8d7 100644 --- a/src/overrides.ts +++ b/src/overrides.ts @@ -12,6 +12,7 @@ import { type PokeballCounts } from "./battle-scene"; import { Gender } from "./data/gender"; import { Variant } from "./data/variant"; import { type ModifierOverride } from "./modifier/modifier-type"; +import { Unlockables } from "./system/unlockables"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; @@ -70,8 +71,10 @@ class DefaultOverrides { [PokeballType.MASTER_BALL]: 0, }, }; + /** Forces an item to be UNLOCKED */ + readonly ITEM_UNLOCK_OVERRIDE: Unlockables[] = []; /** Set to `true` to show all tutorials */ - readonly BYPASS_TUTORIAL_SKIP: boolean = false; + readonly BYPASS_TUTORIAL_SKIP_OVERRIDE: boolean = false; // ---------------- // PLAYER OVERRIDES diff --git a/src/phases/title-phase.ts b/src/phases/title-phase.ts index 52503501837..b23a5ec0c89 100644 --- a/src/phases/title-phase.ts +++ b/src/phases/title-phase.ts @@ -76,7 +76,8 @@ export class TitlePhase extends Phase { this.scene.ui.clearText(); this.end(); }; - if (this.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]) { + const { gameData } = this.scene; + if (gameData.isUnlocked(Unlockables.ENDLESS_MODE)) { const options: OptionSelectItem[] = [ { label: GameMode.getModeName(GameModes.CLASSIC), @@ -100,7 +101,7 @@ export class TitlePhase extends Phase { } } ]; - if (this.scene.gameData.unlocks[Unlockables.SPLICED_ENDLESS_MODE]) { + if (gameData.isUnlocked(Unlockables.SPLICED_ENDLESS_MODE)) { options.push({ label: GameMode.getModeName(GameModes.SPLICED_ENDLESS), handler: () => { @@ -220,6 +221,7 @@ export class TitlePhase extends Phase { const modifiers: Modifier[] = Array(3).fill(null).map(() => modifierTypes.EXP_SHARE().withIdFromFunc(modifierTypes.EXP_SHARE).newModifier()) .concat(Array(3).fill(null).map(() => modifierTypes.GOLDEN_EXP_CHARM().withIdFromFunc(modifierTypes.GOLDEN_EXP_CHARM).newModifier())) + .concat([modifierTypes.MAP().withIdFromFunc(modifierTypes.MAP).newModifier()]) .concat(getDailyRunStarterModifiers(party)) .filter((m) => m !== null); diff --git a/src/system/game-data.ts b/src/system/game-data.ts index 04fef4a81da..22a793e9aca 100644 --- a/src/system/game-data.ts +++ b/src/system/game-data.ts @@ -372,6 +372,18 @@ export class GameData { }; } + /** + * Checks if an `Unlockable` has been unlocked. + * @param unlockable The Unlockable to check + * @returns `true` if the player has unlocked this `Unlockable` or an override has enabled it + */ + public isUnlocked(unlockable: Unlockables): boolean { + if (Overrides.ITEM_UNLOCK_OVERRIDE.includes(unlockable)) { + return true; + } + return this.unlocks[unlockable]; + } + public saveSystem(): Promise { return new Promise(resolve => { this.scene.ui.savingIcon.show(); diff --git a/src/system/version-converter.ts b/src/system/version-converter.ts index c297782ba66..0591647aeaa 100644 --- a/src/system/version-converter.ts +++ b/src/system/version-converter.ts @@ -22,15 +22,25 @@ export function applySessionDataPatches(data: SessionSaveData) { } else if (m.className === "PokemonResetNegativeStatStageModifier") { m.className = "ResetNegativeStatStageModifier"; } else if (m.className === "TempBattleStatBoosterModifier") { - m.className = "TempStatStageBoosterModifier"; - m.typeId = "TEMP_STAT_STAGE_BOOSTER"; + // 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; + // 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 { + m.className = "TempCritBoosterModifier"; + m.typePregenArgs = []; + + // From [ stat, battlesLeft ] to [ maxBattles, battleCount ] + m.args = [ 5, m.args[1] ]; + } - // 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) { @@ -73,7 +83,7 @@ export function applySystemDataPatches(data: SystemSaveData) { case "1.0.3": case "1.0.4": // --- LEGACY PATCHES --- - if (data.starterData) { + 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)) { @@ -104,12 +114,14 @@ export function applySystemDataPatches(data: SystemSaveData) { // --- 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; + if (data.starterData && data.dexData) { + 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; + } } } } diff --git a/src/test/daily_mode.test.ts b/src/test/daily_mode.test.ts index 5cc61a62874..dea204a2d2c 100644 --- a/src/test/daily_mode.test.ts +++ b/src/test/daily_mode.test.ts @@ -1,5 +1,15 @@ +import { MapModifier } from "#app/modifier/modifier"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; import GameManager from "./utils/gameManager"; +import { Moves } from "#app/enums/moves"; +import { getPartyLuckValue, itemPoolChecks } from "#app/modifier/modifier-type"; +import { Biome } from "#app/enums/biome"; +import { BattleEndPhase } from "#app/phases/battle-end-phase"; +import { Mode } from "#app/ui/ui"; +import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; +import Overrides from "#app/overrides"; + +//const TIMEOUT = 20 * 1000; describe("Daily Mode", () => { let phaserGame: Phaser.Game; @@ -28,5 +38,97 @@ describe("Daily Mode", () => { expect(pkm.level).toBe(20); expect(pkm.moveset.length).toBeGreaterThan(0); }); + expect(game.scene.getModifiers(MapModifier).length).toBeGreaterThan(0); }); }); + +//* +// Need to figure out how to properly start a battle +// Need to fix eviolite - test keeps insisting it is not in loot table, even though Mini Black Hole (which is using the exact same condition) is +describe("Shop modifications", async () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + beforeEach(() => { + game = new GameManager(phaserGame); + + game.override + .startingWave(9) + .startingBiome(Biome.ICE_CAVE) // Will lead to Snowy Forest with randomly generated weather + .battleType("single") + .shinyLevel(true) + .startingLevel(100) // Avoid levelling up + .enemyLevel(1000) // Avoid opponent dying before game.doKillOpponents() + .disableTrainerWaves() + .moveset([Moves.KOWTOW_CLEAVE]) + .enemyMoveset(Moves.SPLASH); + itemPoolChecks.set("EVIOLITE", false); + itemPoolChecks.set("MINI_BLACK_HOLE", false); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + itemPoolChecks.clear(); + }); + + it("should not have Eviolite and Mini Black Hole available in Classic if not unlocked", async () => { + await game.classicMode.runToSummon(); + expect(itemPoolChecks.get("EVIOLITE")).toBeDefined(); + expect(itemPoolChecks.get("EVIOLITE")).toBeFalsy(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeDefined(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeFalsy(); + game.move.select(Moves.KOWTOW_CLEAVE); + await game.phaseInterceptor.to("DamagePhase"); + await game.doKillOpponents(); + await game.phaseInterceptor.to(BattleEndPhase); + game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { + expect(game.scene.ui.getHandler()).toBeInstanceOf(ModifierSelectUiHandler); + expect(itemPoolChecks.get("EVIOLITE")).toBeDefined(); + expect(itemPoolChecks.get("EVIOLITE")).toBeFalsy(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeDefined(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeFalsy(); + }); + }); + + it("should have Eviolite and Mini Black Hole available in Daily", async () => { + await game.dailyMode.runToSummon(); + expect(itemPoolChecks.get("EVIOLITE")).toBeDefined(); + expect(itemPoolChecks.get("EVIOLITE")).toBeFalsy(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeDefined(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeFalsy(); + game.move.select(Moves.KOWTOW_CLEAVE); + await game.phaseInterceptor.to("DamagePhase"); + await game.doKillOpponents(); + await game.phaseInterceptor.to(BattleEndPhase); + game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { + expect(game.scene.ui.getHandler()).toBeInstanceOf(ModifierSelectUiHandler); + expect(itemPoolChecks.get("EVIOLITE")).toBeDefined(); + expect(itemPoolChecks.get("EVIOLITE")).toBeTruthy(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeDefined(); + expect(itemPoolChecks.get("MINI_BLACK_HOLE")).toBeTruthy(); + }); + }); + + it("should apply luck in Classic Mode", async () => { + await game.classicMode.runToSummon(); + const party = game.scene.getParty(); + expect(Overrides.SHINY_OVERRIDE).toBeTruthy(); + expect(party[0]).toBeDefined(); + expect(party[0].getLuck()).toBeGreaterThan(0); + expect(getPartyLuckValue(party)).toBeGreaterThan(0); + }); + + it("should not apply luck in Daily Run", async () => { + await game.dailyMode.runToSummon(); + const party = game.scene.getParty(); + expect(party[0]).toBeDefined(); + expect(party[0].getLuck()).toBeGreaterThan(0); + expect(getPartyLuckValue(party)).toBe(0); + }); +}); +//*/ diff --git a/src/test/game-mode.test.ts b/src/test/game-mode.test.ts index ccec3a3aa16..11994a102af 100644 --- a/src/test/game-mode.test.ts +++ b/src/test/game-mode.test.ts @@ -2,6 +2,7 @@ import { GameMode, GameModes, getGameMode } from "#app/game-mode"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import * as Utils from "../utils"; import GameManager from "./utils/gameManager"; + describe("game-mode", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -12,6 +13,7 @@ describe("game-mode", () => { }); afterEach(() => { game.phaseInterceptor.restoreOg(); + vi.clearAllMocks(); vi.resetAllMocks(); }); beforeEach(() => { diff --git a/src/test/reload.test.ts b/src/test/reload.test.ts index 7c4523dd9ef..daf8e43a0cd 100644 --- a/src/test/reload.test.ts +++ b/src/test/reload.test.ts @@ -1,9 +1,13 @@ -import { Species } from "#app/enums/species"; import { GameModes } from "#app/game-mode"; +import OptionSelectUiHandler from "#app/ui/settings/option-select-ui-handler"; +import { Mode } from "#app/ui/ui"; +import { Biome } from "#enums/biome"; +import { Button } from "#enums/buttons"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; +import { MockClock } from "#test/utils/mocks/mockClock"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; -import { Moves } from "#app/enums/moves"; -import { Biome } from "#app/enums/biome"; describe("Reload", () => { let phaserGame: Phaser.Game; @@ -50,6 +54,13 @@ describe("Reload", () => { game.move.select(Moves.KOWTOW_CLEAVE); await game.phaseInterceptor.to("DamagePhase"); await game.doKillOpponents(); + game.onNextPrompt("SelectBiomePhase", Mode.OPTION_SELECT, () => { + (game.scene.time as MockClock).overrideDelay = null; + const optionSelectUiHandler = game.scene.ui.getHandler() as OptionSelectUiHandler; + game.scene.time.delayedCall(1010, () => optionSelectUiHandler.processInput(Button.ACTION)); + game.endPhase(); + (game.scene.time as MockClock).overrideDelay = 1; + }); await game.toNextWave(); expect(game.phaseInterceptor.log).toContain("NewBiomeEncounterPhase"); diff --git a/src/test/ui/transfer-item.test.ts b/src/test/ui/transfer-item.test.ts index f7dea463574..7b5fa7f9171 100644 --- a/src/test/ui/transfer-item.test.ts +++ b/src/test/ui/transfer-item.test.ts @@ -2,6 +2,7 @@ import { BerryType } from "#app/enums/berry-type"; import { Button } from "#app/enums/buttons"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; +import { itemPoolChecks } from "#app/modifier/modifier-type"; import { BattleEndPhase } from "#app/phases/battle-end-phase"; import { SelectModifierPhase } from "#app/phases/select-modifier-phase"; import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler"; @@ -94,3 +95,47 @@ describe("UI - Transfer Items", () => { await game.phaseInterceptor.to(SelectModifierPhase); }, 20000); }); + +describe.skip("Backup Test", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(async () => { + game = new GameManager(phaserGame); + game.override + .battleType("single") + .startingLevel(100) + .startingWave(1) + .startingHeldItems([ + { name: "BERRY", count: 1, type: BerryType.SITRUS }, + { name: "BERRY", count: 2, type: BerryType.APICOT }, + { name: "BERRY", count: 2, type: BerryType.LUM }, + ]) + .moveset([Moves.DRAGON_CLAW]) + .enemySpecies(Species.MAGIKARP) + .enemyMoveset([Moves.SPLASH]); + itemPoolChecks.set("EVIOLITE", false); + itemPoolChecks.set("MINI_BLACK_HOLE", false); + }); + it("should run", async () => { + await game.classicMode.startBattle([Species.RAYQUAZA, Species.RAYQUAZA, Species.RAYQUAZA]); + + game.move.select(Moves.DRAGON_CLAW); + + game.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => { + expect(game.scene.ui.getHandler()).toBeInstanceOf(ModifierSelectUiHandler); + }); + + await game.phaseInterceptor.to(BattleEndPhase); + }); +}); diff --git a/src/test/utils/helpers/overridesHelper.ts b/src/test/utils/helpers/overridesHelper.ts index 686de58e874..d2a0cbdb2d7 100644 --- a/src/test/utils/helpers/overridesHelper.ts +++ b/src/test/utils/helpers/overridesHelper.ts @@ -10,6 +10,8 @@ import { ModifierOverride } from "#app/modifier/modifier-type"; import Overrides from "#app/overrides"; import { vi } from "vitest"; import { GameManagerHelper } from "./gameManagerHelper"; +import { Unlockables } from "#app/system/unlockables"; +import { Variant } from "#app/data/variant"; import { MysteryEncounterType } from "#enums/mystery-encounter-type"; import { MysteryEncounterTier } from "#enums/mystery-encounter-tier"; @@ -300,6 +302,17 @@ export class OverridesHelper extends GameManagerHelper { return this; } + /** + * Gives the player access to an Unlockable. + * @param unlockable The Unlockable to enable. + * @returns this + */ + enableUnlockable(unlockable: Unlockables[]) { + vi.spyOn(Overrides, "ITEM_UNLOCK_OVERRIDE", "get").mockReturnValue(unlockable); + this.log("Temporarily unlocked the following content: ", unlockable); + return this; + } + /** * Override the items rolled at the end of a battle * @param items the items to be rolled @@ -311,6 +324,25 @@ export class OverridesHelper extends GameManagerHelper { return this; } + /** + * Override player shininess + * @param shininess Whether the player's Pokemon should be shiny. + */ + shinyLevel(shininess: boolean): this { + vi.spyOn(Overrides, "SHINY_OVERRIDE", "get").mockReturnValue(shininess); + this.log(`Set player Pokemon as ${shininess ? "" : "not "}shiny!`); + return this; + } + /** + * Override player shiny variant + * @param variant The player's shiny variant. + */ + variantLevel(variant: Variant): this { + vi.spyOn(Overrides, "VARIANT_OVERRIDE", "get").mockReturnValue(variant); + this.log(`Set player Pokemon's shiny variant to ${variant}!`); + return this; + } + /** * Override the enemy (Pokemon) to have the given amount of health segments * @param healthSegments the number of segments to give diff --git a/src/test/utils/phaseInterceptor.ts b/src/test/utils/phaseInterceptor.ts index 46bb757c867..6c4c9a6cf94 100644 --- a/src/test/utils/phaseInterceptor.ts +++ b/src/test/utils/phaseInterceptor.ts @@ -43,6 +43,7 @@ import { UnavailablePhase } from "#app/phases/unavailable-phase"; import { VictoryPhase } from "#app/phases/victory-phase"; import { PartyHealPhase } from "#app/phases/party-heal-phase"; import UI, { Mode } from "#app/ui/ui"; +import { SelectBiomePhase } from "#app/phases/select-biome-phase"; import { MysteryEncounterBattlePhase, MysteryEncounterOptionSelectedPhase, @@ -122,6 +123,7 @@ export default class PhaseInterceptor { [EndEvolutionPhase, this.startPhase], [LevelCapPhase, this.startPhase], [AttemptRunPhase, this.startPhase], + [SelectBiomePhase, this.startPhase], [MysteryEncounterPhase, this.startPhase], [MysteryEncounterOptionSelectedPhase, this.startPhase], [MysteryEncounterBattlePhase, this.startPhase], @@ -346,7 +348,8 @@ export default class PhaseInterceptor { console.log("setMode", `${Mode[mode]} (=${mode})`, args); const ret = this.originalSetMode.apply(instance, [mode, ...args]); if (!this.phases[currentPhase.constructor.name]) { - throw new Error(`missing ${currentPhase.constructor.name} in phaseInterceptor PHASES list`); + throw new Error(`missing ${currentPhase.constructor.name} in phaseInterceptor PHASES list --- Add it to PHASES inside of /test/utils/phaseInterceptor.ts`); + } if (this.phases[currentPhase.constructor.name].endBySetMode) { this.inProgress?.callback(); diff --git a/src/tutorial.ts b/src/tutorial.ts index 18d8291d227..3934ffee57f 100644 --- a/src/tutorial.ts +++ b/src/tutorial.ts @@ -74,11 +74,11 @@ const tutorialHandlers = { * @returns a promise with result `true` if the tutorial was run and finished, `false` otherwise */ export async function handleTutorial(scene: BattleScene, tutorial: Tutorial): Promise { - if (!scene.enableTutorials && !Overrides.BYPASS_TUTORIAL_SKIP) { + if (!scene.enableTutorials && !Overrides.BYPASS_TUTORIAL_SKIP_OVERRIDE) { return false; } - if (scene.gameData.getTutorialFlags()[tutorial] && !Overrides.BYPASS_TUTORIAL_SKIP) { + if (scene.gameData.getTutorialFlags()[tutorial] && !Overrides.BYPASS_TUTORIAL_SKIP_OVERRIDE) { return false; } diff --git a/src/ui/modifier-select-ui-handler.ts b/src/ui/modifier-select-ui-handler.ts index c9d3f195720..521162b8842 100644 --- a/src/ui/modifier-select-ui-handler.ts +++ b/src/ui/modifier-select-ui-handler.ts @@ -230,7 +230,7 @@ export default class ModifierSelectUiHandler extends AwaitableUiHandler { /* Multiplies the appearance duration by the speed parameter so that it is always constant, and avoids "flashbangs" at game speed x5 */ this.scene.showShopOverlay(750 * this.scene.gameSpeed); - this.scene.updateAndShowText(750); + this.scene.updateAndShowText(750, this.scene.gameMode.isDaily); this.scene.updateBiomeWaveText(); this.scene.updateMoneyText();