[Refactor] Make phaseManager#unshiftPhase and #pushPhase variadic

https://github.com/pagefaultgames/pokerogue/pull/6776
This commit is contained in:
Bertie690 2025-12-18 22:11:11 -05:00 committed by GitHub
parent c7bdfe7ed8
commit 8f4243853d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 36 additions and 20 deletions

View File

@ -113,6 +113,7 @@ import { UnlockPhase } from "#phases/unlock-phase";
import { VictoryPhase } from "#phases/victory-phase";
import { WeatherEffectPhase } from "#phases/weather-effect-phase";
import type { PhaseConditionFunc, PhaseMap, PhaseString } from "#types/phase-types";
import type { NonEmptyTuple } from "type-fest";
/**
* Object that holds all of the phase constructors.
@ -275,21 +276,34 @@ export class PhaseManager {
}
/**
* Adds a phase to the end of the queue
* @param phase - The {@linkcode Phase} to add
* Add one or more Phases to the end of the queue.
* They will run once all phases already in the queue have ended.
* @param phases - One or more {@linkcode Phase}s to add
*/
public pushPhase(phase: Phase): void {
this.phaseQueue.pushPhase(this.checkDynamic(phase));
public pushPhase(...phases: NonEmptyTuple<Phase>): void {
for (const phase of phases) {
this.phaseQueue.pushPhase(this.checkDynamic(phase));
}
}
/**
* Queue a phase to be run immediately after the current phase finishes. \
* Queue one or more phases to be run immediately after the current phase finishes. \
* Unshifted phases are run in FIFO order if multiple are queued during a single phase's execution.
* @param phase - The {@linkcode Phase} to add
* @param phases - One or more {@linkcode Phase}s to add
* @privateRemarks
* Any newly-unshifted `MovePhase`s will be queued after the next `MoveEndPhase`.
*/
public unshiftPhase(phase: Phase): void {
const toAdd = this.checkDynamic(phase);
phase.is("MovePhase") ? this.phaseQueue.addAfter(toAdd, "MoveEndPhase") : this.phaseQueue.addPhase(toAdd);
// NB: I'd like to restrict this to only allow passing 1 `MovePhase` at a time, but this causes TS to
// flip the hell out with `Parameters`...
public unshiftPhase(...phases: NonEmptyTuple<Phase>): void {
for (const phase of phases) {
const toAdd = this.checkDynamic(phase);
if (phase.is("MovePhase")) {
this.phaseQueue.addAfter(toAdd, "MoveEndPhase");
} else {
this.phaseQueue.addPhase(toAdd);
}
}
}
/**

View File

@ -9,7 +9,7 @@ import { ATrainersTestEncounter } from "#mystery-encounters/a-trainers-test-enco
import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils";
import * as MysteryEncounters from "#mystery-encounters/mystery-encounters";
import { HUMAN_TRANSITABLE_BIOMES } from "#mystery-encounters/mystery-encounters";
import { PartyHealPhase } from "#phases/party-heal-phase";
import type { PartyHealPhase } from "#phases/party-heal-phase";
import { SelectModifierPhase } from "#phases/select-modifier-phase";
import {
runMysteryEncounterToEnd,
@ -165,8 +165,8 @@ describe("A Trainer's Test - Mystery Encounter", () => {
await game.runToMysteryEncounter(MysteryEncounterType.A_TRAINERS_TEST, defaultParty);
await runMysteryEncounterToEnd(game, 2);
const partyHealPhases = phaseSpy.mock.calls.filter(p => p[0] instanceof PartyHealPhase).map(p => p[0]);
expect(partyHealPhases.length).toBe(1);
const partyHealPhases = phaseSpy.mock.calls.flat().filter((p): p is PartyHealPhase => p.is("PartyHealPhase"));
expect(partyHealPhases).toHaveLength(1);
});
it("Should reward the player with a Rare egg", async () => {

View File

@ -9,8 +9,8 @@ import { UiMode } from "#enums/ui-mode";
import { DancingLessonsEncounter } from "#mystery-encounters/dancing-lessons-encounter";
import * as EncounterPhaseUtils from "#mystery-encounters/encounter-phase-utils";
import * as MysteryEncounters from "#mystery-encounters/mystery-encounters";
import { LearnMovePhase } from "#phases/learn-move-phase";
import { MovePhase } from "#phases/move-phase";
import type { LearnMovePhase } from "#phases/learn-move-phase";
import type { MovePhase } from "#phases/move-phase";
import { MysteryEncounterPhase } from "#phases/mystery-encounter-phases";
import {
runMysteryEncounterToEnd,
@ -110,9 +110,9 @@ describe("Dancing Lessons - Mystery Encounter", () => {
const moveset = enemyField[0].moveset.map(m => m.moveId);
expect(moveset.some(m => m === MoveId.REVELATION_DANCE)).toBeTruthy();
const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]);
expect(movePhases.length).toBe(1);
expect(movePhases.filter(p => (p as MovePhase).move.moveId === MoveId.REVELATION_DANCE).length).toBe(1); // Revelation Dance used before battle
const movePhases = phaseSpy.mock.calls.flat().filter((p): p is MovePhase => p.is("MovePhase"));
expect(movePhases).toHaveLength(1);
expect(movePhases[0].move.moveId).toBe(MoveId.REVELATION_DANCE); // Revelation Dance used before battle
});
it("should have a Baton in the rewards after battle", async () => {
@ -159,7 +159,7 @@ describe("Dancing Lessons - Mystery Encounter", () => {
game.field.getPlayerPokemon().moveset = [];
await runMysteryEncounterToEnd(game, 2, { pokemonNo: 1 });
const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof LearnMovePhase).map(p => p[0]);
const movePhases = phaseSpy.mock.calls.filter(p => p.some(i => i.is("LearnMovePhase"))).map(p => p[0]);
expect(movePhases.length).toBe(1);
expect(movePhases.filter(p => (p as LearnMovePhase)["moveId"] === MoveId.REVELATION_DANCE).length).toBe(1); // Revelation Dance taught to pokemon
});

View File

@ -123,8 +123,10 @@ describe("Uncommon Breed - Mystery Encounter", () => {
expect(enemyField.length).toBe(1);
expect(enemyField[0].species.speciesId).toBe(speciesToSpawn);
const statStagePhases = unshiftPhaseSpy.mock.calls.find(p => p[0] instanceof StatStageChangePhase)?.[0] as any;
expect(statStagePhases.stats).toEqual([Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]);
const statStagePhase = unshiftPhaseSpy.mock.calls
.flat()
.find((p): p is StatStageChangePhase => p.is("StatStageChangePhase"));
expect(statStagePhase?.["stats"]).toEqual([Stat.ATK, Stat.DEF, Stat.SPATK, Stat.SPDEF, Stat.SPD]);
// Should have used its egg move pre-battle
const movePhases = phaseSpy.mock.calls.filter(p => p[0] instanceof MovePhase).map(p => p[0]);