[Test] Add Tests for Zen Mode Ability (#1978)
* added tests for zen mode - change form in battle * added tests to run some battle against trainer/rival & boss * added a test with a method to kill a pokemon * added an override in the clock mocked to reduce the time of fainting pokemon and thus reducing test time from 5s to less than 1s * added some more tests + doAttack, doKillOpponents, toNextWave, toNextTurn helper * added some more tests + doAttack, doKillOpponents, toNextWave, toNextTurn helper + fix some tests
This commit is contained in:
parent
32d222c9cd
commit
e29c08ba1f
|
@ -1079,6 +1079,10 @@ export class NextEncounterPhase extends EncounterPhase {
|
||||||
super(scene);
|
super(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
super.start();
|
||||||
|
}
|
||||||
|
|
||||||
doEncounter(): void {
|
doEncounter(): void {
|
||||||
this.scene.playBgm(undefined, true);
|
this.scene.playBgm(undefined, true);
|
||||||
|
|
||||||
|
@ -1497,6 +1501,10 @@ export class SwitchSummonPhase extends SummonPhase {
|
||||||
this.batonPass = batonPass;
|
this.batonPass = batonPass;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start(): void {
|
||||||
|
super.start();
|
||||||
|
}
|
||||||
|
|
||||||
preSummon(): void {
|
preSummon(): void {
|
||||||
if (!this.player) {
|
if (!this.player) {
|
||||||
if (this.slotIndex === -1) {
|
if (this.slotIndex === -1) {
|
||||||
|
|
|
@ -0,0 +1,142 @@
|
||||||
|
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
|
import * as overrides from "#app/overrides";
|
||||||
|
import {Abilities} from "#app/data/enums/abilities";
|
||||||
|
import {Species} from "#app/data/enums/species";
|
||||||
|
import {
|
||||||
|
CommandPhase,
|
||||||
|
DamagePhase,
|
||||||
|
EnemyCommandPhase,
|
||||||
|
MessagePhase,
|
||||||
|
PostSummonPhase,
|
||||||
|
SwitchPhase,
|
||||||
|
SwitchSummonPhase,
|
||||||
|
TurnEndPhase, TurnInitPhase,
|
||||||
|
TurnStartPhase,
|
||||||
|
} from "#app/phases";
|
||||||
|
import {Mode} from "#app/ui/ui";
|
||||||
|
import {Stat} from "#app/data/pokemon-stat";
|
||||||
|
import {Moves} from "#app/data/enums/moves";
|
||||||
|
import {getMovePosition} from "#app/test/utils/gameManagerUtils";
|
||||||
|
import {Command} from "#app/ui/command-ui-handler";
|
||||||
|
import {QuietFormChangePhase} from "#app/form-change-phase";
|
||||||
|
|
||||||
|
|
||||||
|
describe("Abilities - Zen mode", () => {
|
||||||
|
let phaserGame: Phaser.Game;
|
||||||
|
let game: GameManager;
|
||||||
|
|
||||||
|
beforeAll(() => {
|
||||||
|
phaserGame = new Phaser.Game({
|
||||||
|
type: Phaser.HEADLESS,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
game.phaseInterceptor.restoreOg();
|
||||||
|
});
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
game = new GameManager(phaserGame);
|
||||||
|
const moveToUse = Moves.SPLASH;
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
|
||||||
|
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(100);
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("ZEN MODE - not enough damage to change form", async() => {
|
||||||
|
const moveToUse = Moves.SPLASH;
|
||||||
|
await game.startBattle([
|
||||||
|
Species.DARMANITAN,
|
||||||
|
]);
|
||||||
|
game.scene.getParty()[0].stats[Stat.SPD] = 1;
|
||||||
|
game.scene.getParty()[0].stats[Stat.HP] = 100;
|
||||||
|
game.scene.getParty()[0].hp = 100;
|
||||||
|
expect(game.scene.getParty()[0].formIndex).toBe(0);
|
||||||
|
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
|
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||||
|
});
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
|
||||||
|
const movePosition = getMovePosition(game.scene, 0, moveToUse);
|
||||||
|
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
||||||
|
});
|
||||||
|
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(DamagePhase, false);
|
||||||
|
// await game.phaseInterceptor.runFrom(DamagePhase).to(DamagePhase, false);
|
||||||
|
const damagePhase = game.scene.getCurrentPhase() as DamagePhase;
|
||||||
|
damagePhase.updateAmount(40);
|
||||||
|
await game.phaseInterceptor.runFrom(DamagePhase).to(TurnEndPhase, false);
|
||||||
|
expect(game.scene.getParty()[0].hp).toBeLessThan(100);
|
||||||
|
expect(game.scene.getParty()[0].formIndex).toBe(0);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("ZEN MODE - enough damage to change form", async() => {
|
||||||
|
const moveToUse = Moves.SPLASH;
|
||||||
|
await game.startBattle([
|
||||||
|
Species.DARMANITAN,
|
||||||
|
]);
|
||||||
|
game.scene.getParty()[0].stats[Stat.SPD] = 1;
|
||||||
|
game.scene.getParty()[0].stats[Stat.HP] = 1000;
|
||||||
|
game.scene.getParty()[0].hp = 100;
|
||||||
|
expect(game.scene.getParty()[0].formIndex).toBe(0);
|
||||||
|
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
|
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||||
|
});
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
|
||||||
|
const movePosition = getMovePosition(game.scene, 0, moveToUse);
|
||||||
|
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
||||||
|
});
|
||||||
|
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(QuietFormChangePhase);
|
||||||
|
await game.phaseInterceptor.to(TurnInitPhase, false);
|
||||||
|
expect(game.scene.getParty()[0].hp).not.toBe(100);
|
||||||
|
expect(game.scene.getParty()[0].formIndex).not.toBe(0);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("ZEN MODE - kill pokemon while on zen mode", async() => {
|
||||||
|
const moveToUse = Moves.SPLASH;
|
||||||
|
await game.startBattle([
|
||||||
|
Species.DARMANITAN,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
game.scene.getParty()[0].stats[Stat.SPD] = 1;
|
||||||
|
game.scene.getParty()[0].stats[Stat.HP] = 1000;
|
||||||
|
game.scene.getParty()[0].hp = 100;
|
||||||
|
expect(game.scene.getParty()[0].formIndex).toBe(0);
|
||||||
|
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
|
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||||
|
});
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
|
||||||
|
const movePosition = getMovePosition(game.scene, 0, moveToUse);
|
||||||
|
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
||||||
|
});
|
||||||
|
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(DamagePhase, false);
|
||||||
|
// await game.phaseInterceptor.runFrom(DamagePhase).to(DamagePhase, false);
|
||||||
|
const damagePhase = game.scene.getCurrentPhase() as DamagePhase;
|
||||||
|
damagePhase.updateAmount(80);
|
||||||
|
await game.phaseInterceptor.runFrom(DamagePhase).to(QuietFormChangePhase);
|
||||||
|
expect(game.scene.getParty()[0].hp).not.toBe(100);
|
||||||
|
expect(game.scene.getParty()[0].formIndex).not.toBe(0);
|
||||||
|
await game.killPokemon(game.scene.getParty()[0]);
|
||||||
|
expect(game.scene.getParty()[0].isFainted()).toBe(true);
|
||||||
|
await game.phaseInterceptor.run(MessagePhase);
|
||||||
|
await game.phaseInterceptor.run(EnemyCommandPhase);
|
||||||
|
await game.phaseInterceptor.run(TurnStartPhase);
|
||||||
|
game.onNextPrompt("SwitchPhase", Mode.PARTY, () => {
|
||||||
|
game.scene.unshiftPhase(new SwitchSummonPhase(game.scene, 0, 1, false, false));
|
||||||
|
game.scene.ui.setMode(Mode.MESSAGE);
|
||||||
|
});
|
||||||
|
game.onNextPrompt("SwitchPhase", Mode.MESSAGE, () => {
|
||||||
|
game.endPhase();
|
||||||
|
});
|
||||||
|
await game.phaseInterceptor.run(SwitchPhase);
|
||||||
|
await game.phaseInterceptor.to(PostSummonPhase);
|
||||||
|
expect(game.scene.getParty()[1].formIndex).toBe(1);
|
||||||
|
}, 20000);
|
||||||
|
});
|
|
@ -6,7 +6,7 @@ import {Species} from "#app/data/enums/species";
|
||||||
import * as overrides from "../../overrides";
|
import * as overrides from "../../overrides";
|
||||||
import {Command} from "#app/ui/command-ui-handler";
|
import {Command} from "#app/ui/command-ui-handler";
|
||||||
import {
|
import {
|
||||||
CommandPhase,
|
CommandPhase, DamagePhase,
|
||||||
EncounterPhase,
|
EncounterPhase,
|
||||||
EnemyCommandPhase,
|
EnemyCommandPhase,
|
||||||
LoginPhase,
|
LoginPhase,
|
||||||
|
@ -15,7 +15,7 @@ import {
|
||||||
SelectStarterPhase,
|
SelectStarterPhase,
|
||||||
SummonPhase,
|
SummonPhase,
|
||||||
TitlePhase,
|
TitlePhase,
|
||||||
TurnInitPhase,
|
TurnInitPhase, VictoryPhase,
|
||||||
} from "#app/phases";
|
} from "#app/phases";
|
||||||
import {Moves} from "#app/data/enums/moves";
|
import {Moves} from "#app/data/enums/moves";
|
||||||
import GameManager from "#app/test/utils/gameManager";
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
|
@ -106,9 +106,7 @@ describe("Test Battle Phase", () => {
|
||||||
const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE);
|
const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE);
|
||||||
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
||||||
});
|
});
|
||||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase);
|
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(SelectModifierPhase, false);
|
||||||
expect(game.scene.ui?.getMode()).toBe(Mode.MODIFIER_SELECT);
|
|
||||||
expect(game.scene.getCurrentPhase().constructor.name).toBe(SelectModifierPhase.name);
|
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
|
||||||
it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async() => {
|
it("do attack wave 3 - single battle - regular - NO OHKO with opponent using non damage attack", async() => {
|
||||||
|
@ -128,7 +126,7 @@ describe("Test Battle Phase", () => {
|
||||||
const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE);
|
const movePosition = getMovePosition(game.scene, 0, Moves.TACKLE);
|
||||||
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
||||||
});
|
});
|
||||||
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase);
|
await game.phaseInterceptor.runFrom(EnemyCommandPhase).to(TurnInitPhase, false);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
|
||||||
it("load 100% data file", async() => {
|
it("load 100% data file", async() => {
|
||||||
|
@ -259,5 +257,71 @@ describe("Test Battle Phase", () => {
|
||||||
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
|
||||||
|
it("kill opponent pokemon", async() => {
|
||||||
|
const moveToUse = Moves.SPLASH;
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
|
||||||
|
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.DARMANITAN,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
|
game.scene.ui.setMode(Mode.FIGHT, (game.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||||
|
});
|
||||||
|
game.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
|
||||||
|
const movePosition = getMovePosition(game.scene, 0, moveToUse);
|
||||||
|
(game.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, movePosition, false);
|
||||||
|
});
|
||||||
|
await game.phaseInterceptor.to(DamagePhase, false);
|
||||||
|
await game.killPokemon(game.scene.currentBattle.enemyParty[0]);
|
||||||
|
expect(game.scene.currentBattle.enemyParty[0].isFainted()).toBe(true);
|
||||||
|
await game.phaseInterceptor.to(VictoryPhase, false);
|
||||||
|
}, 200000);
|
||||||
|
|
||||||
|
it("to next turn", async() => {
|
||||||
|
const moveToUse = Moves.SPLASH;
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
|
||||||
|
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
|
||||||
|
await game.startBattle();
|
||||||
|
const turn = game.scene.currentBattle.turn;
|
||||||
|
await game.doAttack(0);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(game.scene.currentBattle.turn).toBeGreaterThan(turn);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("to next wave with pokemon killed, single", async() => {
|
||||||
|
const moveToUse = Moves.SPLASH;
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
|
||||||
|
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
|
||||||
|
await game.startBattle();
|
||||||
|
const waveIndex = game.scene.currentBattle.waveIndex;
|
||||||
|
await game.doAttack(0);
|
||||||
|
await game.doKillOpponents();
|
||||||
|
await game.toNextWave();
|
||||||
|
expect(game.scene.currentBattle.waveIndex).toBeGreaterThan(waveIndex);
|
||||||
|
}, 20000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {afterEach, beforeAll, beforeEach, describe, it, vi} from "vitest";
|
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
|
||||||
import GameManager from "#app/test/utils/gameManager";
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
import Phaser from "phaser";
|
import Phaser from "phaser";
|
||||||
import * as overrides from "#app/overrides";
|
import * as overrides from "#app/overrides";
|
||||||
|
@ -22,18 +22,24 @@ describe("Test Battle Phase", () => {
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
game = new GameManager(phaserGame);
|
game = new GameManager(phaserGame);
|
||||||
});
|
const moveToUse = Moves.SPLASH;
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
it("should start phase", async() => {
|
|
||||||
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
|
vi.spyOn(overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(Species.MEWTWO);
|
||||||
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.ZEN_MODE);
|
||||||
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
|
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
|
||||||
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
||||||
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]);
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]);
|
||||||
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE,Moves.TACKLE,Moves.TACKLE,Moves.TACKLE]);
|
||||||
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
});
|
||||||
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
|
||||||
|
it.skip("to next turn", async() => {
|
||||||
await game.startBattle();
|
await game.startBattle();
|
||||||
}, 100000);
|
const turn = game.scene.currentBattle.turn;
|
||||||
|
await game.doAttack(0);
|
||||||
|
await game.toNextTurn();
|
||||||
|
expect(game.scene.currentBattle.turn).toBeGreaterThan(turn);
|
||||||
|
}, 20000);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest";
|
||||||
|
import {Mode} from "#app/ui/ui";
|
||||||
|
import {Species} from "#app/data/enums/species";
|
||||||
|
import * as overrides from "../../overrides";
|
||||||
|
import {
|
||||||
|
CommandPhase,
|
||||||
|
} from "#app/phases";
|
||||||
|
import {Moves} from "#app/data/enums/moves";
|
||||||
|
import GameManager from "#app/test/utils/gameManager";
|
||||||
|
import Phaser from "phaser";
|
||||||
|
import {Abilities} from "#app/data/enums/abilities";
|
||||||
|
|
||||||
|
describe("Test Battle 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);
|
||||||
|
vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA);
|
||||||
|
vi.spyOn(overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(2000);
|
||||||
|
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE]);
|
||||||
|
vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.HYDRATION);
|
||||||
|
vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.TACKLE, Moves.TACKLE, Moves.TACKLE, Moves.TACKLE]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("startBattle 2vs1 boss", async() => {
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 2vs2 boss", async() => {
|
||||||
|
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(10);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 2vs2 trainer", async() => {
|
||||||
|
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 2vs1 trainer", async() => {
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 2vs1 rival", async() => {
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 2vs2 rival", async() => {
|
||||||
|
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(8);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 1vs1 trainer", async() => {
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 2vs2 trainer", async() => {
|
||||||
|
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("startBattle 4vs2 trainer", async() => {
|
||||||
|
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(5);
|
||||||
|
await game.startBattle([
|
||||||
|
Species.BLASTOISE,
|
||||||
|
Species.CHARIZARD,
|
||||||
|
Species.DARKRAI,
|
||||||
|
Species.GABITE,
|
||||||
|
]);
|
||||||
|
expect(game.scene.ui?.getMode()).toBe(Mode.COMMAND);
|
||||||
|
expect(game.scene.getCurrentPhase().constructor.name).toBe(CommandPhase.name);
|
||||||
|
}, 20000);
|
||||||
|
});
|
||||||
|
|
|
@ -11,6 +11,6 @@ export default class TextInterceptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
getLatestMessage(): string {
|
getLatestMessage(): string {
|
||||||
return this.logs[this.logs.length - 1];
|
return this.logs.pop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,20 @@ import {Mode} from "#app/ui/ui";
|
||||||
import {generateStarter, waitUntil} from "#app/test/utils/gameManagerUtils";
|
import {generateStarter, waitUntil} from "#app/test/utils/gameManagerUtils";
|
||||||
import {
|
import {
|
||||||
CommandPhase,
|
CommandPhase,
|
||||||
|
DamagePhase,
|
||||||
EncounterPhase,
|
EncounterPhase,
|
||||||
LoginPhase,
|
FaintPhase,
|
||||||
PostSummonPhase,
|
LoginPhase, NewBattlePhase,
|
||||||
SelectGenderPhase,
|
SelectGenderPhase,
|
||||||
SelectStarterPhase,
|
SelectStarterPhase,
|
||||||
TitlePhase,
|
TitlePhase, TurnInitPhase,
|
||||||
} from "#app/phases";
|
} from "#app/phases";
|
||||||
import BattleScene from "#app/battle-scene.js";
|
import BattleScene from "#app/battle-scene.js";
|
||||||
import PhaseInterceptor from "#app/test/utils/phaseInterceptor";
|
import PhaseInterceptor from "#app/test/utils/phaseInterceptor";
|
||||||
import TextInterceptor from "#app/test/utils/TextInterceptor";
|
import TextInterceptor from "#app/test/utils/TextInterceptor";
|
||||||
import {GameModes, getGameMode} from "#app/game-mode";
|
import {GameModes, getGameMode} from "#app/game-mode";
|
||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
import { AES, enc } from "crypto-js";
|
import {AES, enc} from "crypto-js";
|
||||||
import {updateUserInfo} from "#app/account";
|
import {updateUserInfo} from "#app/account";
|
||||||
import {Species} from "#app/data/enums/species";
|
import {Species} from "#app/data/enums/species";
|
||||||
import {PlayerGender} from "#app/data/enums/player-gender";
|
import {PlayerGender} from "#app/data/enums/player-gender";
|
||||||
|
@ -23,6 +24,11 @@ import {GameDataType} from "#app/data/enums/game-data-type";
|
||||||
import InputsHandler from "#app/test/utils/inputsHandler";
|
import InputsHandler from "#app/test/utils/inputsHandler";
|
||||||
import {ExpNotification} from "#app/enums/exp-notification";
|
import {ExpNotification} from "#app/enums/exp-notification";
|
||||||
import ErrorInterceptor from "#app/test/utils/errorInterceptor";
|
import ErrorInterceptor from "#app/test/utils/errorInterceptor";
|
||||||
|
import {EnemyPokemon, PlayerPokemon} from "#app/field/pokemon";
|
||||||
|
import {MockClock} from "#app/test/utils/mocks/mockClock";
|
||||||
|
import {Command} from "#app/ui/command-ui-handler";
|
||||||
|
import ModifierSelectUiHandler from "#app/ui/modifier-select-ui-handler";
|
||||||
|
import {Button} from "#app/enums/buttons";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage the game state and transitions between phases.
|
* Class to manage the game state and transitions between phases.
|
||||||
|
@ -84,8 +90,8 @@ export default class GameManager {
|
||||||
* @param callback - The callback to execute.
|
* @param callback - The callback to execute.
|
||||||
* @param expireFn - Optional function to determine if the prompt has expired.
|
* @param expireFn - Optional function to determine if the prompt has expired.
|
||||||
*/
|
*/
|
||||||
onNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn?: () => void) {
|
onNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn?: () => void, awaitingActionInput: boolean = false) {
|
||||||
this.phaseInterceptor.addToNextPrompt(phaseTarget, mode, callback, expireFn);
|
this.phaseInterceptor.addToNextPrompt(phaseTarget, mode, callback, expireFn, awaitingActionInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -142,17 +148,68 @@ export default class GameManager {
|
||||||
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
|
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
|
||||||
this.setMode(Mode.MESSAGE);
|
this.setMode(Mode.MESSAGE);
|
||||||
this.endPhase();
|
this.endPhase();
|
||||||
}, () => this.isCurrentPhase(CommandPhase));
|
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(TurnInitPhase));
|
||||||
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
|
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
|
||||||
this.setMode(Mode.MESSAGE);
|
this.setMode(Mode.MESSAGE);
|
||||||
this.endPhase();
|
this.endPhase();
|
||||||
}, () => this.isCurrentPhase(CommandPhase));
|
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(TurnInitPhase));
|
||||||
await this.phaseInterceptor.runFrom(PostSummonPhase).to(CommandPhase).catch((e) => reject(e));
|
await this.phaseInterceptor.to(CommandPhase).catch((e) => reject(e));
|
||||||
console.log("==================[New Turn]==================");
|
console.log("==================[New Turn]==================");
|
||||||
return resolve();
|
return resolve();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
doAttack(moveIndex: integer): Promise<void> {
|
||||||
|
this.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
|
||||||
|
this.scene.ui.setMode(Mode.FIGHT, (this.scene.getCurrentPhase() as CommandPhase).getFieldIndex());
|
||||||
|
});
|
||||||
|
this.onNextPrompt("CommandPhase", Mode.FIGHT, () => {
|
||||||
|
(this.scene.getCurrentPhase() as CommandPhase).handleCommand(Command.FIGHT, moveIndex, false);
|
||||||
|
});
|
||||||
|
return this.phaseInterceptor.to(DamagePhase);
|
||||||
|
}
|
||||||
|
|
||||||
|
doKillOpponents() {
|
||||||
|
return new Promise<void>(async(resolve, reject) => {
|
||||||
|
await this.killPokemon(this.scene.currentBattle.enemyParty[0]).catch((e) => reject(e));
|
||||||
|
if (this.scene.currentBattle.double) {
|
||||||
|
await this.killPokemon(this.scene.currentBattle.enemyParty[1]).catch((e) => reject(e));
|
||||||
|
}
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toNextTurn(): Promise<void> {
|
||||||
|
return new Promise<void>(async(resolve, reject) => {
|
||||||
|
await this.phaseInterceptor.to(CommandPhase).catch((e) => reject(e));
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
toNextWave(): Promise<void> {
|
||||||
|
return new Promise<void>(async(resolve, reject) => {
|
||||||
|
this.onNextPrompt("SelectModifierPhase", Mode.MODIFIER_SELECT, () => {
|
||||||
|
const handler = this.scene.ui.getHandler() as ModifierSelectUiHandler;
|
||||||
|
handler.processInput(Button.CANCEL);
|
||||||
|
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(NewBattlePhase), true);
|
||||||
|
this.onNextPrompt("SelectModifierPhase", Mode.CONFIRM, () => {
|
||||||
|
const handler = this.scene.ui.getHandler() as ModifierSelectUiHandler;
|
||||||
|
handler.processInput(Button.ACTION);
|
||||||
|
}, () => this.isCurrentPhase(CommandPhase) || this.isCurrentPhase(NewBattlePhase));
|
||||||
|
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
|
||||||
|
this.setMode(Mode.MESSAGE);
|
||||||
|
this.endPhase();
|
||||||
|
}, () => this.isCurrentPhase(TurnInitPhase));
|
||||||
|
this.onNextPrompt("CheckSwitchPhase", Mode.CONFIRM, () => {
|
||||||
|
this.setMode(Mode.MESSAGE);
|
||||||
|
this.endPhase();
|
||||||
|
}, () => this.isCurrentPhase(TurnInitPhase));
|
||||||
|
await this.phaseInterceptor.to(CommandPhase).catch((e) => reject(e));
|
||||||
|
|
||||||
|
return resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the player has won the battle.
|
* Checks if the player has won the battle.
|
||||||
* @returns True if the player has won, otherwise false.
|
* @returns True if the player has won, otherwise false.
|
||||||
|
@ -213,4 +270,15 @@ export default class GameManager {
|
||||||
}
|
}
|
||||||
return updateUserInfo();
|
return updateUserInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async killPokemon(pokemon: PlayerPokemon | EnemyPokemon) {
|
||||||
|
(this.scene.time as MockClock).overrideDelay = 0.01;
|
||||||
|
return new Promise<void>(async(resolve, reject) => {
|
||||||
|
pokemon.hp = 0;
|
||||||
|
this.scene.pushPhase(new FaintPhase(this.scene, pokemon.getBattlerIndex(), true));
|
||||||
|
await this.phaseInterceptor.to(FaintPhase).catch((e) => reject(e));
|
||||||
|
(this.scene.time as MockClock).overrideDelay = undefined;
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ export default class GameWrapper {
|
||||||
pause: () => null,
|
pause: () => null,
|
||||||
setRate: () => null,
|
setRate: () => null,
|
||||||
add: () => this.scene.sound,
|
add: () => this.scene.sound,
|
||||||
get: () => this.scene.sound,
|
get: () => ({...this.scene.sound, totalDuration: 0}),
|
||||||
getAllPlaying: () => [],
|
getAllPlaying: () => [],
|
||||||
manager: {
|
manager: {
|
||||||
game: this.game,
|
game: this.game,
|
||||||
|
@ -131,6 +131,13 @@ export default class GameWrapper {
|
||||||
key: "",
|
key: "",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.scene.cameras = {
|
||||||
|
main: {
|
||||||
|
setPostPipeline: () => null,
|
||||||
|
removePostPipeline: () => null,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
this.scene.tweens = {
|
this.scene.tweens = {
|
||||||
add: (data) => {
|
add: (data) => {
|
||||||
if (data.onComplete) {
|
if (data.onComplete) {
|
||||||
|
|
|
@ -2,8 +2,10 @@ import Clock = Phaser.Time.Clock;
|
||||||
|
|
||||||
|
|
||||||
export class MockClock extends Clock {
|
export class MockClock extends Clock {
|
||||||
|
public overrideDelay: number;
|
||||||
constructor(scene) {
|
constructor(scene) {
|
||||||
super(scene);
|
super(scene);
|
||||||
|
this.overrideDelay = undefined;
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
/*
|
/*
|
||||||
To simulate frame update
|
To simulate frame update
|
||||||
|
@ -14,4 +16,9 @@ export class MockClock extends Clock {
|
||||||
this.update(this.systems.game.loop.time, 100);
|
this.update(this.systems.game.loop.time, 100);
|
||||||
}, 100);
|
}, 100);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addEvent(config: Phaser.Time.TimerEvent | Phaser.Types.Time.TimerEventConfig): Phaser.Time.TimerEvent {
|
||||||
|
const cfg = { ...config, delay: this.overrideDelay || config.delay};
|
||||||
|
return super.addEvent(cfg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -143,6 +143,7 @@ export default class MockSprite {
|
||||||
|
|
||||||
play() {
|
play() {
|
||||||
// return this.phaserSprite.play();
|
// return this.phaserSprite.play();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
setPipelineData(key, value) {
|
setPipelineData(key, value) {
|
||||||
|
|
|
@ -1,17 +1,43 @@
|
||||||
import {
|
import {
|
||||||
BattleEndPhase,
|
BattleEndPhase,
|
||||||
BerryPhase,
|
BerryPhase,
|
||||||
CheckSwitchPhase, CommandPhase, DamagePhase, EggLapsePhase,
|
CheckSwitchPhase,
|
||||||
EncounterPhase, EnemyCommandPhase, FaintPhase,
|
CommandPhase,
|
||||||
LoginPhase, MessagePhase, MoveEffectPhase, MoveEndPhase, MovePhase, NewBattlePhase, NextEncounterPhase,
|
DamagePhase,
|
||||||
|
EggLapsePhase,
|
||||||
|
EncounterPhase,
|
||||||
|
EnemyCommandPhase,
|
||||||
|
FaintPhase,
|
||||||
|
LoginPhase,
|
||||||
|
MessagePhase,
|
||||||
|
MoveEffectPhase,
|
||||||
|
MoveEndPhase,
|
||||||
|
MovePhase,
|
||||||
|
NewBattlePhase,
|
||||||
|
NextEncounterPhase,
|
||||||
PostSummonPhase,
|
PostSummonPhase,
|
||||||
SelectGenderPhase, SelectModifierPhase,
|
SelectGenderPhase,
|
||||||
SelectStarterPhase, SelectTargetPhase, ShinySparklePhase, ShowAbilityPhase, StatChangePhase, SummonPhase,
|
SelectModifierPhase,
|
||||||
TitlePhase, ToggleDoublePositionPhase, TurnEndPhase, TurnInitPhase, TurnStartPhase, UnavailablePhase, VictoryPhase
|
SelectStarterPhase,
|
||||||
|
SelectTargetPhase,
|
||||||
|
ShinySparklePhase,
|
||||||
|
ShowAbilityPhase,
|
||||||
|
StatChangePhase,
|
||||||
|
SummonPhase,
|
||||||
|
SwitchPhase,
|
||||||
|
SwitchSummonPhase,
|
||||||
|
TitlePhase,
|
||||||
|
ToggleDoublePositionPhase,
|
||||||
|
TurnEndPhase,
|
||||||
|
TurnInitPhase,
|
||||||
|
TurnStartPhase,
|
||||||
|
UnavailablePhase,
|
||||||
|
VictoryPhase
|
||||||
} from "#app/phases";
|
} from "#app/phases";
|
||||||
import UI, {Mode} from "#app/ui/ui";
|
import UI, {Mode} from "#app/ui/ui";
|
||||||
import {Phase} from "#app/phase";
|
import {Phase} from "#app/phase";
|
||||||
import ErrorInterceptor from "#app/test/utils/errorInterceptor";
|
import ErrorInterceptor from "#app/test/utils/errorInterceptor";
|
||||||
|
import {QuietFormChangePhase} from "#app/form-change-phase";
|
||||||
|
|
||||||
export default class PhaseInterceptor {
|
export default class PhaseInterceptor {
|
||||||
public scene;
|
public scene;
|
||||||
|
@ -63,10 +89,13 @@ export default class PhaseInterceptor {
|
||||||
[ShinySparklePhase, this.startPhase],
|
[ShinySparklePhase, this.startPhase],
|
||||||
[SelectTargetPhase, this.startPhase],
|
[SelectTargetPhase, this.startPhase],
|
||||||
[UnavailablePhase, this.startPhase],
|
[UnavailablePhase, this.startPhase],
|
||||||
|
[QuietFormChangePhase, this.startPhase],
|
||||||
|
[SwitchPhase, this.startPhase],
|
||||||
|
[SwitchSummonPhase, this.startPhase],
|
||||||
];
|
];
|
||||||
|
|
||||||
private endBySetMode = [
|
private endBySetMode = [
|
||||||
TitlePhase, SelectGenderPhase, CommandPhase, SelectModifierPhase
|
TitlePhase, SelectGenderPhase, CommandPhase
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,8 +107,8 @@ export default class PhaseInterceptor {
|
||||||
this.log = [];
|
this.log = [];
|
||||||
this.onHold = [];
|
this.onHold = [];
|
||||||
this.prompts = [];
|
this.prompts = [];
|
||||||
|
this.startPromptHandler();
|
||||||
this.initPhases();
|
this.initPhases();
|
||||||
this.startPromptHander();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
rejectAll(error) {
|
rejectAll(error) {
|
||||||
|
@ -109,8 +138,10 @@ export default class PhaseInterceptor {
|
||||||
async to(phaseTo, runTarget: boolean = true): Promise<void> {
|
async to(phaseTo, runTarget: boolean = true): Promise<void> {
|
||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
ErrorInterceptor.getInstance().add(this);
|
ErrorInterceptor.getInstance().add(this);
|
||||||
await this.run(this.phaseFrom).catch((e) => reject(e));
|
if (this.phaseFrom) {
|
||||||
this.phaseFrom = null;
|
await this.run(this.phaseFrom).catch((e) => reject(e));
|
||||||
|
this.phaseFrom = null;
|
||||||
|
}
|
||||||
const targetName = typeof phaseTo === "string" ? phaseTo : phaseTo.name;
|
const targetName = typeof phaseTo === "string" ? phaseTo : phaseTo.name;
|
||||||
this.intervalRun = setInterval(async() => {
|
this.intervalRun = setInterval(async() => {
|
||||||
const currentPhase = this.onHold?.length && this.onHold[0];
|
const currentPhase = this.onHold?.length && this.onHold[0];
|
||||||
|
@ -238,7 +269,6 @@ export default class PhaseInterceptor {
|
||||||
*/
|
*/
|
||||||
superEndPhase() {
|
superEndPhase() {
|
||||||
const instance = this.scene.getCurrentPhase();
|
const instance = this.scene.getCurrentPhase();
|
||||||
console.log(`%c INTERCEPTED Super End Phase ${instance.constructor.name}`, "color:red;");
|
|
||||||
this.originalSuperEnd.apply(instance);
|
this.originalSuperEnd.apply(instance);
|
||||||
this.inProgress?.callback();
|
this.inProgress?.callback();
|
||||||
this.inProgress = undefined;
|
this.inProgress = undefined;
|
||||||
|
@ -253,6 +283,9 @@ export default class PhaseInterceptor {
|
||||||
const instance = this.scene.ui;
|
const instance = this.scene.ui;
|
||||||
console.log("setMode", mode, args);
|
console.log("setMode", mode, args);
|
||||||
const ret = this.originalSetMode.apply(instance, [mode, ...args]);
|
const ret = this.originalSetMode.apply(instance, [mode, ...args]);
|
||||||
|
if (!this.phases[currentPhase.constructor.name]) {
|
||||||
|
throw new Error(`missing ${currentPhase.constructor.name} in phaseInterceptior PHASES list`);
|
||||||
|
}
|
||||||
if (this.phases[currentPhase.constructor.name].endBySetMode) {
|
if (this.phases[currentPhase.constructor.name].endBySetMode) {
|
||||||
this.inProgress?.callback();
|
this.inProgress?.callback();
|
||||||
this.inProgress = undefined;
|
this.inProgress = undefined;
|
||||||
|
@ -263,16 +296,17 @@ export default class PhaseInterceptor {
|
||||||
/**
|
/**
|
||||||
* Method to start the prompt handler.
|
* Method to start the prompt handler.
|
||||||
*/
|
*/
|
||||||
startPromptHander() {
|
startPromptHandler() {
|
||||||
this.promptInterval = setInterval(() => {
|
this.promptInterval = setInterval(() => {
|
||||||
if (this.prompts.length) {
|
if (this.prompts.length) {
|
||||||
const actionForNextPrompt = this.prompts[0];
|
const actionForNextPrompt = this.prompts[0];
|
||||||
const expireFn = actionForNextPrompt.expireFn && actionForNextPrompt.expireFn();
|
const expireFn = actionForNextPrompt.expireFn && actionForNextPrompt.expireFn();
|
||||||
const currentMode = this.scene.ui.getMode();
|
const currentMode = this.scene.ui.getMode();
|
||||||
const currentPhase = this.scene.getCurrentPhase().constructor.name;
|
const currentPhase = this.scene.getCurrentPhase().constructor.name;
|
||||||
|
const currentHandler = this.scene.ui.getHandler();
|
||||||
if (expireFn) {
|
if (expireFn) {
|
||||||
this.prompts.shift();
|
this.prompts.shift();
|
||||||
} else if (currentMode === actionForNextPrompt.mode && currentPhase === actionForNextPrompt.phaseTarget) {
|
} else if (currentMode === actionForNextPrompt.mode && currentPhase === actionForNextPrompt.phaseTarget && currentHandler.active && (!actionForNextPrompt.awaitingActionInput || (actionForNextPrompt.awaitingActionInput && currentHandler.awaitingActionInput))) {
|
||||||
this.prompts.shift().callback();
|
this.prompts.shift().callback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,12 +320,13 @@ export default class PhaseInterceptor {
|
||||||
* @param callback - The callback function to execute.
|
* @param callback - The callback function to execute.
|
||||||
* @param expireFn - The function to determine if the prompt has expired.
|
* @param expireFn - The function to determine if the prompt has expired.
|
||||||
*/
|
*/
|
||||||
addToNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn: () => void) {
|
addToNextPrompt(phaseTarget: string, mode: Mode, callback: () => void, expireFn: () => void, awaitingActionInput: boolean = false) {
|
||||||
this.prompts.push({
|
this.prompts.push({
|
||||||
phaseTarget,
|
phaseTarget,
|
||||||
mode,
|
mode,
|
||||||
callback,
|
callback,
|
||||||
expireFn
|
expireFn,
|
||||||
|
awaitingActionInput
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue