diff --git a/src/phases/move-end-phase.ts b/src/phases/move-end-phase.ts index 46e266a32b7..f3a40ce69bd 100644 --- a/src/phases/move-end-phase.ts +++ b/src/phases/move-end-phase.ts @@ -1,13 +1,20 @@ import { globalScene } from "#app/global-scene"; import { BattlerTagLapseType } from "#app/data/battler-tags"; import { PokemonPhase } from "./pokemon-phase"; +import type { BattlerIndex } from "#app/battle"; export class MoveEndPhase extends PokemonPhase { + private wasFollowUp: boolean; + constructor(battlerIndex: BattlerIndex, wasFollowUp: boolean = false) { + super(battlerIndex); + this.wasFollowUp = wasFollowUp; + } + start() { super.start(); const pokemon = this.getPokemon(); - if (pokemon.isActive(true)) { + if (!this.wasFollowUp && pokemon?.isActive(true)) { pokemon.lapseTags(BattlerTagLapseType.AFTER_MOVE); } diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index e04f48c2880..cab02174605 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -465,13 +465,10 @@ export class MovePhase extends BattlePhase { } /** - * Queues a {@linkcode MoveEndPhase} if the move wasn't a {@linkcode followUp} and {@linkcode canMove()} returns `true`, - * then ends the phase. + * Queues a {@linkcode MoveEndPhase} and then ends the phase */ public end(): void { - if (!this.followUp && this.canMove()) { - globalScene.unshiftPhase(new MoveEndPhase(this.pokemon.getBattlerIndex())); - } + globalScene.unshiftPhase(new MoveEndPhase(this.pokemon.getBattlerIndex(), this.followUp)); super.end(); } diff --git a/test/abilities/dancer.test.ts b/test/abilities/dancer.test.ts index 56c357b2212..c296329473d 100644 --- a/test/abilities/dancer.test.ts +++ b/test/abilities/dancer.test.ts @@ -39,20 +39,24 @@ describe("Abilities - Dancer", () => { game.move.select(Moves.SPLASH); game.move.select(Moves.SWORDS_DANCE, 1); await game.setTurnOrder([BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2]); - await game.phaseInterceptor.to("MovePhase"); - // immediately copies ally move - await game.phaseInterceptor.to("MovePhase", false); + await game.phaseInterceptor.to("MovePhase"); // feebas uses swords dance + await game.phaseInterceptor.to("MovePhase", false); // oricorio copies swords dance + let currentPhase = game.scene.getCurrentPhase() as MovePhase; expect(currentPhase.pokemon).toBe(oricorio); expect(currentPhase.move.moveId).toBe(Moves.SWORDS_DANCE); - await game.phaseInterceptor.to("MoveEndPhase"); - await game.phaseInterceptor.to("MovePhase"); - // immediately copies enemy move - await game.phaseInterceptor.to("MovePhase", false); + + await game.phaseInterceptor.to("MoveEndPhase"); // end oricorio's move + await game.phaseInterceptor.to("MovePhase"); // magikarp 1 copies swords dance + await game.phaseInterceptor.to("MovePhase"); // magikarp 2 copies swords dance + await game.phaseInterceptor.to("MovePhase"); // magikarp (left) uses victory dance + await game.phaseInterceptor.to("MovePhase", false); // oricorio copies magikarp's victory dance + currentPhase = game.scene.getCurrentPhase() as MovePhase; expect(currentPhase.pokemon).toBe(oricorio); expect(currentPhase.move.moveId).toBe(Moves.VICTORY_DANCE); - await game.phaseInterceptor.to("BerryPhase"); + + await game.phaseInterceptor.to("BerryPhase"); // finish the turn // doesn't use PP if copied move is also in moveset expect(oricorio.moveset[0]?.ppUsed).toBe(0); diff --git a/test/abilities/mold_breaker.test.ts b/test/abilities/mold_breaker.test.ts new file mode 100644 index 00000000000..8f050a68d76 --- /dev/null +++ b/test/abilities/mold_breaker.test.ts @@ -0,0 +1,51 @@ +import { BattlerIndex } from "#app/battle"; +import { globalScene } from "#app/global-scene"; +import { Abilities } from "#enums/abilities"; +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 } from "vitest"; + +describe("Abilities - Mold Breaker", () => { + 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 + .moveset([ Moves.SPLASH ]) + .ability(Abilities.MOLD_BREAKER) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should turn off the ignore abilities arena variable after the user's move", async () => { + game.override.enemyMoveset(Moves.SPLASH) + .ability(Abilities.MOLD_BREAKER) + .moveset([ Moves.ERUPTION ]) + .startingLevel(100) + .enemyLevel(2); + await game.classicMode.startBattle([ Species.MAGIKARP ]); + const enemy = game.scene.getEnemyPokemon()!; + + expect(enemy.isFainted()).toBe(false); + game.move.select(Moves.SPLASH); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.phaseInterceptor.to("MoveEndPhase", true); + expect(globalScene.arena.ignoreAbilities).toBe(false); + }); +});