Skip to content

Commit

Permalink
[P1][Beta] Fix softlock when losing a run on local build (#4846)
Browse files Browse the repository at this point in the history
  • Loading branch information
PigeonBar authored Nov 11, 2024
1 parent cebedd2 commit 4802f51
Show file tree
Hide file tree
Showing 3 changed files with 103 additions and 5 deletions.
7 changes: 4 additions & 3 deletions src/phases/game-over-phase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -125,10 +125,9 @@ export class GameOverPhase extends BattlePhase {
}

const clear = (endCardPhase?: EndCardPhase) => {
if (newClear) {
this.handleUnlocks();
}
if (this.isVictory && newClear) {
this.handleUnlocks();

for (const species of this.firstRibbons) {
this.scene.unshiftPhase(new RibbonModifierRewardPhase(this.scene, modifierTypes.VOUCHER_PLUS, species));
}
Expand Down Expand Up @@ -183,6 +182,8 @@ export class GameOverPhase extends BattlePhase {
this.scene.gameData.offlineNewClear(this.scene).then(result => {
doGameOver(result);
});
} else {
doGameOver(false);
}
}

Expand Down
77 changes: 77 additions & 0 deletions src/test/phases/game-over-phase.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import { Biome } from "#enums/biome";
import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves";
import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { achvs } from "#app/system/achv";
import { Unlockables } from "#app/system/unlockables";

describe("Game Over Phase", () => {
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
.moveset([ Moves.MEMENTO, Moves.ICE_BEAM, Moves.SPLASH ])
.ability(Abilities.BALL_FETCH)
.battleType("single")
.disableCrits()
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.SPLASH)
.startingWave(200)
.startingBiome(Biome.END)
.startingLevel(10000);
});

it("winning a run should give rewards", async () => {
await game.classicMode.startBattle([ Species.BULBASAUR ]);
vi.spyOn(game.scene, "validateAchv");

// Note: `game.doKillOpponents()` does not properly handle final boss
// Final boss phase 1
game.move.select(Moves.ICE_BEAM);
await game.toNextTurn();

// Final boss phase 2
game.move.select(Moves.ICE_BEAM);
await game.phaseInterceptor.to("PostGameOverPhase", false);

// The game refused to actually give the vouchers during tests,
// so the best we can do is to check that their reward phases occurred.
expect(game.phaseInterceptor.log.includes("GameOverPhase")).toBe(true);
expect(game.phaseInterceptor.log.includes("UnlockPhase")).toBe(true);
expect(game.phaseInterceptor.log.includes("RibbonModifierRewardPhase")).toBe(true);
expect(game.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]).toBe(true);
expect(game.scene.validateAchv).toHaveBeenCalledWith(achvs.CLASSIC_VICTORY);
expect(game.scene.gameData.achvUnlocks[achvs.CLASSIC_VICTORY.id]).toBeTruthy();
});

it("losing a run should not give rewards", async () => {
await game.classicMode.startBattle([ Species.BULBASAUR ]);
vi.spyOn(game.scene, "validateAchv");

game.move.select(Moves.MEMENTO);
await game.phaseInterceptor.to("PostGameOverPhase", false);

expect(game.phaseInterceptor.log.includes("GameOverPhase")).toBe(true);
expect(game.phaseInterceptor.log.includes("UnlockPhase")).toBe(false);
expect(game.phaseInterceptor.log.includes("RibbonModifierRewardPhase")).toBe(false);
expect(game.phaseInterceptor.log.includes("GameOverModifierRewardPhase")).toBe(false);
expect(game.scene.gameData.unlocks[Unlockables.ENDLESS_MODE]).toBe(false);
expect(game.scene.validateAchv).not.toHaveBeenCalledWith(achvs.CLASSIC_VICTORY);
expect(game.scene.gameData.achvUnlocks[achvs.CLASSIC_VICTORY.id]).toBeFalsy();
});
});
24 changes: 22 additions & 2 deletions src/test/utils/phaseInterceptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ import {
import { ModifierRewardPhase } from "#app/phases/modifier-reward-phase";
import { PartyExpPhase } from "#app/phases/party-exp-phase";
import { ExpPhase } from "#app/phases/exp-phase";
import { GameOverPhase } from "#app/phases/game-over-phase";
import { RibbonModifierRewardPhase } from "#app/phases/ribbon-modifier-reward-phase";
import { GameOverModifierRewardPhase } from "#app/phases/game-over-modifier-reward-phase";
import { UnlockPhase } from "#app/phases/unlock-phase";
import { PostGameOverPhase } from "#app/phases/post-game-over-phase";

export interface PromptHandler {
phaseTarget?: string;
Expand Down Expand Up @@ -113,10 +118,15 @@ type PhaseClass =
| typeof MysteryEncounterBattlePhase
| typeof MysteryEncounterRewardsPhase
| typeof PostMysteryEncounterPhase
| typeof RibbonModifierRewardPhase
| typeof GameOverModifierRewardPhase
| typeof ModifierRewardPhase
| typeof PartyExpPhase
| typeof ExpPhase
| typeof EncounterPhase;
| typeof EncounterPhase
| typeof GameOverPhase
| typeof UnlockPhase
| typeof PostGameOverPhase;

type PhaseString =
| "LoginPhase"
Expand Down Expand Up @@ -167,10 +177,15 @@ type PhaseString =
| "MysteryEncounterBattlePhase"
| "MysteryEncounterRewardsPhase"
| "PostMysteryEncounterPhase"
| "RibbonModifierRewardPhase"
| "GameOverModifierRewardPhase"
| "ModifierRewardPhase"
| "PartyExpPhase"
| "ExpPhase"
| "EncounterPhase";
| "EncounterPhase"
| "GameOverPhase"
| "UnlockPhase"
| "PostGameOverPhase";

type PhaseInterceptorPhase = PhaseClass | PhaseString;

Expand Down Expand Up @@ -245,10 +260,15 @@ export default class PhaseInterceptor {
[ MysteryEncounterBattlePhase, this.startPhase ],
[ MysteryEncounterRewardsPhase, this.startPhase ],
[ PostMysteryEncounterPhase, this.startPhase ],
[ RibbonModifierRewardPhase, this.startPhase ],
[ GameOverModifierRewardPhase, this.startPhase ],
[ ModifierRewardPhase, this.startPhase ],
[ PartyExpPhase, this.startPhase ],
[ ExpPhase, this.startPhase ],
[ EncounterPhase, this.startPhase ],
[ GameOverPhase, this.startPhase ],
[ UnlockPhase, this.startPhase ],
[ PostGameOverPhase, this.startPhase ],
];

private endBySetMode = [
Expand Down

0 comments on commit 4802f51

Please sign in to comment.