clean up unit tests and utils
This commit is contained in:
parent
c928445f5e
commit
2697a738ba
|
@ -145,7 +145,7 @@ export const FieryFalloutEncounter: IMysteryEncounter =
|
|||
.withOption(
|
||||
new MysteryEncounterOptionBuilder()
|
||||
.withOptionMode(EncounterOptionMode.DISABLED_OR_SPECIAL)
|
||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, 2)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withPrimaryPokemonRequirement(new TypeRequirement(Type.FIRE, true,2)) // Will set option2PrimaryName and option2PrimaryMove dialogue tokens automatically
|
||||
.withDialogue({
|
||||
buttonLabel: `${namespace}_option_3_label`,
|
||||
buttonTooltip: `${namespace}_option_3_tooltip`,
|
||||
|
|
|
@ -57,7 +57,7 @@ export const SafariZoneEncounter: IMysteryEncounter =
|
|||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
// Start safari encounter
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
encounter.encounterVariant = MysteryEncounterVariant.SAFARI_BATTLE;
|
||||
encounter.encounterVariant = MysteryEncounterVariant.REPEATED_ENCOUNTER;
|
||||
encounter.misc = {
|
||||
safariPokemonRemaining: 3
|
||||
};
|
||||
|
@ -463,14 +463,15 @@ function tryChangeCatchStage(scene: BattleScene, change: number, chance?: number
|
|||
return true;
|
||||
}
|
||||
|
||||
async function doEndTurn(scene: BattleScene, cursorIndex: number, message?: string) {
|
||||
const pokemon = scene.currentBattle.mysteryEncounter.misc.pokemon;
|
||||
const isFlee = isPokemonFlee(pokemon, scene.currentBattle.mysteryEncounter.misc.fleeStage);
|
||||
async function doEndTurn(scene: BattleScene, cursorIndex: number) {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const pokemon = encounter.misc.pokemon;
|
||||
const isFlee = isPokemonFlee(pokemon, encounter.misc.fleeStage);
|
||||
if (isFlee) {
|
||||
// Pokemon flees!
|
||||
await doPokemonFlee(scene, pokemon);
|
||||
// Check how many safari pokemon left
|
||||
if (scene.currentBattle.mysteryEncounter.misc.safariPokemonRemaining > 0) {
|
||||
if (encounter.misc.safariPokemonRemaining > 0) {
|
||||
await summonSafariPokemon(scene);
|
||||
initSubsequentOptionSelect(scene, { overrideOptions: safariZoneGameOptions, startingCursorIndex: cursorIndex, hideDescription: true });
|
||||
} else {
|
||||
|
|
|
@ -27,7 +27,7 @@ export enum MysteryEncounterVariant {
|
|||
WILD_BATTLE,
|
||||
BOSS_BATTLE,
|
||||
NO_BATTLE,
|
||||
SAFARI_BATTLE
|
||||
REPEATED_ENCOUNTER
|
||||
}
|
||||
|
||||
export enum MysteryEncounterTier {
|
||||
|
@ -38,7 +38,7 @@ export enum MysteryEncounterTier {
|
|||
MASTER // Not currently used
|
||||
}
|
||||
|
||||
export class StartOfBattleEffect {
|
||||
export interface StartOfBattleEffect {
|
||||
sourcePokemon?: Pokemon;
|
||||
sourceBattlerIndex?: BattlerIndex;
|
||||
targets: BattlerIndex[];
|
||||
|
@ -108,10 +108,6 @@ export default interface IMysteryEncounter {
|
|||
* You should never need to modify this
|
||||
*/
|
||||
seedOffset?: any;
|
||||
/**
|
||||
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
|
||||
*/
|
||||
startOfBattleEffectsComplete?: boolean;
|
||||
|
||||
/**
|
||||
* Flags
|
||||
|
@ -134,6 +130,10 @@ export default interface IMysteryEncounter {
|
|||
* Will be set to false after a shop is shown (so can't reroll same rarity items for free)
|
||||
*/
|
||||
lockEncounterRewardTiers?: boolean;
|
||||
/**
|
||||
* Will be set automatically, indicates special moves in startOfBattleEffects are complete (so will not repeat)
|
||||
*/
|
||||
startOfBattleEffectsComplete?: boolean;
|
||||
/**
|
||||
* Will be set by option select handlers automatically, and can be used to refer to which option was chosen by later phases
|
||||
*/
|
||||
|
@ -473,6 +473,8 @@ export class MysteryEncounterBuilder implements Partial<IMysteryEncounter> {
|
|||
|
||||
/**
|
||||
* Defines any EncounterAnim animations that are intended to be used during the encounter
|
||||
* EncounterAnims can be played at any point during an encounter or callback
|
||||
* They just need to be specified here so that resources are loaded on encounter init
|
||||
* @param encounterAnimations
|
||||
* @returns
|
||||
*/
|
||||
|
|
|
@ -555,8 +555,10 @@ export function handleMysteryEncounterVictory(scene: BattleScene, addHealPhase:
|
|||
return;
|
||||
}
|
||||
|
||||
if (scene.currentBattle.mysteryEncounter.encounterVariant === MysteryEncounterVariant.SAFARI_BATTLE) {
|
||||
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
||||
// If in repeated encounter variant, do nothing
|
||||
// Variant must eventually be swapped in order to handle "true" end of the encounter
|
||||
if (scene.currentBattle.mysteryEncounter.encounterVariant === MysteryEncounterVariant.REPEATED_ENCOUNTER) {
|
||||
return;
|
||||
} else if (scene.currentBattle.mysteryEncounter.encounterVariant === MysteryEncounterVariant.NO_BATTLE) {
|
||||
scene.pushPhase(new EggLapsePhase(scene));
|
||||
scene.pushPhase(new MysteryEncounterRewardsPhase(scene, addHealPhase));
|
||||
|
|
|
@ -117,9 +117,9 @@ export const EGG_GACHA_PULL_COUNT_OVERRIDE: number = 0;
|
|||
*/
|
||||
|
||||
// 1 to 256, set to null to ignore
|
||||
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = 256;
|
||||
export const MYSTERY_ENCOUNTER_RATE_OVERRIDE: number = null;
|
||||
export const MYSTERY_ENCOUNTER_TIER_OVERRIDE: MysteryEncounterTier = null;
|
||||
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = MysteryEncounterType.FIERY_FALLOUT;
|
||||
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null;
|
||||
|
||||
/**
|
||||
* MODIFIER / ITEM OVERRIDES
|
||||
|
|
|
@ -1,17 +1,19 @@
|
|||
import { Button } from "#app/enums/buttons";
|
||||
import { MessagePhase } from "#app/phases";
|
||||
import { MessagePhase, VictoryPhase } from "#app/phases";
|
||||
import { MysteryEncounterPhase, MysteryEncounterRewardsPhase } from "#app/phases/mystery-encounter-phase";
|
||||
import MysteryEncounterUiHandler from "#app/ui/mystery-encounter-ui-handler";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import GameManager from "../utils/gameManager";
|
||||
import MessageUiHandler from "#app/ui/message-ui-handler";
|
||||
|
||||
export async function runSelectMysteryEncounterOption(game: GameManager, optionNo: number) {
|
||||
// Handle any eventual queued messages (e.g. weather phase, etc.)
|
||||
game.onNextPrompt("MessagePhase", Mode.MESSAGE, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
|
||||
if (game.isCurrentPhase(MessagePhase)) {
|
||||
// Handle eventual weather messages (e.g. a downpour started!)
|
||||
game.onNextPrompt("MessagePhase", Mode.MESSAGE, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
await game.phaseInterceptor.run(MessagePhase);
|
||||
}
|
||||
|
||||
|
@ -20,35 +22,56 @@ export async function runSelectMysteryEncounterOption(game: GameManager, optionN
|
|||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
// select the desired option
|
||||
game.onNextPrompt("MysteryEncounterPhase", Mode.MYSTERY_ENCOUNTER, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
uiHandler.unblockInput(); // input are blocked by 1s to prevent accidental input. Tests need to handle that
|
||||
|
||||
switch (optionNo) {
|
||||
case 1:
|
||||
// no movement needed. Default cursor position
|
||||
break;
|
||||
case 2:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
break;
|
||||
case 3:
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
case 4:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
}
|
||||
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
await game.phaseInterceptor.run(MysteryEncounterPhase);
|
||||
|
||||
// select the desired option
|
||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
uiHandler.unblockInput(); // input are blocked by 1s to prevent accidental input. Tests need to handle that
|
||||
|
||||
switch (optionNo) {
|
||||
case 1:
|
||||
// no movement needed. Default cursor position
|
||||
break;
|
||||
case 2:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
break;
|
||||
case 3:
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
case 4:
|
||||
uiHandler.processInput(Button.RIGHT);
|
||||
uiHandler.processInput(Button.DOWN);
|
||||
break;
|
||||
}
|
||||
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
|
||||
// run the selected options phase
|
||||
game.onNextPrompt("MysteryEncounterOptionSelectedPhase", Mode.MESSAGE, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MysteryEncounterUiHandler>();
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
|
||||
// If a battle is started, fast forward to end of the battle
|
||||
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||
game.scene.clearPhaseQueue();
|
||||
game.scene.clearPhaseQueueSplice();
|
||||
game.scene.unshiftPhase(new VictoryPhase(game.scene, 0));
|
||||
game.endPhase();
|
||||
});
|
||||
|
||||
// Handle end of battle trainer messages
|
||||
game.onNextPrompt("TrainerVictoryPhase", Mode.MESSAGE, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
|
||||
// Handle egg hatch dialogue
|
||||
game.onNextPrompt("EggLapsePhase", Mode.MESSAGE, () => {
|
||||
const uiHandler = game.scene.ui.getHandler<MessageUiHandler>();
|
||||
uiHandler.processInput(Button.ACTION);
|
||||
});
|
||||
|
||||
await game.phaseInterceptor.to(MysteryEncounterRewardsPhase);
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import { Moves } from "#app/enums/moves";
|
|||
import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
|
||||
import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { workaround_reInitSceneWithOverrides } from "#app/test/utils/testUtils";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { runSelectMysteryEncounterOption } from "../encounterTestUtils";
|
||||
|
||||
|
@ -30,8 +29,9 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
beforeEach(async () => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override.mysteryEncounterChance(100);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(
|
||||
new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.SEA, [MysteryEncounterType.LOST_AT_SEA]],
|
||||
|
@ -45,7 +45,6 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
});
|
||||
|
||||
it("should have the correct properties", async () => {
|
||||
await workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
|
||||
expect(LostAtSeaEncounter.encounterType).toBe(MysteryEncounterType.LOST_AT_SEA);
|
||||
|
@ -59,7 +58,6 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
|
||||
it("should not spawn outside of sea biome", async () => {
|
||||
game.override.startingBiome(Biome.MOUNTAIN);
|
||||
await workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
expect(game.scene.currentBattle.mysteryEncounter.encounterType).not.toBe(MysteryEncounterType.LOST_AT_SEA);
|
||||
|
@ -117,7 +115,6 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
it("should award exp to surfable PKM (Blastoise)", async () => {
|
||||
const laprasSpecies = getPokemonSpecies(Species.LAPRAS);
|
||||
|
||||
await workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
const party = game.scene.getParty();
|
||||
const blastoise = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||
|
@ -126,13 +123,12 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
await runSelectMysteryEncounterOption(game, 2);
|
||||
|
||||
expect(blastoise.exp).toBe(expBefore + laprasSpecies.baseExp * defaultWave);
|
||||
});
|
||||
}, 10000000);
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
game.override.startingWave(33);
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
||||
await workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
|
@ -168,7 +164,6 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
const wave = 33;
|
||||
game.override.startingWave(wave);
|
||||
|
||||
await workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
const party = game.scene.getParty();
|
||||
const pidgeot = party.find((pkm) => pkm.species.speciesId === Species.PIDGEOT);
|
||||
|
@ -183,7 +178,7 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
game.override.startingWave(33);
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
||||
await workaround_reInitSceneWithOverrides(game);
|
||||
// await workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 2);
|
||||
|
||||
|
@ -215,7 +210,6 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
it("should damage all (allowed in battle) party PKM by 25%", async () => {
|
||||
game.override.startingWave(33);
|
||||
|
||||
await workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
|
||||
const party = game.scene.getParty();
|
||||
|
@ -237,7 +231,6 @@ describe("Lost at Sea - Mystery Encounter", () => {
|
|||
game.override.startingWave(33);
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
||||
workaround_reInitSceneWithOverrides(game);
|
||||
await game.runToMysteryEncounter(defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 3);
|
||||
|
||||
|
|
|
@ -36,16 +36,12 @@ describe("Mystery Encounter Utils", () => {
|
|||
describe("getRandomPlayerPokemon", () => {
|
||||
it("gets a random pokemon from player party", () => {
|
||||
// Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal)
|
||||
scene.waveSeed = "random";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random");
|
||||
|
||||
let result = getRandomPlayerPokemon(scene);
|
||||
expect(result.species.speciesId).toBe(Species.MANAPHY);
|
||||
|
||||
scene.waveSeed = "random2";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random2");
|
||||
|
||||
result = getRandomPlayerPokemon(scene);
|
||||
expect(result.species.speciesId).toBe(Species.ARCEUS);
|
||||
|
@ -60,16 +56,12 @@ describe("Mystery Encounter Utils", () => {
|
|||
});
|
||||
|
||||
// Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal)
|
||||
scene.waveSeed = "random";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random");
|
||||
|
||||
let result = getRandomPlayerPokemon(scene);
|
||||
expect(result.species.speciesId).toBe(Species.MANAPHY);
|
||||
|
||||
scene.waveSeed = "random2";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random2");
|
||||
|
||||
result = getRandomPlayerPokemon(scene);
|
||||
expect(result.species.speciesId).toBe(Species.ARCEUS);
|
||||
|
@ -83,16 +75,12 @@ describe("Mystery Encounter Utils", () => {
|
|||
party[0].updateInfo();
|
||||
|
||||
// Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal)
|
||||
scene.waveSeed = "random";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random");
|
||||
|
||||
let result = getRandomPlayerPokemon(scene, true);
|
||||
expect(result.species.speciesId).toBe(Species.MANAPHY);
|
||||
|
||||
scene.waveSeed = "random2";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random2");
|
||||
|
||||
result = getRandomPlayerPokemon(scene, true);
|
||||
expect(result.species.speciesId).toBe(Species.MANAPHY);
|
||||
|
@ -106,16 +94,12 @@ describe("Mystery Encounter Utils", () => {
|
|||
party[0].updateInfo();
|
||||
|
||||
// Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal)
|
||||
scene.waveSeed = "random";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random");
|
||||
|
||||
let result = getRandomPlayerPokemon(scene, true, false);
|
||||
expect(result.species.speciesId).toBe(Species.MANAPHY);
|
||||
|
||||
scene.waveSeed = "random2";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random2");
|
||||
|
||||
result = getRandomPlayerPokemon(scene, true, false);
|
||||
expect(result.species.speciesId).toBe(Species.MANAPHY);
|
||||
|
@ -129,16 +113,12 @@ describe("Mystery Encounter Utils", () => {
|
|||
party[0].updateInfo();
|
||||
|
||||
// Seeds are calculated to return index 0 first, 1 second (if both pokemon are legal)
|
||||
scene.waveSeed = "random";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random");
|
||||
|
||||
let result = getRandomPlayerPokemon(scene, true, true);
|
||||
expect(result.species.speciesId).toBe(Species.ARCEUS);
|
||||
|
||||
scene.waveSeed = "random2";
|
||||
Phaser.Math.RND.sow([scene.waveSeed]);
|
||||
scene.rngCounter = 0;
|
||||
game.override.seed("random2");
|
||||
|
||||
result = getRandomPlayerPokemon(scene, true, true);
|
||||
expect(result.species.speciesId).toBe(Species.ARCEUS);
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
import { afterEach, beforeAll, beforeEach, expect, describe, it, vi } from "vitest";
|
||||
import * as overrides from "../../overrides";
|
||||
import { afterEach, beforeAll, beforeEach, expect, describe, it } from "vitest";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { Species } from "#enums/species";
|
||||
|
@ -22,16 +21,9 @@ describe("Mystery Encounters", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(overrides, "MYSTERY_ENCOUNTER_RATE_OVERRIDE", "get").mockReturnValue(256);
|
||||
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(11);
|
||||
vi.spyOn(overrides, "MYSTERY_ENCOUNTER_OVERRIDE", "get").mockReturnValue(MysteryEncounterType.MYSTERIOUS_CHALLENGERS);
|
||||
|
||||
// Seed guarantees wild encounter to be replaced by ME
|
||||
vi.spyOn(game.scene, "resetSeed").mockImplementation(() => {
|
||||
game.scene.waveSeed = "test";
|
||||
Phaser.Math.RND.sow([game.scene.waveSeed]);
|
||||
game.scene.rngCounter = 0;
|
||||
});
|
||||
game.override.startingWave(11);
|
||||
game.override.mysteryEncounterChance(100);
|
||||
game.override.mysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS);
|
||||
});
|
||||
|
||||
it("Spawns a mystery encounter", async () => {
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
import {afterEach, beforeAll, beforeEach, expect, describe, it, vi} from "vitest";
|
||||
import * as overrides from "../../overrides";
|
||||
import {afterEach, beforeAll, beforeEach, expect, describe, it, vi } from "vitest";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import {Species} from "#enums/species";
|
||||
import {MysteryEncounterOptionSelectedPhase, MysteryEncounterPhase} from "#app/phases/mystery-encounter-phase";
|
||||
import { MysteryEncounterOptionSelectedPhase, MysteryEncounterPhase } from "#app/phases/mystery-encounter-phase";
|
||||
import {Mode} from "#app/ui/ui";
|
||||
import {Button} from "#enums/buttons";
|
||||
import MysteryEncounterUiHandler from "#app/ui/mystery-encounter-ui-handler";
|
||||
import {MysteryEncounterType} from "#enums/mystery-encounter-type";
|
||||
import {MysteryEncounterTier} from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import MessageUiHandler from "#app/ui/message-ui-handler";
|
||||
|
||||
describe("Mystery Encounter Phases", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
|
@ -26,16 +26,11 @@ describe("Mystery Encounter Phases", () => {
|
|||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(overrides, "MYSTERY_ENCOUNTER_RATE_OVERRIDE", "get").mockReturnValue(256);
|
||||
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(11);
|
||||
vi.spyOn(overrides, "MYSTERY_ENCOUNTER_OVERRIDE", "get").mockReturnValue(MysteryEncounterType.MYSTERIOUS_CHALLENGERS);
|
||||
|
||||
game.override.startingWave(11);
|
||||
game.override.mysteryEncounterChance(100);
|
||||
game.override.mysteryEncounter(MysteryEncounterType.MYSTERIOUS_CHALLENGERS);
|
||||
// Seed guarantees wild encounter to be replaced by ME
|
||||
vi.spyOn(game.scene, "resetSeed").mockImplementation(() => {
|
||||
game.scene.waveSeed = "test";
|
||||
Phaser.Math.RND.sow([ game.scene.waveSeed ]);
|
||||
game.scene.rngCounter = 0;
|
||||
});
|
||||
game.override.seed("test");
|
||||
});
|
||||
|
||||
describe("MysteryEncounterPhase", () => {
|
||||
|
@ -75,21 +70,25 @@ describe("Mystery Encounter Phases", () => {
|
|||
Species.VOLCARONA
|
||||
]);
|
||||
|
||||
game.onNextPrompt("MysteryEncounterPhase", Mode.MYSTERY_ENCOUNTER, () => {
|
||||
// Select option 1 for encounter
|
||||
const handler = game.scene.ui.getHandler() as MysteryEncounterUiHandler;
|
||||
handler.unblockInput();
|
||||
game.onNextPrompt("MysteryEncounterPhase", Mode.MESSAGE, () => {
|
||||
const handler = game.scene.ui.getHandler() as MessageUiHandler;
|
||||
handler.processInput(Button.ACTION);
|
||||
}, () => !game.isCurrentPhase(MysteryEncounterPhase));
|
||||
});
|
||||
|
||||
await game.phaseInterceptor.run(MysteryEncounterPhase);
|
||||
|
||||
// After option selected
|
||||
expect(game.scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterOptionSelectedPhase.name);
|
||||
// Select option 1 for encounter
|
||||
const handler = game.scene.ui.getHandler() as MysteryEncounterUiHandler;
|
||||
handler.unblockInput();
|
||||
handler.processInput(Button.ACTION);
|
||||
|
||||
// Waitfor required so that option select messages and preOptionPhase logic are handled
|
||||
await vi.waitFor(() => expect(game.scene.getCurrentPhase().constructor.name).toBe(MysteryEncounterOptionSelectedPhase.name));
|
||||
expect(game.scene.ui.getMode()).toBe(Mode.MESSAGE);
|
||||
expect(dialogueSpy).toHaveBeenCalledTimes(1);
|
||||
expect(messageSpy).toHaveBeenCalledTimes(2);
|
||||
expect(dialogueSpy).toHaveBeenCalledWith("What's this?", "???", null, expect.any(Function));
|
||||
expect(messageSpy).toHaveBeenCalledWith("Mysterious challengers have appeared!", null, expect.any(Function), 300, true);
|
||||
expect(messageSpy).toHaveBeenCalledWith("Mysterious challengers have appeared!", null, expect.any(Function), 750, true);
|
||||
expect(messageSpy).toHaveBeenCalledWith("The trainer steps forward...", null, expect.any(Function), 300, true);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -11,6 +11,11 @@ export default class TextInterceptor {
|
|||
this.logs.push(text);
|
||||
}
|
||||
|
||||
showDialogue(text: string, name: string, delay?: integer, callback?: Function, callbackDelay?: integer, promptDelay?: integer): void {
|
||||
console.log(name, text);
|
||||
this.logs.push(name, text);
|
||||
}
|
||||
|
||||
getLatestMessage(): string {
|
||||
return this.logs.pop();
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ export default class GameManager {
|
|||
this.phaseInterceptor = new PhaseInterceptor(this.scene);
|
||||
this.textInterceptor = new TextInterceptor(this.scene);
|
||||
this.gameWrapper.setScene(this.scene);
|
||||
this.override = new OverridesHelper();
|
||||
this.override = new OverridesHelper(this);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -17,6 +17,7 @@ export default class MockText {
|
|||
// Phaser.GameObjects.Text.prototype.updateText = () => null;
|
||||
// Phaser.Textures.TextureManager.prototype.addCanvas = () => {};
|
||||
UI.prototype.showText = this.showText;
|
||||
UI.prototype.showDialogue = this.showDialogue;
|
||||
// super(scene, x, y);
|
||||
// this.phaserText = new Phaser.GameObjects.Text(scene, x, y, content, styleOptions);
|
||||
}
|
||||
|
@ -79,6 +80,13 @@ export default class MockText {
|
|||
}
|
||||
}
|
||||
|
||||
showDialogue(text, name, delay, callback, callbackDelay, promptDelay) {
|
||||
this.scene.messageWrapper.showDialogue(text, name, delay, callback, callbackDelay, promptDelay);
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
setScale(scale) {
|
||||
// return this.phaserText.setScale(scale);
|
||||
}
|
||||
|
|
|
@ -1,61 +1,90 @@
|
|||
import { Weather, WeatherType } from "#app/data/weather";
|
||||
import { Biome } from "#app/enums/biome";
|
||||
import * as Overrides from "#app/overrides";
|
||||
import { vi } from "vitest";
|
||||
import { MockInstance, vi } from "vitest";
|
||||
import GameManager from "#test/utils/gameManager";
|
||||
import { MysteryEncounterType } from "#enums/mystery-encounter-type";
|
||||
import * as overrides from "#app/overrides";
|
||||
|
||||
/**
|
||||
* Helper to handle overrides in tests
|
||||
*/
|
||||
export class OverridesHelper {
|
||||
constructor() {}
|
||||
game: GameManager;
|
||||
constructor(game: GameManager) {
|
||||
this.game = game;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the encounter chance for a mystery encounter.
|
||||
* @param percentage the encounter chance in %
|
||||
* @returns spy instance
|
||||
*/
|
||||
mysteryEncounterChance(percentage: number) {
|
||||
mysteryEncounterChance(percentage: number): MockInstance {
|
||||
const maxRate: number = 256; // 100%
|
||||
const rate = maxRate * (percentage / 100);
|
||||
vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_RATE_OVERRIDE", "get").mockReturnValue(rate);
|
||||
const spy = vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_RATE_OVERRIDE", "get").mockReturnValue(rate);
|
||||
this.log(`Mystery encounter chance set to ${percentage}% (=${rate})!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the encounter that spawns for the scene
|
||||
* @param encounterType
|
||||
* @returns spy instance
|
||||
*/
|
||||
mysteryEncounter(encounterType: MysteryEncounterType): MockInstance {
|
||||
const spy = vi.spyOn(overrides, "MYSTERY_ENCOUNTER_OVERRIDE", "get").mockReturnValue(encounterType);
|
||||
this.log(`Mystery encounter override set to ${encounterType}!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the starting biome
|
||||
* @warning The biome will not be overridden unless you call `workaround_reInitSceneWithOverrides()` (testUtils)
|
||||
* @warning Any event listeners that are attached to [NewArenaEvent](events\battle-scene.ts) may need to be handled down the line
|
||||
* @param biome the biome to set
|
||||
*/
|
||||
startingBiome(biome: Biome) {
|
||||
vi.spyOn(Overrides, "STARTING_BIOME_OVERRIDE", "get").mockReturnValue(biome);
|
||||
this.game.scene.newArena(biome);
|
||||
this.log(`Starting biome set to ${Biome[biome]} (=${biome})!`);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the starting wave (index)
|
||||
* @param wave the wave (index) to set. Classic: `1`-`200`
|
||||
* @returns spy instance
|
||||
*/
|
||||
startingWave(wave: number) {
|
||||
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(wave);
|
||||
startingWave(wave: number): MockInstance {
|
||||
const spy = vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(wave);
|
||||
this.log(`Starting wave set to ${wave}!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the weather (type)
|
||||
* @param type weather type to set
|
||||
* @returns spy instance
|
||||
*/
|
||||
weather(type: WeatherType) {
|
||||
vi.spyOn(Overrides, "WEATHER_OVERRIDE", "get").mockReturnValue(type);
|
||||
weather(type: WeatherType): MockInstance {
|
||||
const spy = vi.spyOn(Overrides, "WEATHER_OVERRIDE", "get").mockReturnValue(type);
|
||||
this.log(`Weather set to ${Weather[type]} (=${type})!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the seed
|
||||
* @warning The seed will not be overridden unless you call `workaround_reInitSceneWithOverrides()` (testUtils)
|
||||
* @param seed the seed to set
|
||||
* @returns spy instance
|
||||
*/
|
||||
seed(seed: string) {
|
||||
vi.spyOn(Overrides, "SEED_OVERRIDE", "get").mockReturnValue(seed);
|
||||
seed(seed: string): MockInstance {
|
||||
const spy = vi.spyOn(this.game.scene, "resetSeed").mockImplementation(() => {
|
||||
this.game.scene.waveSeed = seed;
|
||||
Phaser.Math.RND.sow([seed]);
|
||||
this.game.scene.rngCounter = 0;
|
||||
});
|
||||
this.game.scene.resetSeed();
|
||||
this.log(`Seed set to "${seed}"!`);
|
||||
return spy;
|
||||
}
|
||||
|
||||
private log(...params: any[]) {
|
||||
|
|
|
@ -108,7 +108,7 @@ export default class PhaseInterceptor {
|
|||
];
|
||||
|
||||
private endBySetMode = [
|
||||
TitlePhase, SelectGenderPhase, CommandPhase, SelectModifierPhase, PostMysteryEncounterPhase
|
||||
TitlePhase, SelectGenderPhase, CommandPhase, SelectModifierPhase, MysteryEncounterPhase, PostMysteryEncounterPhase
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
import i18next, { type ParseKeys } from "i18next";
|
||||
import { vi } from "vitest";
|
||||
import GameManager from "./gameManager";
|
||||
|
||||
/**
|
||||
* Sets up the i18next mock.
|
||||
|
@ -22,15 +21,3 @@ export function mockI18next() {
|
|||
export function arrayOfRange(start: integer, end: integer) {
|
||||
return Array.from({ length: end - start }, (_v, k) => k + start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Woraround to reinitialize the game scene with overrides being set properly.
|
||||
* By default the scene is initialized without all overrides even having a chance to be applied.
|
||||
* @warning USE AT YOUR OWN RISK! Might be deleted in the future
|
||||
* @param game The game manager
|
||||
* @deprecated
|
||||
*/
|
||||
export async function workaround_reInitSceneWithOverrides(game: GameManager) {
|
||||
await game.runToTitle();
|
||||
game.gameWrapper.setScene(game.scene);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue