[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 const clientSessionId = Utils.randomString(32);
|
||||
|
||||
export function initLoggedInUser(): void {
|
||||
loggedInUser = { username: "Guest", lastSessionSlot: -1 };
|
||||
}
|
||||
|
||||
export function updateUserInfo(): Promise<[boolean, integer]> {
|
||||
return new Promise<[boolean, integer]>(resolve => {
|
||||
if (bypassLogin) {
|
||||
|
|
|
@ -1922,6 +1922,8 @@ export default class BattleScene extends SceneBase {
|
|||
}
|
||||
if (!this.phaseQueue.length) {
|
||||
this.populatePhaseQueue();
|
||||
// clear the conditionalQueue if there are no phases left in the phaseQueue
|
||||
this.conditionalQueue = [];
|
||||
}
|
||||
this.currentPhase = this.phaseQueue.shift();
|
||||
|
||||
|
|
|
@ -1033,13 +1033,19 @@ export class EncounterPhase extends BattlePhase {
|
|||
|
||||
if (this.scene.currentBattle.battleType !== BattleType.TRAINER) {
|
||||
enemyField.map(p => this.scene.pushConditionalPhase(new PostSummonPhase(this.scene, p.getBattlerIndex()), () => {
|
||||
// is the player party initialized ?
|
||||
const a = !!this.scene.getParty()?.length;
|
||||
// if there is not a player party, we can't continue
|
||||
if (!this.scene.getParty()?.length) {
|
||||
return false;
|
||||
}
|
||||
// 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
|
||||
const b = this.scene.currentBattle.double ? amountOnTheField === 2 : amountOnTheField === 1;
|
||||
return a && b;
|
||||
if (this.scene.currentBattle.double) {
|
||||
return pokemonsOnFieldCount === requiredPokemonsOnField;
|
||||
}
|
||||
return pokemonsOnFieldCount === 1;
|
||||
}));
|
||||
const ivScannerModifier = this.scene.findModifier(m => m instanceof IvScannerModifier);
|
||||
if (ivScannerModifier) {
|
||||
|
|
|
@ -5,15 +5,17 @@ import * as overrides from "#app/overrides";
|
|||
import {Abilities} from "#app/data/enums/abilities";
|
||||
import {Species} from "#app/data/enums/species";
|
||||
import {
|
||||
CommandPhase, DamagePhase,
|
||||
EnemyCommandPhase,
|
||||
CommandPhase, DamagePhase, EncounterPhase,
|
||||
EnemyCommandPhase, SelectStarterPhase,
|
||||
TurnInitPhase,
|
||||
} from "#app/phases";
|
||||
import {Mode} from "#app/ui/ui";
|
||||
import {BattleStat} from "#app/data/battle-stat";
|
||||
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 {Status, StatusEffect} from "#app/data/status-effect";
|
||||
import {GameModes, getGameMode} from "#app/game-mode";
|
||||
|
||||
|
||||
describe("Abilities - Intimidate", () => {
|
||||
|
@ -337,5 +339,53 @@ describe("Abilities - Intimidate", () => {
|
|||
expect(battleStatsPokemon[BattleStat.ATK]).toBe(-1);
|
||||
battleStatsOpponent = game.scene.currentBattle.enemyParty[0].summonData.battleStats;
|
||||
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", () => {
|
||||
it("should start the login phase", async () => {
|
||||
const loginPhase = new LoginPhase(scene);
|
||||
scene.pushPhase(loginPhase);
|
||||
scene.unshiftPhase(loginPhase);
|
||||
await game.phaseInterceptor.run(LoginPhase);
|
||||
expect(scene.ui.getMode()).to.equal(Mode.MESSAGE);
|
||||
});
|
||||
|
@ -37,7 +37,7 @@ describe("Phases", () => {
|
|||
describe("TitlePhase", () => {
|
||||
it("should start the title phase", async () => {
|
||||
const titlePhase = new TitlePhase(scene);
|
||||
scene.pushPhase(titlePhase);
|
||||
scene.unshiftPhase(titlePhase);
|
||||
await game.phaseInterceptor.run(TitlePhase);
|
||||
expect(scene.ui.getMode()).to.equal(Mode.TITLE);
|
||||
});
|
||||
|
@ -46,7 +46,7 @@ describe("Phases", () => {
|
|||
describe("UnavailablePhase", () => {
|
||||
it("should start the unavailable phase", async () => {
|
||||
const unavailablePhase = new UnavailablePhase(scene);
|
||||
scene.pushPhase(unavailablePhase);
|
||||
scene.unshiftPhase(unavailablePhase);
|
||||
await game.phaseInterceptor.run(UnavailablePhase);
|
||||
expect(scene.ui.getMode()).to.equal(Mode.UNAVAILABLE);
|
||||
}, 20000);
|
||||
|
|
|
@ -6,7 +6,6 @@ import {
|
|||
EncounterPhase,
|
||||
FaintPhase,
|
||||
LoginPhase, NewBattlePhase,
|
||||
SelectGenderPhase,
|
||||
SelectStarterPhase,
|
||||
TitlePhase, TurnInitPhase,
|
||||
} from "#app/phases";
|
||||
|
@ -100,14 +99,8 @@ export default class GameManager {
|
|||
* @returns A promise that resolves when the title phase is reached.
|
||||
*/
|
||||
async runToTitle(): Promise<void> {
|
||||
await this.phaseInterceptor.run(LoginPhase);
|
||||
|
||||
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.whenAboutToRun(LoginPhase);
|
||||
this.phaseInterceptor.pop();
|
||||
await this.phaseInterceptor.run(TitlePhase);
|
||||
|
||||
this.scene.gameSpeed = 5;
|
||||
|
@ -116,6 +109,9 @@ export default class GameManager {
|
|||
this.scene.expGainsSpeed = 3;
|
||||
this.scene.expParty = ExpNotification.SKIP;
|
||||
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) => {
|
||||
ErrorInterceptor.getInstance().add(this);
|
||||
const interval = setInterval(async () => {
|
||||
const currentPhase = this.onHold.shift();
|
||||
if (currentPhase) {
|
||||
if (currentPhase.name !== targetName) {
|
||||
this.onHold.unshift(currentPhase);
|
||||
} else {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
const currentPhase = this.onHold[0];
|
||||
if (currentPhase?.name === targetName) {
|
||||
clearInterval(interval);
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
pop() {
|
||||
this.onHold.pop();
|
||||
this.scene.shiftPhase();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {initAchievements} from "#app/system/achv.js";
|
||||
import { initVouchers } from "#app/system/voucher.js";
|
||||
import {initLoggedInUser} from "#app/account";
|
||||
|
||||
initVouchers();
|
||||
initAchievements();
|
||||
|
@ -21,5 +22,6 @@ initPokemonForms();
|
|||
initSpecies();
|
||||
initMoves();
|
||||
initAbilities();
|
||||
initLoggedInUser();
|
||||
|
||||
global.testFailed = false;
|
||||
|
|
Loading…
Reference in New Issue