mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-05 07:52:17 +02:00
Hopefully fixed extraneous reset calls and call timing
This commit is contained in:
parent
5532432085
commit
a42b7ed9f7
@ -86,7 +86,7 @@ export function ForceSwitch<TBase extends SubMoveOrAbAttr>(Base: TBase) {
|
||||
|
||||
/**
|
||||
* Wrapper function to handle the actual "switching out" of Pokemon.
|
||||
* @param switchOutTarget - The {@linkcode Pokemon} (player or enemy) attempting to switch out.
|
||||
* @param switchOutTarget - The {@linkcode Pokemon} (player or enemy) to be switched switch out.
|
||||
*/
|
||||
protected doSwitch(switchOutTarget: Pokemon): void {
|
||||
if (switchOutTarget instanceof PlayerPokemon) {
|
||||
|
@ -7771,8 +7771,9 @@ const targetSleptOrComatoseCondition: MoveConditionFunc = (user: Pokemon, target
|
||||
const failIfLastCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => globalScene.phaseQueue.find(phase => phase instanceof MovePhase) !== undefined;
|
||||
|
||||
const failIfLastInPartyCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => {
|
||||
const party: Pokemon[] = user.isPlayer() ? globalScene.getPlayerParty() : globalScene.getEnemyParty();
|
||||
return party.some(pokemon => pokemon.isActive() && !pokemon.isOnField());
|
||||
const player = user.isPlayer();
|
||||
const otherPartyIndices = globalScene.getBackupPartyMemberIndices(player, !player ? (user as EnemyPokemon).trainerSlot : undefined)
|
||||
return otherPartyIndices.length > 0;
|
||||
};
|
||||
|
||||
const failIfGhostTypeCondition: MoveConditionFunc = (user: Pokemon, target: Pokemon, move: Move) => !target.isOfType(PokemonType.GHOST);
|
||||
|
@ -5034,6 +5034,7 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
}
|
||||
|
||||
for (const tag of source.summonData.tags) {
|
||||
// Skip non-Baton Passable tags (or telekinesis for mega gengar; cf. https://bulbapedia.bulbagarden.net/wiki/Telekinesis_(move))
|
||||
if (
|
||||
!tag.isBatonPassable ||
|
||||
(tag.tagType === BattlerTagType.TELEKINESIS &&
|
||||
@ -6314,20 +6315,20 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
|
||||
* @param destroy - Whether to destroy this Pokemon once it leaves the field; default `false`
|
||||
* @remarks
|
||||
* This **SHOULD NOT** be called when a `SummonPhase` or `SwitchSummonPhase` is already being added,
|
||||
* which can lead to premature resetting of {@klinkcode turnData} and {@linkcode summonData}.
|
||||
* which can lead to premature resetting of {@linkcode turnData} and {@linkcode summonData}.
|
||||
*/
|
||||
leaveField(clearEffects = true, hideInfo = true, destroy = false) {
|
||||
console.log(`leaveField called on Pokemon ${this.name}`)
|
||||
this.resetSprite();
|
||||
this.resetTurnData();
|
||||
globalScene
|
||||
.getField(true)
|
||||
.filter(p => p !== this)
|
||||
.getField(true)
|
||||
.filter(p => p !== this)
|
||||
.forEach(p => p.removeTagsBySourceId(this.id));
|
||||
|
||||
if (clearEffects) {
|
||||
this.destroySubstitute();
|
||||
this.resetSummonData();
|
||||
this.resetTurnData();
|
||||
}
|
||||
if (hideInfo) {
|
||||
this.hideInfo();
|
||||
|
@ -61,8 +61,7 @@ export class FaintPhase extends PokemonPhase {
|
||||
faintPokemon.getTag(BattlerTagType.GRUDGE)?.lapse(faintPokemon, BattlerTagLapseType.CUSTOM, this.source);
|
||||
}
|
||||
|
||||
faintPokemon.resetSummonData();
|
||||
|
||||
// Check for reviver seed
|
||||
if (!this.preventInstantRevive) {
|
||||
const instantReviveModifier = globalScene.applyModifier(
|
||||
PokemonInstantReviveModifier,
|
||||
@ -71,6 +70,7 @@ export class FaintPhase extends PokemonPhase {
|
||||
) as PokemonInstantReviveModifier;
|
||||
|
||||
if (instantReviveModifier) {
|
||||
faintPokemon.resetSummonData();
|
||||
faintPokemon.loseHeldItem(instantReviveModifier);
|
||||
globalScene.updateModifiers(this.player);
|
||||
return this.end();
|
||||
@ -179,11 +179,11 @@ export class FaintPhase extends PokemonPhase {
|
||||
} else {
|
||||
globalScene.unshiftPhase(new VictoryPhase(this.battlerIndex));
|
||||
if ([BattleType.TRAINER, BattleType.MYSTERY_ENCOUNTER].includes(globalScene.currentBattle.battleType)) {
|
||||
const hasReservePartyMember = !!globalScene
|
||||
.getEnemyParty()
|
||||
.filter(p => p.isActive() && !p.isOnField() && p.trainerSlot === (pokemon as EnemyPokemon).trainerSlot)
|
||||
.length;
|
||||
if (hasReservePartyMember) {
|
||||
const reservePartyIndices = globalScene.getBackupPartyMemberIndices(
|
||||
false,
|
||||
(pokemon as EnemyPokemon).trainerSlot,
|
||||
);
|
||||
if (reservePartyIndices.length) {
|
||||
globalScene.pushPhase(new SwitchSummonPhase(SwitchType.SWITCH, this.fieldIndex, -1, false, false));
|
||||
}
|
||||
}
|
||||
@ -217,6 +217,7 @@ export class FaintPhase extends PokemonPhase {
|
||||
globalScene.addFaintedEnemyScore(pokemon as EnemyPokemon);
|
||||
globalScene.currentBattle.addPostBattleLoot(pokemon as EnemyPokemon);
|
||||
}
|
||||
// TODO: Do we need to leave the field here & now as opposed to during `switchSummonPhase`?
|
||||
pokemon.leaveField();
|
||||
this.end();
|
||||
},
|
||||
|
@ -111,7 +111,6 @@ export class SwitchSummonPhase extends SummonPhase {
|
||||
scale: 0.5,
|
||||
onComplete: () => {
|
||||
globalScene.time.delayedCall(750, () => this.switchAndSummon());
|
||||
lastPokemon.leaveField(this.switchType === SwitchType.SWITCH, false);
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -162,9 +161,12 @@ export class SwitchSummonPhase extends SummonPhase {
|
||||
}
|
||||
}
|
||||
|
||||
// Swap around the 2 pokemon's party positions and play an animation to send in the new pokemon.
|
||||
party[this.slotIndex] = this.lastPokemon;
|
||||
party[this.fieldIndex] = switchedInPokemon;
|
||||
const showTextAndSummon = () => {
|
||||
// TODO: Should this remove the info container?
|
||||
this.lastPokemon.leaveField(![SwitchType.BATON_PASS, SwitchType.SHED_TAIL].includes(this.switchType), false);
|
||||
globalScene.ui.showText(
|
||||
this.player
|
||||
? i18next.t("battle:playerGo", {
|
||||
@ -209,25 +211,30 @@ export class SwitchSummonPhase extends SummonPhase {
|
||||
|
||||
const pokemon = this.getPokemon();
|
||||
|
||||
// If not switching at start of battle, reset turn counts and temp data on the newly sent in Pokemon
|
||||
// Needed as we increment turn counters in `TurnEndPhase`.
|
||||
if (this.switchType !== SwitchType.INITIAL_SWITCH) {
|
||||
// No need to reset turn/summon data for initial switch
|
||||
// (since both get initialized to an empty object on object creation)
|
||||
this.lastPokemon.resetTurnData();
|
||||
this.lastPokemon.resetSummonData();
|
||||
pokemon.tempSummonData.turnCount--;
|
||||
pokemon.tempSummonData.waveTurnCount--;
|
||||
pokemon.turnData.switchedInThisTurn = true;
|
||||
}
|
||||
|
||||
// Baton Pass over any eligible effects or substitutes before resetting the last pokemon's temporary data.
|
||||
if (this.switchType === SwitchType.BATON_PASS) {
|
||||
pokemon.transferSummon(this.lastPokemon);
|
||||
this.lastPokemon.resetTurnData();
|
||||
this.lastPokemon.resetSummonData();
|
||||
} else if (this.switchType === SwitchType.SHED_TAIL) {
|
||||
const subTag = this.lastPokemon.getTag(SubstituteTag);
|
||||
if (subTag) {
|
||||
pokemon.summonData.tags.push(subTag);
|
||||
}
|
||||
}
|
||||
|
||||
// If not switching at start of battle, reset turn counts and temp data.
|
||||
// Needed as we increment turn counters in `TurnEndPhase`.
|
||||
if (this.switchType !== SwitchType.INITIAL_SWITCH) {
|
||||
pokemon.tempSummonData.turnCount--;
|
||||
pokemon.tempSummonData.waveTurnCount--;
|
||||
pokemon.turnData.switchedInThisTurn = true;
|
||||
// No need to reset turn/summon data for initial switch
|
||||
//(since both get initialized to an empty object on object creation)
|
||||
pokemon.resetTurnData();
|
||||
pokemon.resetSummonData();
|
||||
this.lastPokemon.resetTurnData();
|
||||
this.lastPokemon.resetSummonData();
|
||||
}
|
||||
|
||||
globalScene.triggerPokemonFormChange(pokemon, SpeciesFormChangeActiveTrigger, true);
|
||||
|
@ -1,21 +1,157 @@
|
||||
import Trainer from "#app/field/trainer";
|
||||
import { PokemonSummonData, PokemonTurnData } from "#app/field/pokemon";
|
||||
import { Abilities } from "#enums/abilities";
|
||||
import { BattleType } from "#enums/battle-type";
|
||||
import { BattlerTagType } from "#enums/battler-tag-type";
|
||||
import { Moves } from "#enums/moves";
|
||||
import { Species } from "#enums/species";
|
||||
import GameManager from "#test/testUtils/gameManager";
|
||||
import Phaser from "phaser";
|
||||
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
describe.each<{ name: string; selfMove?: Moves; selfAbility?: Abilities; oppMove?: Moves }>([
|
||||
{ name: "Self Switch Attack Moves", selfMove: Moves.U_TURN },
|
||||
{ name: "Target Switch Attack Moves", oppMove: Moves.DRAGON_TAIL },
|
||||
{ name: "Self Switch Status Moves", selfMove: Moves.TELEPORT },
|
||||
{ name: "Target Switch Status Moves", oppMove: Moves.WHIRLWIND },
|
||||
{ name: "Self Switch Abilities", selfAbility: Abilities.EMERGENCY_EXIT },
|
||||
describe("Manual Switching -", () => {
|
||||
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
|
||||
.battleStyle("single")
|
||||
.disableCrits()
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.moveset(Moves.SPLASH)
|
||||
.enemyMoveset(Moves.SPLASH)
|
||||
.battleType(BattleType.TRAINER)
|
||||
.enemyAbility(Abilities.BALL_FETCH);
|
||||
});
|
||||
|
||||
describe("Player", () => {
|
||||
it("should only call leaveField once on the switched out pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloLeaveSpy = vi.spyOn(piloswine, "leaveField");
|
||||
const mamoLeaveSpy = vi.spyOn(mamoswine, "leaveField");
|
||||
|
||||
game.doSwitchPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(piloLeaveSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoLeaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("should only reset summonData/turnData once per switch", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloSummonSpy = vi.spyOn(piloswine, "resetSummonData");
|
||||
const piloTurnSpy = vi.spyOn(piloswine, "resetTurnData");
|
||||
const mamoSummonSpy = vi.spyOn(mamoswine, "resetSummonData");
|
||||
const mamoTurnSpy = vi.spyOn(mamoswine, "resetTurnData");
|
||||
|
||||
game.doSwitchPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(piloSummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(piloTurnSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoSummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoTurnSpy).toHaveBeenCalledTimes(2); // once from switching, once at turn start
|
||||
});
|
||||
|
||||
it("should not reset battleData/waveData upon switching", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloWaveSpy = vi.spyOn(piloswine, "resetWaveData");
|
||||
const piloBattleWaveSpy = vi.spyOn(piloswine, "resetBattleAndWaveData");
|
||||
const mamoWaveSpy = vi.spyOn(mamoswine, "resetWaveData");
|
||||
const mamoBattleWaveSpy = vi.spyOn(mamoswine, "resetBattleAndWaveData");
|
||||
|
||||
game.doSwitchPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(piloWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(piloBattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(mamoWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(mamoBattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe("Enemy", () => {
|
||||
it("should only call leaveField once on the switched out pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [enemy1, enemy2] = game.scene.getEnemyParty();
|
||||
const enemy1LeaveSpy = vi.spyOn(enemy1, "leaveField");
|
||||
const enemy2LeaveSpy = vi.spyOn(enemy2, "leaveField");
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.forceEnemyToSwitch();
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(enemy1LeaveSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy2LeaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("should only reset summonData/turnData once per switch", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [enemy1, enemy2] = game.scene.getEnemyParty();
|
||||
const enemy1SummonSpy = vi.spyOn(enemy1, "resetSummonData");
|
||||
const enemy1TurnSpy = vi.spyOn(enemy1, "resetTurnData");
|
||||
const enemy2SummonSpy = vi.spyOn(enemy2, "resetSummonData");
|
||||
const enemy2TurnSpy = vi.spyOn(enemy2, "resetTurnData");
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.forceEnemyToSwitch();
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(enemy1SummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy1TurnSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy2SummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy2TurnSpy).toHaveBeenCalledTimes(2); // once from switching, once at turn start
|
||||
});
|
||||
|
||||
it("should not reset battleData/waveData upon switching", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [enemy1, enemy2] = game.scene.getEnemyParty();
|
||||
const enemy1WaveSpy = vi.spyOn(enemy1, "resetWaveData");
|
||||
const enemy1BattleWaveSpy = vi.spyOn(enemy1, "resetBattleAndWaveData");
|
||||
const enemy2WaveSpy = vi.spyOn(enemy2, "resetWaveData");
|
||||
const enemy2BattleWaveSpy = vi.spyOn(enemy2, "resetBattleAndWaveData");
|
||||
|
||||
game.move.select(Moves.SPLASH);
|
||||
game.forceEnemyToSwitch();
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(enemy1WaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(enemy1BattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(enemy2WaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(enemy2BattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe.each<{ name: string; playerMove?: Moves; playerAbility?: Abilities; enemyMove?: Moves }>([
|
||||
{ name: "Self Switch Attack Moves", playerMove: Moves.U_TURN },
|
||||
{ name: "Target Switch Attack Moves", enemyMove: Moves.DRAGON_TAIL },
|
||||
{ name: "Self Switch Status Moves", playerMove: Moves.TELEPORT },
|
||||
{ name: "Target Switch Status Moves", enemyMove: Moves.WHIRLWIND },
|
||||
{ name: "Self Switch Abilities", playerAbility: Abilities.EMERGENCY_EXIT, enemyMove: Moves.BRAVE_BIRD },
|
||||
/* { name: "Fainting", playerMove: Moves.EXPLOSION }, */ // TODO: This calls it twice...
|
||||
])(
|
||||
"Switch Outs - $name - ",
|
||||
({ selfMove = Moves.SPLASH, selfAbility = Abilities.BALL_FETCH, oppMove = Moves.SPLASH }) => {
|
||||
"Mid-Battle Switch Outs - $name - ",
|
||||
({ playerMove = Moves.SPLASH, playerAbility = Abilities.BALL_FETCH, enemyMove = Moves.SPLASH }) => {
|
||||
let phaserGame: Phaser.Game;
|
||||
let game: GameManager;
|
||||
|
||||
@ -32,136 +168,73 @@ describe.each<{ name: string; selfMove?: Moves; selfAbility?: Abilities; oppMove
|
||||
beforeEach(() => {
|
||||
game = new GameManager(phaserGame);
|
||||
game.override
|
||||
.moveset(playerMove)
|
||||
.ability(playerAbility)
|
||||
.battleStyle("single")
|
||||
.disableCrits()
|
||||
.enemyLevel(100)
|
||||
.battleType(BattleType.TRAINER)
|
||||
.passiveAbility(Abilities.STURDY)
|
||||
.enemySpecies(Species.MAGIKARP)
|
||||
.enemyMoveset(enemyMove)
|
||||
.enemyAbility(Abilities.BALL_FETCH)
|
||||
.enemyPassiveAbility(Abilities.NO_GUARD);
|
||||
});
|
||||
|
||||
describe("Player -", () => {
|
||||
beforeEach(() => {
|
||||
game.override.moveset(oppMove).ability(selfAbility).enemyMoveset(selfMove).enemyAbility(Abilities.BALL_FETCH);
|
||||
});
|
||||
it("should only call leaveField once on the switched out pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
it("should only call leaveField once on the switched out pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloLeaveSpy = vi.spyOn(piloswine, "leaveField");
|
||||
const mamoLeaveSpy = vi.spyOn(mamoswine, "leaveField");
|
||||
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloLeaveSpy = vi.spyOn(piloswine, "leaveField");
|
||||
const mamoLeaveSpy = vi.spyOn(mamoswine, "leaveField");
|
||||
game.move.select(playerMove);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
game.move.select(selfMove);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(piloLeaveSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoLeaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
it("should only reset summonData/turnData once per switch", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloSummonSpy = vi.spyOn(piloswine, "resetSummonData");
|
||||
const piloTurnSpy = vi.spyOn(piloswine, "resetTurnData");
|
||||
const mamoSummonSpy = vi.spyOn(mamoswine, "resetSummonData");
|
||||
const mamoTurnSpy = vi.spyOn(mamoswine, "resetTurnData");
|
||||
|
||||
game.move.select(selfMove);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(piloSummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(piloTurnSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoSummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoTurnSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should not reset battleData/waveData upon switching", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloWaveSpy = vi.spyOn(piloswine, "resetWaveData");
|
||||
const piloBattleWaveSpy = vi.spyOn(piloswine, "resetBattleAndWaveData");
|
||||
const mamoWaveSpy = vi.spyOn(mamoswine, "resetWaveData");
|
||||
const mamoBattleWaveSpy = vi.spyOn(mamoswine, "resetBattleAndWaveData");
|
||||
|
||||
game.move.select(selfMove);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(piloWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(piloBattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(mamoWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(mamoBattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
expect(piloLeaveSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoLeaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
|
||||
describe("Enemy - ", () => {
|
||||
beforeEach(() => {
|
||||
game.override
|
||||
.enemyMoveset(oppMove)
|
||||
.enemyAbility(selfAbility)
|
||||
.moveset(selfMove)
|
||||
.ability(Abilities.BALL_FETCH)
|
||||
.battleType(BattleType.TRAINER);
|
||||
it("should only reset summonData/turnData once per switch", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
// prevent natural trainer switches
|
||||
vi.spyOn(Trainer.prototype, "getPartyMemberMatchupScores").mockReturnValue([
|
||||
[100, 1],
|
||||
[100, 1],
|
||||
]);
|
||||
});
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
piloswine.addTag(BattlerTagType.AQUA_RING, 999); // give piloswine a tag to ensure we know if summonData got reset
|
||||
const piloSummonSpy = vi.spyOn(piloswine, "resetSummonData");
|
||||
const piloTurnSpy = vi.spyOn(piloswine, "resetTurnData");
|
||||
const mamoSummonSpy = vi.spyOn(mamoswine, "resetSummonData");
|
||||
const mamoTurnSpy = vi.spyOn(mamoswine, "resetTurnData");
|
||||
|
||||
it("should only call leaveField once on the switched out pokemon", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
game.move.select(playerMove);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const [enemy1, enemy2] = game.scene.getEnemyParty();
|
||||
const enemy1LeaveSpy = vi.spyOn(enemy1, "leaveField");
|
||||
const enemy2LeaveSpy = vi.spyOn(enemy2, "leaveField");
|
||||
expect(piloSummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(piloTurnSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoSummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(mamoTurnSpy).toHaveBeenCalledTimes(1);
|
||||
expect(piloswine.summonData).toEqual(new PokemonSummonData());
|
||||
expect(piloswine.turnData).toEqual(new PokemonTurnData());
|
||||
});
|
||||
|
||||
game.move.select(selfMove);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
it("should not reset battleData/waveData upon switching", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
expect(enemy1LeaveSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy2LeaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
const [piloswine, mamoswine] = game.scene.getPlayerParty();
|
||||
const piloWaveSpy = vi.spyOn(piloswine, "resetWaveData");
|
||||
const piloBattleWaveSpy = vi.spyOn(piloswine, "resetBattleAndWaveData");
|
||||
const mamoWaveSpy = vi.spyOn(mamoswine, "resetWaveData");
|
||||
const mamoBattleWaveSpy = vi.spyOn(mamoswine, "resetBattleAndWaveData");
|
||||
|
||||
it("should only reset summonData/turnData once per switch", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
game.move.select(playerMove);
|
||||
game.doSelectPartyPokemon(1);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
const [enemy1, enemy2] = game.scene.getEnemyParty();
|
||||
const enemy1SummonSpy = vi.spyOn(enemy1, "resetSummonData");
|
||||
const enemy1TurnSpy = vi.spyOn(enemy1, "resetTurnData");
|
||||
const enemy2SummonSpy = vi.spyOn(enemy2, "resetSummonData");
|
||||
const enemy2TurnSpy = vi.spyOn(enemy2, "resetTurnData");
|
||||
|
||||
game.move.select(selfMove);
|
||||
await game.phaseInterceptor.to("BerryPhase", false);
|
||||
|
||||
expect(enemy1SummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy1TurnSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy2SummonSpy).toHaveBeenCalledTimes(1);
|
||||
expect(enemy2TurnSpy).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("should not reset battleData/waveData upon switching", async () => {
|
||||
await game.classicMode.startBattle([Species.PILOSWINE, Species.MAMOSWINE]);
|
||||
|
||||
const [enemy1, enemy2] = game.scene.getEnemyParty();
|
||||
const enemy1WaveSpy = vi.spyOn(enemy1, "resetWaveData");
|
||||
const enemy1BattleWaveSpy = vi.spyOn(enemy1, "resetBattleAndWaveData");
|
||||
const enemy2WaveSpy = vi.spyOn(enemy2, "resetWaveData");
|
||||
const enemy2BattleWaveSpy = vi.spyOn(enemy2, "resetBattleAndWaveData");
|
||||
|
||||
game.move.select(selfMove);
|
||||
await game.phaseInterceptor.to("TurnEndPhase");
|
||||
|
||||
expect(enemy1WaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(enemy1BattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(enemy2WaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(enemy2BattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
expect(piloWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(piloBattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(mamoWaveSpy).toHaveBeenCalledTimes(0);
|
||||
expect(mamoBattleWaveSpy).toHaveBeenCalledTimes(0);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
Loading…
Reference in New Issue
Block a user