mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-19 13:59:27 +02:00
Added tests for failing catches
This commit is contained in:
parent
b32bb090d4
commit
6c22ab9483
@ -82,6 +82,14 @@ export class GameMode implements GameModeConfig {
|
||||
return this.challenges.some(c => c.id === challenge && c.value !== 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to see if a GameMode has any challenges, needed in tests
|
||||
* @returns true if the game mode has at least one challenge
|
||||
*/
|
||||
hasAnyChallenges(): boolean {
|
||||
return this.challenges.length > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper function to see if the game mode is using fresh start
|
||||
* @returns true if a fresh start challenge is being applied
|
||||
|
@ -390,12 +390,12 @@ export class CommandPhase extends FieldPhase {
|
||||
const isClassicFinalBoss = globalScene.gameMode.isBattleClassicFinalBoss(globalScene.currentBattle.waveIndex);
|
||||
const isEndlessMinorBoss = globalScene.gameMode.isEndlessMinorBoss(globalScene.currentBattle.waveIndex);
|
||||
const isFullFreshStart = globalScene.gameMode.isFullFreshStartChallenge();
|
||||
|
||||
const someUncaughtSpeciesOnField = globalScene
|
||||
.getEnemyField()
|
||||
.some(p => p.isActive() && !dexData[p.species.speciesId].caughtAttr);
|
||||
const missingMultipleStarters =
|
||||
gameData.getStarterCount(d => !!d.caughtAttr) < Object.keys(speciesStarterCosts).length - 1;
|
||||
|
||||
if (biomeType === BiomeId.END) {
|
||||
if (
|
||||
(isClassic && !isClassicFinalBoss && someUncaughtSpeciesOnField) ||
|
||||
@ -410,7 +410,7 @@ export class CommandPhase extends FieldPhase {
|
||||
(isEndless && isEndlessMinorBoss) ||
|
||||
isDaily
|
||||
) {
|
||||
// Uncatchable final boss in classic and endless
|
||||
// Uncatchable final boss in classic, endless and daily
|
||||
this.queueShowText("battle:noPokeballForceFinalBoss");
|
||||
} else {
|
||||
return true;
|
||||
@ -446,10 +446,8 @@ export class CommandPhase extends FieldPhase {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Restricts use of Master Ball against final boss in challenges
|
||||
const restrictMasterBall =
|
||||
globalScene.gameMode.isChallenge &&
|
||||
globalScene.gameMode.isBattleClassicFinalBoss(globalScene.currentBattle.waveIndex);
|
||||
const isChallengeActive = globalScene.gameMode.hasAnyChallenges();
|
||||
const isFinalBoss = globalScene.gameMode.isBattleClassicFinalBoss(globalScene.currentBattle.waveIndex);
|
||||
|
||||
const numBallTypes = 5;
|
||||
if (cursor < numBallTypes) {
|
||||
@ -460,10 +458,16 @@ export class CommandPhase extends FieldPhase {
|
||||
// TODO: Decouple this hardcoded exception for wonder guard and just check the target...
|
||||
!targetPokemon?.hasAbility(AbilityId.WONDER_GUARD, false, true)
|
||||
) {
|
||||
if (restrictMasterBall) {
|
||||
// When facing the final boss, it must be weakened unless a Master Ball is used AND no challenges are active.
|
||||
// The message is customized for the final boss.
|
||||
if (
|
||||
isFinalBoss &&
|
||||
(cursor < PokeballType.MASTER_BALL || (cursor === PokeballType.MASTER_BALL && isChallengeActive))
|
||||
) {
|
||||
this.queueShowText("battle:noPokeballForceFinalBossCatchable");
|
||||
return false;
|
||||
}
|
||||
// When facing any other boss, Master Ball can always be used, and we use the standard message.
|
||||
if (cursor < PokeballType.MASTER_BALL) {
|
||||
this.queueShowText("battle:noPokeballStrong");
|
||||
return false;
|
||||
|
244
test/field/catching.test.ts
Normal file
244
test/field/catching.test.ts
Normal file
@ -0,0 +1,244 @@
|
||||
import { pokerogueApi } from "#api/pokerogue-api";
|
||||
import { BiomeId } from "#enums/biome-id";
|
||||
import { Challenges } from "#enums/challenges";
|
||||
import { GameModes } from "#enums/game-modes";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { PokeballType } from "#enums/pokeball";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import i18next from "i18next";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
/**
|
||||
* Helper function to run tests on cactching mons
|
||||
*
|
||||
* @remarks
|
||||
* - Starts a run on the desired game mode, then attempts to throw a ball
|
||||
* - If still in the command phase (meaning the ball did not catch) uses a move to proceed
|
||||
* - If expecting success, checks that party length has increased by 1
|
||||
* - Otherwise, checks that {@link i18next} has been called on the requested error key
|
||||
*
|
||||
* @param game {@link GameManager} The game manager from the test
|
||||
* @param ball {@link PokeballType} The type of pokéball to be used for the catch attempt
|
||||
* @param expectedResult {@link string} Either "success", if the enemy should be caught, or the expected locales error key
|
||||
* @param mode One between "classic", "daily", and "challenge", defaults to "classic".
|
||||
*/
|
||||
async function runPokeballTest(
|
||||
game: GameManager,
|
||||
ball: PokeballType,
|
||||
expectedResult: string,
|
||||
mode: "classic" | "daily" | "challenge" = "classic",
|
||||
) {
|
||||
if (mode === "classic") {
|
||||
await game.classicMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
} else if (mode === "daily") {
|
||||
// Have to do it this way because daily run is weird...
|
||||
await game.runToFinalBossEncounter([SpeciesId.MAGIKARP], GameModes.DAILY);
|
||||
} else if (mode === "challenge") {
|
||||
await game.challengeMode.startBattle([SpeciesId.MAGIKARP]);
|
||||
}
|
||||
|
||||
const partyLength = game.scene.getPlayerParty().length;
|
||||
|
||||
game.scene.pokeballCounts[ball] = 1;
|
||||
|
||||
const tSpy = vi.spyOn(i18next, "t").mockImplementation((key: string) => key);
|
||||
|
||||
game.doThrowPokeball(ball);
|
||||
|
||||
// If still in the command phase due to ball failing, use a move to go on
|
||||
if (game.isCurrentPhase("CommandPhase")) {
|
||||
game.move.select(MoveId.SPLASH);
|
||||
}
|
||||
|
||||
await game.toEndOfTurn();
|
||||
if (expectedResult === "success") {
|
||||
// Check that a mon has been caught by noticing that party length has increased
|
||||
expect(game.scene.getPlayerParty()).toHaveLength(partyLength + 1);
|
||||
} else {
|
||||
expect(tSpy).toHaveBeenCalledWith(expectedResult);
|
||||
}
|
||||
}
|
||||
|
||||
describe("Throwing balls in classic", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.startingWave(199)
|
||||
.startingBiome(BiomeId.END)
|
||||
.battleStyle("single")
|
||||
.moveset([MoveId.SPLASH])
|
||||
.enemyMoveset([MoveId.SPLASH])
|
||||
.startingLevel(9999);
|
||||
});
|
||||
|
||||
it("throwing ball at paradox mon", async () => {
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForce");
|
||||
});
|
||||
|
||||
it("throwing ball at two paradox mons", async () => {
|
||||
game.override.battleStyle("double");
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballMulti");
|
||||
});
|
||||
|
||||
it("throwing ball at previously caught paradox mon", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "success");
|
||||
});
|
||||
|
||||
it("throwing ball at final boss", async () => {
|
||||
game.override.startingWave(200);
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss");
|
||||
});
|
||||
|
||||
it("throwing rogue ball at final boss with full dex", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
game.override.startingWave(200);
|
||||
await runPokeballTest(game, PokeballType.ROGUE_BALL, "battle:noPokeballForceFinalBossCatchable");
|
||||
});
|
||||
|
||||
it("throwing master ball at final boss with full dex", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
game.override.startingWave(200);
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "success");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Throwing balls in fresh start challenge", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.challengeMode.addChallenge(Challenges.FRESH_START, 2, 1);
|
||||
game.override
|
||||
.startingWave(199)
|
||||
.startingBiome(BiomeId.END)
|
||||
.battleStyle("single")
|
||||
.moveset([MoveId.SPLASH])
|
||||
.enemyMoveset([MoveId.SPLASH])
|
||||
.startingLevel(9999);
|
||||
});
|
||||
|
||||
// Tests should give the same result as a normal classic run, except for the last one
|
||||
it("throwing ball at paradox mon", async () => {
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForce", "challenge");
|
||||
});
|
||||
|
||||
it("throwing ball at previously caught paradox mon", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "success", "challenge");
|
||||
});
|
||||
|
||||
it("throwing ball at final boss", async () => {
|
||||
game.override.startingWave(200);
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss", "challenge");
|
||||
});
|
||||
|
||||
it("throwing rogue ball at final boss with full dex", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
game.override.startingWave(200);
|
||||
await runPokeballTest(game, PokeballType.ROGUE_BALL, "battle:noPokeballForceFinalBossCatchable", "challenge");
|
||||
});
|
||||
|
||||
// If a challenge is active, even if the dex is complete we still need to weaken the final boss to master ball it
|
||||
it("throwing ball at final boss with full dex", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
game.override.startingWave(200);
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBossCatchable", "challenge");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Throwing balls in full fresh start challenge", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.challengeMode.addChallenge(Challenges.FRESH_START, 1, 1);
|
||||
game.override
|
||||
.startingWave(199)
|
||||
.startingBiome(BiomeId.END)
|
||||
.battleStyle("single")
|
||||
.moveset([MoveId.SPLASH])
|
||||
.enemyMoveset([MoveId.SPLASH])
|
||||
.startingLevel(9999);
|
||||
});
|
||||
|
||||
// Paradox and final boss can NEVER be caught in the full fresh start challenge
|
||||
it("throwing ball at previously caught paradox mon", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForce", "challenge");
|
||||
});
|
||||
|
||||
it("throwing ball at final boss with full dex", async () => {
|
||||
await game.importData("./test/test-utils/saves/everything.prsv");
|
||||
game.override.startingWave(200);
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss", "challenge");
|
||||
});
|
||||
});
|
||||
|
||||
describe("Throwing balls in daily run", () => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
beforeAll(() => {
|
||||
phaserGame = new Phaser.Game({
|
||||
type: Phaser.HEADLESS,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
game.phaseInterceptor.restoreOg();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
vi.spyOn(pokerogueApi.daily, "getSeed").mockResolvedValue("test-seed");
|
||||
game.override
|
||||
.startingWave(50)
|
||||
.startingBiome(BiomeId.END)
|
||||
.battleStyle("single")
|
||||
.moveset([MoveId.SPLASH])
|
||||
.enemyMoveset([MoveId.SPLASH])
|
||||
.startingLevel(9999);
|
||||
});
|
||||
|
||||
it("throwing ball at daily run boss", async () => {
|
||||
await runPokeballTest(game, PokeballType.MASTER_BALL, "battle:noPokeballForceFinalBoss", "daily");
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user