mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-04-02 16:08:48 +01:00
[Bug] Fix PostSummonPhase Logic to Support Single Pokémon Teams (#2153)
* added test for spikes + forceOpponentToSwitch * fix conditional for intimidate in a double if there is only 1 pokemon available on our side * fix variable naming and ternary condition * added a fallback to clear the conditionalQueue if it's a new turn * speed up tests by skipping LoginPhase
This commit is contained in:
parent
0970c2cd4e
commit
c908153761
@ -9,6 +9,10 @@ export interface UserInfo {
|
|||||||
export let loggedInUser: UserInfo = null;
|
export let loggedInUser: UserInfo = null;
|
||||||
export const clientSessionId = Utils.randomString(32);
|
export const clientSessionId = Utils.randomString(32);
|
||||||
|
|
||||||
|
export function initLoggedInUser(): void {
|
||||||
|
loggedInUser = { username: "Guest", lastSessionSlot: -1 };
|
||||||
|
}
|
||||||
|
|
||||||
export function updateUserInfo(): Promise<[boolean, integer]> {
|
export function updateUserInfo(): Promise<[boolean, integer]> {
|
||||||
return new Promise<[boolean, integer]>(resolve => {
|
return new Promise<[boolean, integer]>(resolve => {
|
||||||
if (bypassLogin) {
|
if (bypassLogin) {
|
||||||
|
@ -1922,6 +1922,8 @@ export default class BattleScene extends SceneBase {
|
|||||||
}
|
}
|
||||||
if (!this.phaseQueue.length) {
|
if (!this.phaseQueue.length) {
|
||||||
this.populatePhaseQueue();
|
this.populatePhaseQueue();
|
||||||
|
// clear the conditionalQueue if there are no phases left in the phaseQueue
|
||||||
|
this.conditionalQueue = [];
|
||||||
}
|
}
|
||||||
this.currentPhase = this.phaseQueue.shift();
|
this.currentPhase = this.phaseQueue.shift();
|
||||||
|
|
||||||
|
@ -1033,13 +1033,19 @@ export class EncounterPhase extends BattlePhase {
|
|||||||
|
|
||||||
if (this.scene.currentBattle.battleType !== BattleType.TRAINER) {
|
if (this.scene.currentBattle.battleType !== BattleType.TRAINER) {
|
||||||
enemyField.map(p => this.scene.pushConditionalPhase(new PostSummonPhase(this.scene, p.getBattlerIndex()), () => {
|
enemyField.map(p => this.scene.pushConditionalPhase(new PostSummonPhase(this.scene, p.getBattlerIndex()), () => {
|
||||||
// is the player party initialized ?
|
// if there is not a player party, we can't continue
|
||||||
const a = !!this.scene.getParty()?.length;
|
if (!this.scene.getParty()?.length) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// how many player pokemon are on the field ?
|
// how many player pokemon are on the field ?
|
||||||
const amountOnTheField = this.scene.getParty().filter(p => p.isOnField()).length;
|
const pokemonsOnFieldCount = this.scene.getParty().filter(p => p.isOnField()).length;
|
||||||
|
// if it's a 2vs1, there will never be a 2nd pokemon on our field even
|
||||||
|
const requiredPokemonsOnField = Math.min(this.scene.getParty().filter((p) => !p.isFainted()).length, 2);
|
||||||
// if it's a double, there should be 2, otherwise 1
|
// if it's a double, there should be 2, otherwise 1
|
||||||
const b = this.scene.currentBattle.double ? amountOnTheField === 2 : amountOnTheField === 1;
|
if (this.scene.currentBattle.double) {
|
||||||
return a && b;
|
return pokemonsOnFieldCount === requiredPokemonsOnField;
|
||||||
|
}
|
||||||
|
return pokemonsOnFieldCount === 1;
|
||||||
}));
|
}));
|
||||||
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
|
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
|
||||||
if (ivScannerModifier) {
|
if (ivScannerModifier) {
|
||||||
|
@ -5,15 +5,17 @@ import * as overrides from "#app/overrides";
|
|||||||
import {Abilities} from "#app/data/enums/abilities";
|
import {Abilities} from "#app/data/enums/abilities";
|
||||||
import {Species} from "#app/data/enums/species";
|
import {Species} from "#app/data/enums/species";
|
||||||
import {
|
import {
|
||||||
CommandPhase, DamagePhase,
|
CommandPhase, DamagePhase, EncounterPhase,
|
||||||
EnemyCommandPhase,
|
EnemyCommandPhase, SelectStarterPhase,
|
||||||
TurnInitPhase,
|
TurnInitPhase,
|
||||||
} from "#app/phases";
|
} from "#app/phases";
|
||||||
import {Mode} from "#app/ui/ui";
|
import {Mode} from "#app/ui/ui";
|
||||||
import {BattleStat} from "#app/data/battle-stat";
|
import {BattleStat} from "#app/data/battle-stat";
|
||||||
import {Moves} from "#app/data/enums/moves";
|
import {Moves} from "#app/data/enums/moves";
|
||||||
import {getMovePosition} from "#app/test/utils/gameManagerUtils";
|
import {generateStarter, getMovePosition} from "#app/test/utils/gameManagerUtils";
|
||||||
import {Command} from "#app/ui/command-ui-handler";
|
import {Command} from "#app/ui/command-ui-handler";
|
||||||
|
import {Status, StatusEffect} from "#app/data/status-effect";
|
||||||
|
import {GameModes, getGameMode} from "#app/game-mode";
|
||||||
|
|
||||||
|
|
||||||
describe("Abilities - Intimidate", () => {
|
describe("Abilities - Intimidate", () => {
|
||||||
@ -337,5 +339,53 @@ describe("Abilities - Intimidate", () => {
|
|||||||
expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1);
|
expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1);
|
||||||
battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats;
|
battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats;
|
||||||
expect(battleStatsOpponent[BattleStat.ATK]).toBe(-1);
|
expect(battleStatsOpponent[BattleStat.ATK]).toBe(-1);
|
||||||
}, 200000);
|
}, 20000);
|
||||||
|
|
||||||
|
it("double - wild vs only 1 on player side", async() => {
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false);
|
||||||
|
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
||||||
|
await game.runToSummon([
|
||||||
|
Species.MIGHTYENA,
|
||||||
|
]);
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, false);
|
||||||
|
const battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats;
|
||||||
|
expect(battleStatsOpponent[BattleStat.ATK]).toBe(-1);
|
||||||
|
const battleStatsOpponent2 = game.scene.currentBattle.enemyParty[1].summonData.battleStats;
|
||||||
|
expect(battleStatsOpponent2[BattleStat.ATK]).toBe(-1);
|
||||||
|
|
||||||
|
const battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats;
|
||||||
|
expect(battleStatsPokemon[BattleStat.ATK]).toBe(-2);
|
||||||
|
}, 20000);
|
||||||
|
|
||||||
|
it("double - wild vs only 1 alive on player side", async() => {
|
||||||
|
vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(false);
|
||||||
|
vi.spyOn(overrides, "DOUBLE_BATTLE_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
vi.spyOn(overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(3);
|
||||||
|
await game.runToTitle();
|
||||||
|
|
||||||
|
game.onNextPrompt("TitlePhase", Mode.TITLE, () => {
|
||||||
|
game.scene.gameMode = getGameMode(GameModes.CLASSIC);
|
||||||
|
const starters = generateStarter(game.scene, [
|
||||||
|
Species.MIGHTYENA,
|
||||||
|
Species.POOCHYENA,
|
||||||
|
]);
|
||||||
|
const selectStarterPhase = new SelectStarterPhase(game.scene);
|
||||||
|
game.scene.pushPhase(new EncounterPhase(game.scene, false));
|
||||||
|
selectStarterPhase.initBattle(starters);
|
||||||
|
game.scene.getParty()[1].hp = 0;
|
||||||
|
game.scene.getParty()[1].status = new Status(StatusEffect.FAINT);
|
||||||
|
});
|
||||||
|
|
||||||
|
await game.phaseInterceptor.run(EncounterPhase);
|
||||||
|
|
||||||
|
await game.phaseInterceptor.to(CommandPhase, false);
|
||||||
|
const battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats;
|
||||||
|
expect(battleStatsOpponent[BattleStat.ATK]).toBe(-1);
|
||||||
|
const battleStatsOpponent2 = game.scene.currentBattle.enemyParty[1].summonData.battleStats;
|
||||||
|
expect(battleStatsOpponent2[BattleStat.ATK]).toBe(-1);
|
||||||
|
|
||||||
|
const battleStatsPokemon = game.scene.getParty()[0].summonData.battleStats;
|
||||||
|
expect(battleStatsPokemon[BattleStat.ATK]).toBe(-2);
|
||||||
|
}, 20000);
|
||||||
});
|
});
|
||||||
|
@ -28,7 +28,7 @@ describe("Phases", () => {
|
|||||||
describe("LoginPhase", () => {
|
describe("LoginPhase", () => {
|
||||||
it("should start the login phase", async () => {
|
it("should start the login phase", async () => {
|
||||||
const loginPhase = new LoginPhase(scene);
|
const loginPhase = new LoginPhase(scene);
|
||||||
scene.pushPhase(loginPhase);
|
scene.unshiftPhase(loginPhase);
|
||||||
await game.phaseInterceptor.run(LoginPhase);
|
await game.phaseInterceptor.run(LoginPhase);
|
||||||
expect(scene.ui.getMode()).to.equal(Mode.MESSAGE);
|
expect(scene.ui.getMode()).to.equal(Mode.MESSAGE);
|
||||||
});
|
});
|
||||||
@ -37,7 +37,7 @@ describe("Phases", () => {
|
|||||||
describe("TitlePhase", () => {
|
describe("TitlePhase", () => {
|
||||||
it("should start the title phase", async () => {
|
it("should start the title phase", async () => {
|
||||||
const titlePhase = new TitlePhase(scene);
|
const titlePhase = new TitlePhase(scene);
|
||||||
scene.pushPhase(titlePhase);
|
scene.unshiftPhase(titlePhase);
|
||||||
await game.phaseInterceptor.run(TitlePhase);
|
await game.phaseInterceptor.run(TitlePhase);
|
||||||
expect(scene.ui.getMode()).to.equal(Mode.TITLE);
|
expect(scene.ui.getMode()).to.equal(Mode.TITLE);
|
||||||
});
|
});
|
||||||
@ -46,7 +46,7 @@ describe("Phases", () => {
|
|||||||
describe("UnavailablePhase", () => {
|
describe("UnavailablePhase", () => {
|
||||||
it("should start the unavailable phase", async () => {
|
it("should start the unavailable phase", async () => {
|
||||||
const unavailablePhase = new UnavailablePhase(scene);
|
const unavailablePhase = new UnavailablePhase(scene);
|
||||||
scene.pushPhase(unavailablePhase);
|
scene.unshiftPhase(unavailablePhase);
|
||||||
await game.phaseInterceptor.run(UnavailablePhase);
|
await game.phaseInterceptor.run(UnavailablePhase);
|
||||||
expect(scene.ui.getMode()).to.equal(Mode.UNAVAILABLE);
|
expect(scene.ui.getMode()).to.equal(Mode.UNAVAILABLE);
|
||||||
}, 20000);
|
}, 20000);
|
||||||
|
@ -6,7 +6,6 @@ import {
|
|||||||
EncounterPhase,
|
EncounterPhase,
|
||||||
FaintPhase,
|
FaintPhase,
|
||||||
LoginPhase, NewBattlePhase,
|
LoginPhase, NewBattlePhase,
|
||||||
SelectGenderPhase,
|
|
||||||
SelectStarterPhase,
|
SelectStarterPhase,
|
||||||
TitlePhase, TurnInitPhase,
|
TitlePhase, TurnInitPhase,
|
||||||
} from "#app/phases";
|
} from "#app/phases";
|
||||||
@ -100,14 +99,8 @@ export default class GameManager {
|
|||||||
* @returns A promise that resolves when the title phase is reached.
|
* @returns A promise that resolves when the title phase is reached.
|
||||||
*/
|
*/
|
||||||
async runToTitle(): Promise<void> {
|
async runToTitle(): Promise<void> {
|
||||||
await this.phaseInterceptor.run(LoginPhase);
|
await this.phaseInterceptor.whenAboutToRun(LoginPhase);
|
||||||
|
this.phaseInterceptor.pop();
|
||||||
this.onNextPrompt("SelectGenderPhase", Mode.OPTION_SELECT, () => {
|
|
||||||
this.scene.gameData.gender = PlayerGender.MALE;
|
|
||||||
this.endPhase();
|
|
||||||
}, () => this.isCurrentPhase(TitlePhase));
|
|
||||||
|
|
||||||
await this.phaseInterceptor.run(SelectGenderPhase, () => this.isCurrentPhase(TitlePhase));
|
|
||||||
await this.phaseInterceptor.run(TitlePhase);
|
await this.phaseInterceptor.run(TitlePhase);
|
||||||
|
|
||||||
this.scene.gameSpeed = 5;
|
this.scene.gameSpeed = 5;
|
||||||
@ -116,6 +109,9 @@ export default class GameManager {
|
|||||||
this.scene.expGainsSpeed = 3;
|
this.scene.expGainsSpeed = 3;
|
||||||
this.scene.expParty = ExpNotification.SKIP;
|
this.scene.expParty = ExpNotification.SKIP;
|
||||||
this.scene.hpBarSpeed = 3;
|
this.scene.hpBarSpeed = 3;
|
||||||
|
this.scene.enableTutorials = false;
|
||||||
|
this.scene.gameData.gender = PlayerGender.MALE;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -212,19 +212,20 @@ export default class PhaseInterceptor {
|
|||||||
return new Promise(async (resolve, reject) => {
|
return new Promise(async (resolve, reject) => {
|
||||||
ErrorInterceptor.getInstance().add(this);
|
ErrorInterceptor.getInstance().add(this);
|
||||||
const interval = setInterval(async () => {
|
const interval = setInterval(async () => {
|
||||||
const currentPhase = this.onHold.shift();
|
const currentPhase = this.onHold[0];
|
||||||
if (currentPhase) {
|
if (currentPhase?.name === targetName) {
|
||||||
if (currentPhase.name !== targetName) {
|
clearInterval(interval);
|
||||||
this.onHold.unshift(currentPhase);
|
resolve();
|
||||||
} else {
|
|
||||||
clearInterval(interval);
|
|
||||||
resolve();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pop() {
|
||||||
|
this.onHold.pop();
|
||||||
|
this.scene.shiftPhase();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Method to initialize phases and their corresponding methods.
|
* Method to initialize phases and their corresponding methods.
|
||||||
*/
|
*/
|
||||||
|
@ -10,6 +10,7 @@ import {initMoves} from "#app/data/move";
|
|||||||
import {initAbilities} from "#app/data/ability";
|
import {initAbilities} from "#app/data/ability";
|
||||||
import {initAchievements} from "#app/system/achv.js";
|
import {initAchievements} from "#app/system/achv.js";
|
||||||
import { initVouchers } from "#app/system/voucher.js";
|
import { initVouchers } from "#app/system/voucher.js";
|
||||||
|
import {initLoggedInUser} from "#app/account";
|
||||||
|
|
||||||
initVouchers();
|
initVouchers();
|
||||||
initAchievements();
|
initAchievements();
|
||||||
@ -21,5 +22,6 @@ initPokemonForms();
|
|||||||
initSpecies();
|
initSpecies();
|
||||||
initMoves();
|
initMoves();
|
||||||
initAbilities();
|
initAbilities();
|
||||||
|
initLoggedInUser();
|
||||||
|
|
||||||
global.testFailed = false;
|
global.testFailed = false;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user