diff --git a/src/phases/move-phase.ts b/src/phases/move-phase.ts index f8edaa56981..119a3e5a466 100644 --- a/src/phases/move-phase.ts +++ b/src/phases/move-phase.ts @@ -368,6 +368,17 @@ export class MovePhase extends BattlePhase { const move = this.move.getMove(); + // Check if the move is Roar or Whirlwind and if there is a trainer with only Pokémon left. + if ([Moves.ROAR, Moves.WHIRLWIND].includes(this.move.moveId) && globalScene.currentBattle.trainer) { + const enemyParty = globalScene.getEnemyParty(); + // Filter out any Pokémon that are not allowed in battle (e.g. fainted ones) + const remainingPokemon = enemyParty.filter(pokemon => pokemon.hp > 0 && pokemon.isAllowedInBattle()); + + if (remainingPokemon.length <= 1) { + success = false; + } + } + /** * Move conditions assume the move has a single target * TODO: is this sustainable? diff --git a/test/moves/whirlwind.test.ts b/test/moves/whirlwind.test.ts index d6124b6c766..0fc0e9058bf 100644 --- a/test/moves/whirlwind.test.ts +++ b/test/moves/whirlwind.test.ts @@ -10,6 +10,7 @@ import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { Status } from "#app/data/status-effect"; import { StatusEffect } from "#enums/status-effect"; +import { globalScene } from "#app/global-scene"; describe("Moves - Whirlwind", () => { let phaserGame: Phaser.Game; @@ -156,4 +157,36 @@ describe("Moves - Whirlwind", () => { expect(lapras.isOnField()).toBe(true); expect(eevee.isOnField()).toBe(false); }); + + it("should fail when player uses Whirlwind against an opponent with only one available Pokémon", async () => { + // Set up the battle scenario with the player knowing Whirlwind + game.override.startingWave(5).enemySpecies(Species.PIDGEY).moveset([Moves.WHIRLWIND]); + await game.classicMode.startBattle(); + + const enemyParty = game.scene.getEnemyParty(); + + // Ensure the opponent has only one available Pokémon + if (enemyParty.length > 1) { + enemyParty.slice(1).forEach(p => { + p.hp = 0; + p.status = new Status(StatusEffect.FAINT); + }); + } + const eligibleEnemy = enemyParty.filter(p => p.hp > 0 && p.isAllowedInBattle()); + expect(eligibleEnemy.length).toBe(1); + + // Spy on the queueMessage function + const queueSpy = vi.spyOn(globalScene, "queueMessage"); + + // Player uses Whirlwind; opponent uses Splash + game.move.select(Moves.WHIRLWIND); + await game.forceEnemyMove(Moves.SPLASH); + await game.phaseInterceptor.to("MoveEndPhase", false); + await game.toNextTurn(); + + // Verify that the failure message is displayed for Whirlwind + expect(queueSpy).toHaveBeenCalledWith(expect.stringContaining("But it failed")); + // Verify the opponent's Splash message + expect(queueSpy).toHaveBeenCalledWith(expect.stringContaining("But nothing happened!")); + }); });