From d5146a57b9a1e5dccbe09ba8a8d19549d8c67ab3 Mon Sep 17 00:00:00 2001 From: geeilhan <107366005+geeilhan@users.noreply.github.com> Date: Sat, 30 Nov 2024 22:08:32 +0100 Subject: [PATCH] [Bug] Fix Lingering Arena Trap if Pokemon Switches Out (#4755) * [P2 BUG] Fixed Lingering Arena Trap if Pokemon Switches Out (#3713) * added switchOutStatus for all relevant moves * Added Lingering Arena Trap Fix for Mystery Encounters * Removing Redundant switchOutStatus Sets * added automated test case to arena trap test * Update src/field/pokemon.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Update src/test/abilities/arena_trap.test.ts Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com> Co-authored-by: Moka <54149968+MokaStitcher@users.noreply.github.com> --- src/field/pokemon.ts | 10 ++++++- src/test/abilities/arena_trap.test.ts | 38 ++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index d46e729274c..5706725f763 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -325,6 +325,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { if (!this.scene) { return false; } + if (this.switchOutStatus) { + return false; + } return this.scene.field.getIndex(this) > -1; } @@ -1583,7 +1586,12 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { } const trappedByAbility = new Utils.BooleanHolder(false); - const opposingField = this.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField(); + /** + * Contains opposing Pokemon (Enemy/Player Pokemon) depending on perspective + * Afterwards, it filters out Pokemon that have been switched out of the field so trapped abilities/moves do not trigger + */ + const opposingFieldUnfiltered = this.isPlayer() ? this.scene.getEnemyField() : this.scene.getPlayerField(); + const opposingField = opposingFieldUnfiltered.filter(enemyPkm => enemyPkm.switchOutStatus === false); opposingField.forEach((opponent) => applyCheckTrappedAbAttrs(CheckTrappedAbAttr, opponent, trappedByAbility, this, trappedAbMessages, simulated) diff --git a/src/test/abilities/arena_trap.test.ts b/src/test/abilities/arena_trap.test.ts index 5068fed6b77..12b9673080d 100644 --- a/src/test/abilities/arena_trap.test.ts +++ b/src/test/abilities/arena_trap.test.ts @@ -1,9 +1,10 @@ +import { allAbilities } from "#app/data/ability"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/utils/gameManager"; import Phaser from "phaser"; -import { afterEach, beforeAll, beforeEach, describe, it, expect } from "vitest"; +import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; describe("Abilities - Arena Trap", () => { let phaserGame: Phaser.Game; @@ -55,4 +56,39 @@ describe("Abilities - Arena Trap", () => { expect(game.scene.getEnemyField().length).toBe(2); }); + + /** + * This checks if the Player Pokemon is able to switch out/run away after the Enemy Pokemon with {@linkcode Abilities.ARENA_TRAP} + * is forcefully moved out of the field from moves such as Roar {@linkcode Moves.ROAR} + * + * Note: It should be able to switch out/run away + */ + it("should lift if pokemon with this ability leaves the field", async () => { + game.override + .battleType("double") + .enemyMoveset(Moves.SPLASH) + .moveset([ Moves.ROAR, Moves.SPLASH ]) + .ability(Abilities.BALL_FETCH); + await game.classicMode.startBattle([ Species.MAGIKARP, Species.SUDOWOODO, Species.LUNATONE ]); + + const [ enemy1, enemy2 ] = game.scene.getEnemyField(); + const [ player1, player2 ] = game.scene.getPlayerField(); + + vi.spyOn(enemy1, "getAbility").mockReturnValue(allAbilities[Abilities.ARENA_TRAP]); + + game.move.select(Moves.ROAR); + game.move.select(Moves.SPLASH, 1); + + // This runs the fist command phase where the moves are selected + await game.toNextTurn(); + // During the next command phase the player pokemons should not be trapped anymore + game.move.select(Moves.SPLASH); + game.move.select(Moves.SPLASH, 1); + await game.toNextTurn(); + + expect(player1.isTrapped()).toBe(false); + expect(player2.isTrapped()).toBe(false); + expect(enemy1.isOnField()).toBe(false); + expect(enemy2.isOnField()).toBe(true); + }); });