Minor Attempt run phase rework to abstract logic to whole team

This commit is contained in:
jnotsknab 2025-06-19 05:52:29 -05:00
parent 6873a89296
commit 53c5efc82e
4 changed files with 32 additions and 8 deletions

View File

@ -808,6 +808,15 @@ export default class BattleScene extends SceneBase {
return party.slice(0, Math.min(party.length, this.currentBattle?.double ? 2 : 1)); 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[] { public getEnemyParty(): EnemyPokemon[] {
return this.currentBattle?.enemyParty ?? []; return this.currentBattle?.enemyParty ?? [];
} }

View File

@ -4,7 +4,7 @@ import { StatusEffect } from "#enums/status-effect";
import type { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon"; import type { PlayerPokemon, EnemyPokemon } from "#app/field/pokemon";
import type Pokemon from "#app/field/pokemon"; import type Pokemon from "#app/field/pokemon";
import i18next from "i18next"; import i18next from "i18next";
import { NumberHolder } from "#app/utils/common"; import { NumberHolder, randSeedInt } from "#app/utils/common";
import { PokemonPhase } from "./pokemon-phase"; import { PokemonPhase } from "./pokemon-phase";
import { globalScene } from "#app/global-scene"; 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 */ /** For testing purposes: this is to force the pokemon to fail and escape */
public forceFailEscape = false; public forceFailEscape = false;
private getTeamRNG(range: number, min = 0) {
return globalScene.currentBattle ? globalScene.randBattleSeedInt(range, min) : randSeedInt(range, min);
}
start() { start() {
super.start(); super.start();
const playerField = globalScene.getPlayerField(); const activePlayerField = globalScene.getActivePlayerField();
const enemyField = globalScene.getEnemyField(); const enemyField = globalScene.getEnemyField();
//Attempting to run is a TEAM not PLAYER based action, we should not be referercing individual pokemon,
const playerPokemon = this.getPokemon(); //we should instead be referring to the team as a whole and
const escapeChance = new NumberHolder(0); 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)); enemyField.forEach(enemyPokemon => applyPreLeaveFieldAbAttrs("PreLeaveFieldAbAttr", enemyPokemon));
globalScene.playSound("se/flee"); globalScene.playSound("se/flee");
@ -60,7 +67,11 @@ export class AttemptRunPhase extends PokemonPhase {
globalScene.phaseManager.pushNew("NewBattlePhase"); globalScene.phaseManager.pushNew("NewBattlePhase");
} else { } 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); globalScene.phaseManager.queueMessage(i18next.t("battle:runAwayCannotEscape"), null, true, 500);
} }

View File

@ -8,6 +8,7 @@ import { SpeciesId } from "#enums/species-id";
import GameManager from "#test/testUtils/gameManager"; import GameManager from "#test/testUtils/gameManager";
import Phaser from "phaser"; import Phaser from "phaser";
import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, it, expect, vi } from "vitest";
import { globalScene } from "#app/global-scene";
describe("Abilities - Desolate Land", () => { describe("Abilities - Desolate Land", () => {
let phaserGame: Phaser.Game; let phaserGame: Phaser.Game;
@ -145,6 +146,7 @@ describe("Abilities - Desolate Land", () => {
expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.HARSH_SUN); expect(game.scene.arena.weather?.weatherType).toBe(WeatherType.HARSH_SUN);
vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0);
vi.spyOn(globalScene, "randBattleSeedInt").mockReturnValue(0);
const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase; const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase;
commandPhase.handleCommand(Command.RUN, 0); commandPhase.handleCommand(Command.RUN, 0);

View File

@ -10,6 +10,7 @@ import { Stat } from "#enums/stat";
import GameManager from "#test/testUtils/gameManager"; import GameManager from "#test/testUtils/gameManager";
import Phaser from "phaser"; 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 { globalScene } from "#app/global-scene";
describe("Abilities - Neutralizing Gas", () => { describe("Abilities - Neutralizing Gas", () => {
let phaserGame: Phaser.Game; let phaserGame: Phaser.Game;
@ -164,6 +165,7 @@ describe("Abilities - Neutralizing Gas", () => {
expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined(); expect(game.scene.arena.getTag(ArenaTagType.NEUTRALIZING_GAS)).toBeDefined();
vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0); vi.spyOn(game.scene.getPlayerPokemon()!, "randBattleSeedInt").mockReturnValue(0);
vi.spyOn(globalScene, "randBattleSeedInt").mockReturnValue(0);
const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase; const commandPhase = game.scene.phaseManager.getCurrentPhase() as CommandPhase;
commandPhase.handleCommand(Command.RUN, 0); commandPhase.handleCommand(Command.RUN, 0);