diff --git a/src/battle-scene.ts b/src/battle-scene.ts index b802466ee19..7821ce3f7f7 100644 --- a/src/battle-scene.ts +++ b/src/battle-scene.ts @@ -808,6 +808,15 @@ export default class BattleScene extends SceneBase { return party.slice(0, Math.min(party.length, this.currentBattle?.double ? 2 : 1)); } + /** + * Returns an array of PlayerPokemon of length 1 or 2 depending on if in a double battle or not. + * Does check if the pokemon are on the field or not. + * @returns array of {@linkcode PlayerPokemon} + */ + public getActivePlayerField(): PlayerPokemon[] { + return this.getPlayerField().filter(p => p.isActive()); + } + public getEnemyParty(): EnemyPokemon[] { return this.currentBattle?.enemyParty ?? []; } diff --git a/src/phases/attempt-run-phase.ts b/src/phases/attempt-run-phase.ts index 5e24f3474a6..31b6bc61ff4 100644 --- a/src/phases/attempt-run-phase.ts +++ b/src/phases/attempt-run-phase.ts @@ -4,7 +4,7 @@ import { StatusEffect } from "#enums/status-effect"; import type { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon"; import i18next from "i18next"; -import { NumberHolder } from "#app/utils/common"; +import { NumberHolder, randSeedInt } from "#app/utils/common"; import { PokemonPhase } from "./pokemon-phase"; import { globalScene } from "#app/global-scene"; @@ -13,21 +13,28 @@ export class AttemptRunPhase extends PokemonPhase { /** For testing purposes: this is to force the pokemon to fail and escape */ public forceFailEscape = false; + private getTeamRNG(range: number, min = 0) { + return globalScene.currentBattle ? globalScene.randBattleSeedInt(range, min) : randSeedInt(range, min); + } + start() { super.start(); - const playerField = globalScene.getPlayerField(); + const activePlayerField = globalScene.getActivePlayerField(); const enemyField = globalScene.getEnemyField(); - - const playerPokemon = this.getPokemon(); + //Attempting to run is a TEAM not PLAYER based action, we should not be referercing individual pokemon, + //we should instead be referring to the team as a whole and const escapeChance = new NumberHolder(0); + const escapeRoll = this.getTeamRNG(100); - this.attemptRunAway(playerField, enemyField, escapeChance); + this.attemptRunAway(activePlayerField, enemyField, escapeChance); - applyAbAttrs("RunSuccessAbAttr", playerPokemon, null, false, escapeChance); + activePlayerField.forEach(p => { + applyAbAttrs("RunSuccessAbAttr", p, null, false, escapeChance); + }); - if (playerPokemon.randBattleSeedInt(100) < escapeChance.value && !this.forceFailEscape) { + if (escapeRoll < escapeChance.value && !this.forceFailEscape) { enemyField.forEach(enemyPokemon => applyPreLeaveFieldAbAttrs("PreLeaveFieldAbAttr", enemyPokemon)); globalScene.playSound("se/flee"); @@ -60,7 +67,11 @@ export class AttemptRunPhase extends PokemonPhase { globalScene.phaseManager.pushNew("NewBattlePhase"); } else { - playerPokemon.turnData.failedRunAway = true; + //there should be a general failed run away bool for the active team + activePlayerField.forEach(p => { + p.turnData.failedRunAway = true; + }); + globalScene.phaseManager.queueMessage(i18next.t("battle:runAwayCannotEscape"), null, true, 500); } diff --git a/test/abilities/desolate-land.test.ts b/test/abilities/desolate-land.test.ts index 90565d9caf8..eee44b3d818 100644 --- a/test/abilities/desolate-land.test.ts +++ b/test/abilities/desolate-land.test.ts @@ -8,6 +8,7 @@ import { SpeciesId } from "#enums/species-id"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; +import { globalScene } from "#app/global-scene"; describe("Abilities - Desolate Land", () => { let phaserGame: Phaser.Game; @@ -145,6 +146,7 @@ describe("Abilities - Desolate Land", () => { expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.HARSH_SUN); vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); + vi.spyOn(globalScene, "randBattleSeedInt").mockReturnValue(0); const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0); diff --git a/test/abilities/neutralizing_gas.test.ts b/test/abilities/neutralizing_gas.test.ts index 2408a78f11d..8007dd3723b 100644 --- a/test/abilities/neutralizing_gas.test.ts +++ b/test/abilities/neutralizing_gas.test.ts @@ -10,6 +10,7 @@ import { Stat } from "#enums/stat"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { globalScene } from "#app/global-scene"; describe("Abilities - Neutralizing Gas", () => { let phaserGame: Phaser.Game; @@ -164,6 +165,7 @@ describe("Abilities - Neutralizing Gas", () => { expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined(); vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); + vi.spyOn(globalScene, "randBattleSeedInt").mockReturnValue(0); const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase; commandPhase.handleCommand(Command.RUN, 0);