add unit tests for pokemon salesman
This commit is contained in:
parent
792af86f39
commit
0c45194892
|
@ -94,7 +94,7 @@ export const PokemonSalesmanEncounter: IMysteryEncounter =
|
|||
encounter.setDialogueToken("purchasePokemon", pokemon.name);
|
||||
encounter.setDialogueToken("price", price.toString());
|
||||
encounter.misc = {
|
||||
money: price,
|
||||
price: price,
|
||||
pokemon: pokemon
|
||||
};
|
||||
|
||||
|
@ -118,11 +118,11 @@ export const PokemonSalesmanEncounter: IMysteryEncounter =
|
|||
})
|
||||
.withOptionPhase(async (scene: BattleScene) => {
|
||||
const encounter = scene.currentBattle.mysteryEncounter;
|
||||
const cost = encounter.misc.money;
|
||||
const price = encounter.misc.price;
|
||||
const purchasedPokemon = encounter.misc.pokemon as PlayerPokemon;
|
||||
|
||||
// Update money
|
||||
updatePlayerMoney(scene, -cost, true, false);
|
||||
updatePlayerMoney(scene, -price, true, false);
|
||||
|
||||
// Show dialogue
|
||||
await showEncounterDialogue(scene, `${namespace}:option:1:selected_dialogue`, `${namespace}:speaker`);
|
||||
|
|
|
@ -316,6 +316,7 @@ export function initCustomMovesForEncounter(scene: BattleScene, moves: Moves | M
|
|||
* @param scene - Battle Scene
|
||||
* @param changeValue
|
||||
* @param playSound
|
||||
* @param showMessage
|
||||
*/
|
||||
export function updatePlayerMoney(scene: BattleScene, changeValue: number, playSound: boolean = true, showMessage: boolean = true) {
|
||||
scene.money = Math.min(Math.max(scene.money + changeValue, 0), Number.MAX_SAFE_INTEGER);
|
||||
|
|
|
@ -173,6 +173,9 @@ export default class MysteryEncounterIntroVisuals extends Phaser.GameObjects.Con
|
|||
}
|
||||
});
|
||||
|
||||
// Load dex progress icon
|
||||
this.scene.loadAtlas("encounter_radar", "mystery-encounters");
|
||||
|
||||
this.scene.load.once(Phaser.Loader.Events.COMPLETE, () => {
|
||||
this.spriteConfigs.every((config) => {
|
||||
if (config.isItem) {
|
||||
|
|
|
@ -273,8 +273,6 @@ export class LoadingScene extends SceneBase {
|
|||
this.loadAtlas("xbox", "inputs");
|
||||
this.loadAtlas("keyboard", "inputs");
|
||||
|
||||
this.loadAtlas("encounter_radar", "mystery-encounters");
|
||||
|
||||
this.loadSe("select");
|
||||
this.loadSe("menu_open");
|
||||
this.loadSe("hit");
|
||||
|
|
|
@ -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.POKEMON_SALESMAN;
|
||||
export const MYSTERY_ENCOUNTER_OVERRIDE: MysteryEncounterType = null;
|
||||
|
||||
/**
|
||||
* MODIFIER / ITEM OVERRIDES
|
||||
|
|
|
@ -0,0 +1,171 @@
|
|||
import * as MysteryEncounters from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { Biome } from "#app/enums/biome";
|
||||
import { MysteryEncounterType } from "#app/enums/mystery-encounter-type";
|
||||
import { Species } from "#app/enums/species";
|
||||
import GameManager from "#app/test/utils/gameManager";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import Battle from "#app/battle";
|
||||
import * as EncounterPhaseUtils from "#app/data/mystery-encounters/utils/encounter-phase-utils";
|
||||
import { EncounterOptionMode } from "#app/data/mystery-encounters/mystery-encounter-option";
|
||||
import { runSelectMysteryEncounterOption } from "#test/mystery-encounter/encounterTestUtils";
|
||||
import BattleScene from "#app/battle-scene";
|
||||
import { MysteryEncounterTier } from "#app/data/mystery-encounters/mystery-encounter";
|
||||
import { PlayerPokemon } from "#app/field/pokemon";
|
||||
import { HUMAN_TRANSITABLE_BIOMES } from "#app/data/mystery-encounters/mystery-encounters";
|
||||
import { PokemonSalesmanEncounter } from "#app/data/mystery-encounters/encounters/pokemon-salesman-encounter";
|
||||
|
||||
const namespace = "mysteryEncounter:pokemonSalesman";
|
||||
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
||||
const defaultBiome = Biome.CAVE;
|
||||
const defaultWave = 45;
|
||||
|
||||
describe("The Pokemon Salesman - Mystery Encounter", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
let scene: BattleScene;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({ type: Phaser.HEADLESS });
|
||||
});
|
||||
|
||||
beforeEach(async () => {
|
||||
game = new GameManager(phaserGame);
|
||||
scene = game.scene;
|
||||
game.override.mysteryEncounterChance(100);
|
||||
game.override.mysteryEncounterTier(MysteryEncounterTier.COMMON);
|
||||
game.override.startingWave(defaultWave);
|
||||
game.override.startingBiome(defaultBiome);
|
||||
|
||||
const biomeMap = new Map<Biome, MysteryEncounterType[]>([
|
||||
[Biome.VOLCANO, [MysteryEncounterType.MYSTERIOUS_CHALLENGERS]],
|
||||
]);
|
||||
HUMAN_TRANSITABLE_BIOMES.forEach(biome => {
|
||||
biomeMap.set(biome, [MysteryEncounterType.POKEMON_SALESMAN]);
|
||||
});
|
||||
vi.spyOn(MysteryEncounters, "mysteryEncountersByBiome", "get").mockReturnValue(biomeMap);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
vi.clearAllMocks();
|
||||
vi.resetAllMocks();
|
||||
});
|
||||
|
||||
it("should have the correct properties", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||
|
||||
expect(PokemonSalesmanEncounter.encounterType).toBe(MysteryEncounterType.POKEMON_SALESMAN);
|
||||
expect(PokemonSalesmanEncounter.encounterTier).toBe(MysteryEncounterTier.ULTRA);
|
||||
expect(PokemonSalesmanEncounter.dialogue).toBeDefined();
|
||||
expect(PokemonSalesmanEncounter.dialogue.intro).toStrictEqual([
|
||||
{ text: `${namespace}:intro` },
|
||||
{ speaker: "mysteryEncounter:pokemonSalesman:speaker", text: "mysteryEncounter:pokemonSalesman:intro_dialogue" }
|
||||
]);
|
||||
expect(PokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.title).toBe(`${namespace}:title`);
|
||||
expect(PokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.description).toBe(`${namespace}:description`);
|
||||
expect(PokemonSalesmanEncounter.dialogue.encounterOptionsDialogue.query).toBe(`${namespace}:query`);
|
||||
expect(PokemonSalesmanEncounter.options.length).toBe(2);
|
||||
});
|
||||
|
||||
it("should not spawn outside of HUMAN_TRANSITABLE_BIOMES", async () => {
|
||||
game.override.startingBiome(Biome.VOLCANO);
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
expect(scene.currentBattle?.mysteryEncounter?.encounterType).not.toBe(MysteryEncounterType.POKEMON_SALESMAN);
|
||||
});
|
||||
|
||||
it("should not run below wave 10", async () => {
|
||||
game.override.startingWave(9);
|
||||
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
expect(scene.currentBattle?.mysteryEncounter?.encounterType).not.toBe(MysteryEncounterType.POKEMON_SALESMAN);
|
||||
});
|
||||
|
||||
it("should not run above wave 179", async () => {
|
||||
game.override.startingWave(181);
|
||||
|
||||
await game.runToMysteryEncounter();
|
||||
|
||||
expect(scene.currentBattle.mysteryEncounter).toBeUndefined();
|
||||
});
|
||||
|
||||
it("should initialize fully ", async () => {
|
||||
vi.spyOn(scene, "currentBattle", "get").mockReturnValue({ mysteryEncounter: PokemonSalesmanEncounter } as Battle);
|
||||
|
||||
const { onInit } = PokemonSalesmanEncounter;
|
||||
|
||||
expect(PokemonSalesmanEncounter.onInit).toBeDefined();
|
||||
|
||||
const onInitResult = onInit(scene);
|
||||
|
||||
expect(PokemonSalesmanEncounter.dialogueTokens?.purchasePokemon).toBeDefined();
|
||||
expect(PokemonSalesmanEncounter.dialogueTokens?.price).toBeDefined();
|
||||
expect(PokemonSalesmanEncounter.misc.pokemon instanceof PlayerPokemon).toBeTruthy();
|
||||
expect(PokemonSalesmanEncounter.misc?.price?.toString()).toBe(PokemonSalesmanEncounter.dialogueTokens?.price);
|
||||
expect(onInitResult).toBe(true);
|
||||
});
|
||||
|
||||
describe("Option 1 - Purchase the pokemon", () => {
|
||||
it("should have the correct properties", () => {
|
||||
const option1 = PokemonSalesmanEncounter.options[0];
|
||||
expect(option1.optionMode).toBe(EncounterOptionMode.DEFAULT_OR_SPECIAL);
|
||||
expect(option1.dialogue).toBeDefined();
|
||||
expect(option1.dialogue).toStrictEqual({
|
||||
buttonLabel: `${namespace}:option:1:label`,
|
||||
buttonTooltip: `${namespace}:option:1:tooltip`,
|
||||
selected: [
|
||||
{
|
||||
text: `${namespace}:option:1:selected_message`,
|
||||
},
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
it("Should update the player's money properly", async () => {
|
||||
const initialMoney = 20000;
|
||||
scene.money = initialMoney;
|
||||
const updateMoneySpy = vi.spyOn(EncounterPhaseUtils, "updatePlayerMoney");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
const price = scene.currentBattle.mysteryEncounter.misc.price;
|
||||
|
||||
expect(updateMoneySpy).toHaveBeenCalledWith(scene, -price, true, false);
|
||||
expect(scene.money).toBe(initialMoney - price);
|
||||
});
|
||||
|
||||
it("Should add the Pokemon to the party", async () => {
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||
|
||||
const initialPartySize = scene.getParty().length;
|
||||
const pokemonName = scene.currentBattle.mysteryEncounter.misc.pokemon.name;
|
||||
|
||||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
expect(scene.getParty().length).toBe(initialPartySize + 1);
|
||||
expect(scene.getParty().find(p => p.name === pokemonName) instanceof PlayerPokemon).toBeTruthy();
|
||||
});
|
||||
|
||||
it("should leave encounter without battle", async () => {
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("Option 2 - Leave", () => {
|
||||
it("should leave encounter without battle", async () => {
|
||||
const leaveEncounterWithoutBattleSpy = vi.spyOn(EncounterPhaseUtils, "leaveEncounterWithoutBattle");
|
||||
|
||||
await game.runToMysteryEncounter(MysteryEncounterType.POKEMON_SALESMAN, defaultParty);
|
||||
await runSelectMysteryEncounterOption(game, 2);
|
||||
|
||||
expect(leaveEncounterWithoutBattleSpy).toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
|
@ -22,6 +22,7 @@ import { BattlerTagType } from "#enums/battler-tag-type";
|
|||
import { PokemonMove } from "#app/field/pokemon";
|
||||
import { Mode } from "#app/ui/ui";
|
||||
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||
import { PokemonBaseStatTotalModifier } from "#app/modifier/modifier";
|
||||
|
||||
const namespace = "mysteryEncounter:theStrongStuff";
|
||||
const defaultParty = [Species.LAPRAS, Species.GENGAR, Species.ABRA];
|
||||
|
@ -153,7 +154,9 @@ describe("The Strong Stuff - Mystery Encounter", () => {
|
|||
await runSelectMysteryEncounterOption(game, 1);
|
||||
|
||||
const bstsAfter = scene.getParty().map(p => {
|
||||
return p.getSpeciesForm().getBaseStatTotal();
|
||||
const baseStats = p.getSpeciesForm().baseStats.slice(0);
|
||||
scene.applyModifiers(PokemonBaseStatTotalModifier, true, p, baseStats);
|
||||
return baseStats.reduce((a, b) => a + b);
|
||||
});
|
||||
|
||||
expect(bstsAfter[0]).toEqual(bstsPrior[0] - 20 * 6);
|
||||
|
|
|
@ -298,7 +298,7 @@ describe("Mystery Encounter Utils", () => {
|
|||
const spy = vi.spyOn(game.scene.ui, "showDialogue");
|
||||
|
||||
showEncounterDialogue(scene, "mysteryEncounter:unit_test_dialogue", "mysteryEncounter:unit_test_dialogue");
|
||||
expect(spy).toHaveBeenCalledWith("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", "valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", null, undefined, 0, 0);
|
||||
expect(spy).toHaveBeenCalledWith("valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", "valuevalue {{testvalue}} {{test1}} {{test}} {{test\\}} {{test\\}} {test}}", null, expect.any(Function), 0);
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -248,6 +248,14 @@ export default class MockText {
|
|||
};
|
||||
}
|
||||
|
||||
disableInteractive() {
|
||||
// Disables interaction with this Game Object.
|
||||
}
|
||||
|
||||
clearTint() {
|
||||
// Clears tint on this Game Object.
|
||||
}
|
||||
|
||||
add(obj) {
|
||||
// Adds a child to this Game Object.
|
||||
this.list.push(obj);
|
||||
|
|
Loading…
Reference in New Issue