mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-08-06 23:49:26 +02:00
[Balance] End of turn triggers won't occur when you end a biome (#6169)
* [Balance] End of turn triggers won't occur when you end a biome * Add tests * Move phase manipulation logic into `PhaseManager` * Rename "biome end" to "interlude" * Rename `TurnEndPhase#endOfBiome` to `upcomingInterlude` --------- Co-authored-by: Wlowscha <54003515+Wlowscha@users.noreply.github.com>
This commit is contained in:
parent
ede2a947ca
commit
10b9cfcdb0
@ -9,6 +9,7 @@ import { AttemptCapturePhase } from "#phases/attempt-capture-phase";
|
||||
import { AttemptRunPhase } from "#phases/attempt-run-phase";
|
||||
import { BattleEndPhase } from "#phases/battle-end-phase";
|
||||
import { BerryPhase } from "#phases/berry-phase";
|
||||
import { CheckInterludePhase } from "#phases/check-interlude-phase";
|
||||
import { CheckStatusEffectPhase } from "#phases/check-status-effect-phase";
|
||||
import { CheckSwitchPhase } from "#phases/check-switch-phase";
|
||||
import { CommandPhase } from "#phases/command-phase";
|
||||
@ -121,6 +122,7 @@ const PHASES = Object.freeze({
|
||||
AttemptRunPhase,
|
||||
BattleEndPhase,
|
||||
BerryPhase,
|
||||
CheckInterludePhase,
|
||||
CheckStatusEffectPhase,
|
||||
CheckSwitchPhase,
|
||||
CommandPhase,
|
||||
@ -665,4 +667,15 @@ export class PhaseManager {
|
||||
): void {
|
||||
this.startDynamicPhase(this.create(phase, ...args));
|
||||
}
|
||||
|
||||
/** Prevents end of turn effects from triggering when transitioning to a new biome on a X0 wave */
|
||||
public onInterlude(): void {
|
||||
const phasesToRemove = ["WeatherEffectPhase", "BerryPhase", "CheckStatusEffectPhase"];
|
||||
this.phaseQueue = this.phaseQueue.filter(p => !phasesToRemove.includes(p.phaseName));
|
||||
|
||||
const turnEndPhase = this.findPhase<TurnEndPhase>(p => p.phaseName === "TurnEndPhase");
|
||||
if (turnEndPhase) {
|
||||
turnEndPhase.upcomingInterlude = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
18
src/phases/check-interlude-phase.ts
Normal file
18
src/phases/check-interlude-phase.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { globalScene } from "#app/global-scene";
|
||||
import { Phase } from "#app/phase";
|
||||
|
||||
export class CheckInterludePhase extends Phase {
|
||||
public override readonly phaseName = "CheckInterludePhase";
|
||||
|
||||
public override start(): void {
|
||||
super.start();
|
||||
const { phaseManager } = globalScene;
|
||||
const { waveIndex } = globalScene.currentBattle;
|
||||
|
||||
if (waveIndex % 10 === 0 && globalScene.getEnemyParty().every(p => p.isFainted())) {
|
||||
phaseManager.onInterlude();
|
||||
}
|
||||
|
||||
this.end();
|
||||
}
|
||||
}
|
@ -18,6 +18,8 @@ import i18next from "i18next";
|
||||
|
||||
export class TurnEndPhase extends FieldPhase {
|
||||
public readonly phaseName = "TurnEndPhase";
|
||||
public upcomingInterlude = false;
|
||||
|
||||
start() {
|
||||
super.start();
|
||||
|
||||
@ -59,9 +61,11 @@ export class TurnEndPhase extends FieldPhase {
|
||||
pokemon.tempSummonData.waveTurnCount++;
|
||||
};
|
||||
|
||||
this.executeForAll(handlePokemon);
|
||||
if (!this.upcomingInterlude) {
|
||||
this.executeForAll(handlePokemon);
|
||||
|
||||
globalScene.arena.lapseTags();
|
||||
globalScene.arena.lapseTags();
|
||||
}
|
||||
|
||||
if (globalScene.arena.weather && !globalScene.arena.weather.lapse()) {
|
||||
globalScene.arena.trySetWeather(WeatherType.NONE);
|
||||
|
@ -218,6 +218,7 @@ export class TurnStartPhase extends FieldPhase {
|
||||
break;
|
||||
}
|
||||
}
|
||||
phaseManager.pushNew("CheckInterludePhase");
|
||||
|
||||
phaseManager.pushNew("WeatherEffectPhase");
|
||||
phaseManager.pushNew("BerryPhase");
|
||||
@ -227,10 +228,10 @@ export class TurnStartPhase extends FieldPhase {
|
||||
|
||||
phaseManager.pushNew("TurnEndPhase");
|
||||
|
||||
/**
|
||||
* this.end() will call shiftPhase(), which dumps everything from PrependQueue (aka everything that is unshifted()) to the front
|
||||
* of the queue and dequeues to start the next phase
|
||||
* this is important since stuff like SwitchSummon, AttemptRun, AttemptCapture Phases break the "flow" and should take precedence
|
||||
/*
|
||||
* `this.end()` will call `PhaseManager#shiftPhase()`, which dumps everything from `phaseQueuePrepend`
|
||||
* (aka everything that is queued via `unshift()`) to the front of the queue and dequeues to start the next phase.
|
||||
* This is important since stuff like `SwitchSummonPhase`, `AttemptRunPhase`, and `AttemptCapturePhase` break the "flow" and should take precedence
|
||||
*/
|
||||
this.end();
|
||||
}
|
||||
|
62
test/phases/check-biome-end-phase.test.ts
Normal file
62
test/phases/check-biome-end-phase.test.ts
Normal file
@ -0,0 +1,62 @@
|
||||
import { AbilityId } from "#enums/ability-id";
|
||||
import { BerryType } from "#enums/berry-type";
|
||||
import { MoveId } from "#enums/move-id";
|
||||
import { SpeciesId } from "#enums/species-id";
|
||||
import { WeatherType } from "#enums/weather-type";
|
||||
import { GameManager } from "#test/test-utils/game-manager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
|
||||
|
||||
describe("Check Biome End 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
|
||||
.enemySpecies(SpeciesId.MAGIKARP)
|
||||
.enemyMoveset(MoveId.SPLASH)
|
||||
.enemyAbility(AbilityId.BALL_FETCH)
|
||||
.ability(AbilityId.BALL_FETCH)
|
||||
.startingLevel(100);
|
||||
});
|
||||
|
||||
it("should not trigger end of turn effects when defeating the final pokemon of a biome in classic", async () => {
|
||||
game.override
|
||||
.startingWave(10)
|
||||
.weather(WeatherType.SANDSTORM)
|
||||
.startingHeldItems([{ name: "BERRY", type: BerryType.SITRUS }]);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const player = game.field.getPlayerPokemon();
|
||||
|
||||
player.hp = 1;
|
||||
|
||||
game.move.use(MoveId.EXTREME_SPEED);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
expect(player.hp).toBe(1);
|
||||
});
|
||||
|
||||
it("should not prevent end of turn effects when transitioning waves within a biome", async () => {
|
||||
game.override.weather(WeatherType.SANDSTORM);
|
||||
await game.classicMode.startBattle([SpeciesId.FEEBAS]);
|
||||
|
||||
const player = game.field.getPlayerPokemon();
|
||||
|
||||
game.move.use(MoveId.EXTREME_SPEED);
|
||||
await game.toEndOfTurn();
|
||||
|
||||
expect(player.hp).toBeLessThan(player.getMaxHp());
|
||||
});
|
||||
});
|
Loading…
Reference in New Issue
Block a user