[Bug]: Fix #5010: roar and whirlwind missing fail message when against a trainer (#5659)

* [BUG] Fixes #5010 Roar and Whirlwind don´t display a fail message
Roar and Whirlwind should now display a fail message when
used against a trainer with only one pokémon left

* Apply suggestions from code review made by SirzBenjie
This commit is contained in:
Sophia 2025-05-21 08:14:16 +01:00 committed by GitHub
parent 3c934808c0
commit d1b0bbb155
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 47 additions and 0 deletions

View File

@ -6390,8 +6390,23 @@ export class ForceSwitchOutAttr extends MoveEffectAttr {
return (user, target, move) => { return (user, target, move) => {
const switchOutTarget = (this.selfSwitch ? user : target); const switchOutTarget = (this.selfSwitch ? user : target);
const player = switchOutTarget instanceof PlayerPokemon; const player = switchOutTarget instanceof PlayerPokemon;
const forceSwitchAttr = move.getAttrs(ForceSwitchOutAttr).find(attr => attr.switchType === SwitchType.FORCE_SWITCH);
if (!this.selfSwitch) { if (!this.selfSwitch) {
if (move.hitsSubstitute(user, target)) {
return false;
}
// Check if the move is Roar or Whirlwind and if there is a trainer with only Pokémon left.
if (forceSwitchAttr && 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(p => p.hp > 0 && p.isAllowedInBattle());
if (remainingPokemon.length <= 1) {
return false;
}
}
// Dondozo with an allied Tatsugiri in its mouth cannot be forced out // Dondozo with an allied Tatsugiri in its mouth cannot be forced out
const commandedTag = switchOutTarget.getTag(BattlerTagType.COMMANDED); const commandedTag = switchOutTarget.getTag(BattlerTagType.COMMANDED);
if (commandedTag?.getSourcePokemon()?.isActive(true)) { if (commandedTag?.getSourcePokemon()?.isActive(true)) {

View File

@ -10,6 +10,7 @@ import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
import { Status } from "#app/data/status-effect"; import { Status } from "#app/data/status-effect";
import { StatusEffect } from "#enums/status-effect"; import { StatusEffect } from "#enums/status-effect";
import { globalScene } from "#app/global-scene";
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { BattleType } from "#enums/battle-type"; import { BattleType } from "#enums/battle-type";
import { TrainerType } from "#enums/trainer-type"; import { TrainerType } from "#enums/trainer-type";
@ -161,6 +162,37 @@ describe("Moves - Whirlwind", () => {
expect(eevee.isOnField()).toBe(false); 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.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!"));
});
it("should not pull in the other trainer's pokemon in a partner trainer battle", async () => { it("should not pull in the other trainer's pokemon in a partner trainer battle", async () => {
game.override game.override
.startingWave(2) .startingWave(2)