pokerogue/test/phases/select-reward-phase.test.ts
Wlowscha dac9e202a0
[Modifier Refactor] Modernize reward pool (#6208)
* Added missing `export`s to classes

* Created `allRewards` object

* RewardPool now uses ids; function to generate appropriate reward from id (including held item or trainer item)

* Added generateRewardOptionFromId function

* Using `RewardSpecs` for predetermined reward generation

* Removed RewardOverride

* Removed rewardInitObj

* Removed WeightedReward

* Proper initialization of allRewards
2025-08-04 09:04:48 +02:00

282 lines
12 KiB
TypeScript

import type { BattleScene } from "#app/battle-scene";
import { allRewards } from "#data/data-lists";
import { AbilityId } from "#enums/ability-id";
import { Button } from "#enums/buttons";
import { HeldItemId } from "#enums/held-item-id";
import { MoveId } from "#enums/move-id";
import { RewardId } from "#enums/reward-id";
import { RarityTier } from "#enums/reward-tier";
import { SpeciesId } from "#enums/species-id";
import { TrainerItemId } from "#enums/trainer-item-id";
import { UiMode } from "#enums/ui-mode";
import { PlayerPokemon } from "#field/pokemon";
import type { HeldItemReward, TrainerItemReward } from "#items/reward";
import { RewardOption } from "#items/reward";
import type { CustomRewardSettings } from "#items/reward-pool-utils";
import { SelectRewardPhase } from "#phases/select-reward-phase";
import { GameManager } from "#test/test-utils/game-manager";
import { initSceneWithoutEncounterPhase } from "#test/test-utils/game-manager-utils";
import { RewardSelectUiHandler } from "#ui/reward-select-ui-handler";
import { shiftCharCodes } from "#utils/common";
import { getPokemonSpecies } from "#utils/pokemon-utils";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
describe("SelectRewardPhase", () => {
let phaserGame: Phaser.Game;
let game: GameManager;
let scene: BattleScene;
beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});
beforeEach(() => {
game = new GameManager(phaserGame);
scene = game.scene;
game.override
.moveset([MoveId.FISSURE, MoveId.SPLASH])
.ability(AbilityId.NO_GUARD)
.startingLevel(200)
.enemySpecies(SpeciesId.MAGIKARP);
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
it("should start a select modifier phase", async () => {
initSceneWithoutEncounterPhase(scene, [SpeciesId.ABRA, SpeciesId.VOLCARONA]);
const selectRewardPhase = new SelectRewardPhase();
scene.phaseManager.unshiftPhase(selectRewardPhase);
await game.phaseInterceptor.to(SelectRewardPhase);
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
});
it("should generate random modifiers", async () => {
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.VOLCARONA]);
game.move.select(MoveId.FISSURE);
await game.phaseInterceptor.to("SelectRewardPhase");
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
const rewardSelectHandler = scene.ui.handlers.find(
h => h instanceof RewardSelectUiHandler,
) as RewardSelectUiHandler;
expect(rewardSelectHandler.options.length).toEqual(3);
});
it("should modify reroll cost", async () => {
initSceneWithoutEncounterPhase(scene, [SpeciesId.ABRA, SpeciesId.VOLCARONA]);
const options = [
new RewardOption(allRewards.POTION(), 0, RarityTier.COMMON, 100),
new RewardOption(allRewards.ETHER(), 0, RarityTier.COMMON, 400),
new RewardOption(allRewards.REVIVE(), 0, RarityTier.COMMON, 1000),
];
const selectRewardPhase1 = new SelectRewardPhase(0, undefined, {
guaranteedRewardOptions: options,
});
const selectRewardPhase2 = new SelectRewardPhase(0, undefined, {
guaranteedRewardOptions: options,
rerollMultiplier: 2,
});
const cost1 = selectRewardPhase1.getRerollCost(false);
const cost2 = selectRewardPhase2.getRerollCost(false);
expect(cost2).toEqual(cost1 * 2);
});
it.todo("should generate random modifiers from reroll", async () => {
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.VOLCARONA]);
scene.money = 1000000;
scene.shopCursorTarget = 0;
game.move.select(MoveId.FISSURE);
await game.phaseInterceptor.to("SelectRewardPhase");
// TODO: nagivate the ui to reroll somehow
//const smphase = scene.phaseManager.getCurrentPhase() as SelectRewardPhase;
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
const rewardSelectHandler = scene.ui.handlers.find(
h => h instanceof RewardSelectUiHandler,
) as RewardSelectUiHandler;
expect(rewardSelectHandler.options.length).toEqual(3);
rewardSelectHandler.processInput(Button.ACTION);
expect(scene.money).toBe(1000000 - 250);
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
expect(rewardSelectHandler.options.length).toEqual(3);
});
it.todo("should generate random modifiers of same tier for reroll with reroll lock", async () => {
game.override.startingTrainerItems([{ entry: TrainerItemId.LOCK_CAPSULE }]);
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.VOLCARONA]);
scene.money = 1000000;
// Just use fully random seed for this test
vi.spyOn(scene, "resetSeed").mockImplementation(() => {
scene.waveSeed = shiftCharCodes(scene.seed, 5);
Phaser.Math.RND.sow([scene.waveSeed]);
console.log("Wave Seed:", scene.waveSeed, 5);
scene.rngCounter = 0;
});
game.move.select(MoveId.FISSURE);
await game.phaseInterceptor.to("SelectRewardPhase");
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
const rewardSelectHandler = scene.ui.handlers.find(
h => h instanceof RewardSelectUiHandler,
) as RewardSelectUiHandler;
expect(rewardSelectHandler.options.length).toEqual(3);
const firstRollTiers: RarityTier[] = rewardSelectHandler.options.map(o => o.rewardOption.tier);
// TODO: nagivate ui to reroll with lock capsule enabled
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
expect(rewardSelectHandler.options.length).toEqual(3);
// Reroll with lock can still upgrade
expect(
rewardSelectHandler.options[0].rewardOption.tier - rewardSelectHandler.options[0].rewardOption.upgradeCount,
).toEqual(firstRollTiers[0]);
expect(
rewardSelectHandler.options[1].rewardOption.tier - rewardSelectHandler.options[1].rewardOption.upgradeCount,
).toEqual(firstRollTiers[1]);
expect(
rewardSelectHandler.options[2].rewardOption.tier - rewardSelectHandler.options[2].rewardOption.upgradeCount,
).toEqual(firstRollTiers[2]);
});
it("should generate custom modifiers", async () => {
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.VOLCARONA]);
scene.money = 1000000;
const customRewards: CustomRewardSettings = {
guaranteedRewardSpecs: [
allRewards.MEMORY_MUSHROOM,
allRewards.TM_ULTRA,
allRewards.LEFTOVERS,
allRewards.AMULET_COIN,
allRewards.GOLDEN_PUNCH,
],
};
const selectRewardPhase = new SelectRewardPhase(0, undefined, customRewards);
scene.phaseManager.unshiftPhase(selectRewardPhase);
game.move.select(MoveId.SPLASH);
await game.phaseInterceptor.to("SelectRewardPhase");
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
const rewardSelectHandler = scene.ui.handlers.find(
h => h instanceof RewardSelectUiHandler,
) as RewardSelectUiHandler;
expect(rewardSelectHandler.options.length).toEqual(5);
expect(rewardSelectHandler.options[0].rewardOption.type.id).toEqual(RewardId.MEMORY_MUSHROOM);
expect(rewardSelectHandler.options[1].rewardOption.type.id).toEqual(RewardId.TM_ULTRA);
expect(rewardSelectHandler.options[2].rewardOption.type.id).toEqual(RewardId.HELD_ITEM);
expect((rewardSelectHandler.options[2].rewardOption.type as HeldItemReward).itemId).toEqual(HeldItemId.LEFTOVERS);
expect(rewardSelectHandler.options[3].rewardOption.type.id).toEqual(RewardId.TRAINER_ITEM);
expect((rewardSelectHandler.options[3].rewardOption.type as TrainerItemReward).itemId).toEqual(
TrainerItemId.AMULET_COIN,
);
expect(rewardSelectHandler.options[4].rewardOption.type.id).toEqual(RewardId.HELD_ITEM);
expect((rewardSelectHandler.options[4].rewardOption.type as HeldItemReward).itemId).toEqual(
HeldItemId.GOLDEN_PUNCH,
);
});
it("should generate custom modifier tiers that can upgrade from luck", async () => {
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.VOLCARONA]);
scene.money = 1000000;
const customRewards: CustomRewardSettings = {
guaranteedRarityTiers: [
RarityTier.COMMON,
RarityTier.GREAT,
RarityTier.ULTRA,
RarityTier.ROGUE,
RarityTier.MASTER,
],
};
const pokemon = new PlayerPokemon(getPokemonSpecies(SpeciesId.BULBASAUR), 10, undefined, 0, undefined, true, 2);
// Fill party with max shinies
while (scene.getPlayerParty().length > 0) {
scene.getPlayerParty().pop();
}
scene.getPlayerParty().push(pokemon, pokemon, pokemon, pokemon, pokemon, pokemon);
const selectRewardPhase = new SelectRewardPhase(0, undefined, customRewards);
scene.phaseManager.unshiftPhase(selectRewardPhase);
game.move.select(MoveId.SPLASH);
await game.phaseInterceptor.to("SelectRewardPhase");
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
const rewardSelectHandler = scene.ui.handlers.find(
h => h instanceof RewardSelectUiHandler,
) as RewardSelectUiHandler;
expect(rewardSelectHandler.options.length).toEqual(5);
expect(
rewardSelectHandler.options[0].rewardOption.tier - rewardSelectHandler.options[0].rewardOption.upgradeCount,
).toEqual(RarityTier.COMMON);
expect(
rewardSelectHandler.options[1].rewardOption.tier - rewardSelectHandler.options[1].rewardOption.upgradeCount,
).toEqual(RarityTier.GREAT);
expect(
rewardSelectHandler.options[2].rewardOption.tier - rewardSelectHandler.options[2].rewardOption.upgradeCount,
).toEqual(RarityTier.ULTRA);
expect(
rewardSelectHandler.options[3].rewardOption.tier - rewardSelectHandler.options[3].rewardOption.upgradeCount,
).toEqual(RarityTier.ROGUE);
expect(
rewardSelectHandler.options[4].rewardOption.tier - rewardSelectHandler.options[4].rewardOption.upgradeCount,
).toEqual(RarityTier.MASTER);
});
it("should generate custom modifiers and modifier tiers together", async () => {
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.VOLCARONA]);
scene.money = 1000000;
const customRewards: CustomRewardSettings = {
guaranteedRewardSpecs: [allRewards.MEMORY_MUSHROOM, allRewards.TM_COMMON],
guaranteedRarityTiers: [RarityTier.MASTER, RarityTier.MASTER],
};
const selectRewardPhase = new SelectRewardPhase(0, undefined, customRewards);
scene.phaseManager.unshiftPhase(selectRewardPhase);
game.move.select(MoveId.SPLASH);
await game.phaseInterceptor.run(SelectRewardPhase);
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
const rewardSelectHandler = scene.ui.handlers.find(
h => h instanceof RewardSelectUiHandler,
) as RewardSelectUiHandler;
expect(rewardSelectHandler.options.length).toEqual(4);
expect(rewardSelectHandler.options[0].rewardOption.type.id).toEqual(RewardId.MEMORY_MUSHROOM);
expect(rewardSelectHandler.options[1].rewardOption.type.id).toEqual(RewardId.TM_COMMON);
expect(rewardSelectHandler.options[2].rewardOption.tier).toEqual(RarityTier.MASTER);
expect(rewardSelectHandler.options[3].rewardOption.tier).toEqual(RarityTier.MASTER);
});
it("should fill remaining modifiers if fillRemaining is true with custom modifiers", async () => {
await game.classicMode.startBattle([SpeciesId.ABRA, SpeciesId.VOLCARONA]);
scene.money = 1000000;
const customRewards: CustomRewardSettings = {
guaranteedRewardSpecs: [allRewards.MEMORY_MUSHROOM],
guaranteedRarityTiers: [RarityTier.MASTER],
fillRemaining: true,
};
const selectRewardPhase = new SelectRewardPhase(0, undefined, customRewards);
scene.phaseManager.unshiftPhase(selectRewardPhase);
game.move.select(MoveId.SPLASH);
await game.phaseInterceptor.run(SelectRewardPhase);
expect(scene.ui.getMode()).to.equal(UiMode.REWARD_SELECT);
const rewardSelectHandler = scene.ui.handlers.find(
h => h instanceof RewardSelectUiHandler,
) as RewardSelectUiHandler;
expect(rewardSelectHandler.options.length).toEqual(3);
expect(rewardSelectHandler.options[0].rewardOption.type.id).toEqual(RewardId.MEMORY_MUSHROOM);
expect(rewardSelectHandler.options[1].rewardOption.tier).toEqual(RarityTier.MASTER);
});
});