mirror of
https://github.com/pagefaultgames/pokerogue.git
synced 2025-07-03 15:02:16 +02:00
[Refactor] Minor run phase rework (#6017)
* Minor Attempt run phase rework to abstract logic to whole team * Decoupled individual pokemon from run phase logic * Formatting * Completed run phase refactor implementation and updated tests * Updated run phase to extend field phase instead of pokemon phase * Removed unused phase decleration in tests * Removed unecessary arg in turn start phase as refactor no longer needs it * Cleaned up getPlayerField * Made adjustments based on reviewer suggestions * Reintrocuded calculateEscapeChance into AttemptRunPhase and removed run utils * Resolve merge issues * Minor TSDoc improvement to `BattleScene#getPlayerField` * Moved early override check to top of calculateEscapeChance --------- Co-authored-by: NightKev <34855794+DayKev@users.noreply.github.com>
This commit is contained in:
parent
a54cd953a6
commit
12aaa31454
@ -797,12 +797,14 @@ export default class BattleScene extends SceneBase {
|
|||||||
// TODO: Add `undefined` to return type
|
// TODO: Add `undefined` to return type
|
||||||
/**
|
/**
|
||||||
* Returns an array of PlayerPokemon of length 1 or 2 depending on if in a double battle or not.
|
* Returns an array of PlayerPokemon of length 1 or 2 depending on if in a double battle or not.
|
||||||
* Does not actually check if the pokemon are on the field or not.
|
* @param active - (Default `false`) Whether to consider only {@linkcode Pokemon.isActive | active} on-field pokemon
|
||||||
* @returns array of {@linkcode PlayerPokemon}
|
* @returns array of {@linkcode PlayerPokemon}
|
||||||
*/
|
*/
|
||||||
public getPlayerField(): PlayerPokemon[] {
|
public getPlayerField(active = false): PlayerPokemon[] {
|
||||||
const party = this.getPlayerParty();
|
const party = this.getPlayerParty();
|
||||||
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))
|
||||||
|
.filter(p => !active || p.isActive());
|
||||||
}
|
}
|
||||||
|
|
||||||
public getEnemyParty(): EnemyPokemon[] {
|
public getEnemyParty(): EnemyPokemon[] {
|
||||||
|
@ -95,6 +95,12 @@ export default class Battle {
|
|||||||
/** If the current battle is a Mystery Encounter, this will always be defined */
|
/** If the current battle is a Mystery Encounter, this will always be defined */
|
||||||
public mysteryEncounter?: MysteryEncounter;
|
public mysteryEncounter?: MysteryEncounter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracker for whether the last run attempt failed.
|
||||||
|
* @defaultValue `false`
|
||||||
|
*/
|
||||||
|
public failedRunAway = false;
|
||||||
|
|
||||||
private rngCounter = 0;
|
private rngCounter = 0;
|
||||||
|
|
||||||
constructor(gameMode: GameMode, waveIndex: number, battleType: BattleType, trainer?: Trainer, double = false) {
|
constructor(gameMode: GameMode, waveIndex: number, battleType: BattleType, trainer?: Trainer, double = false) {
|
||||||
|
@ -119,7 +119,13 @@ class DefaultOverrides {
|
|||||||
* or `false` to force it to never trigger.
|
* or `false` to force it to never trigger.
|
||||||
*/
|
*/
|
||||||
readonly CONFUSION_ACTIVATION_OVERRIDE: boolean | null = null;
|
readonly CONFUSION_ACTIVATION_OVERRIDE: boolean | null = null;
|
||||||
|
/**
|
||||||
|
* If non-null, will override random flee attempts to always or never succeed by forcing {@linkcode calculateEscapeChance} to return 100% or 0%.
|
||||||
|
* Set to `null` to disable.
|
||||||
|
*
|
||||||
|
* Is overridden if either player Pokemon has {@linkcode AbilityId.RUN_AWAY | Run Away}.
|
||||||
|
*/
|
||||||
|
readonly RUN_SUCCESS_OVERRIDE: boolean | null = null;
|
||||||
// ----------------
|
// ----------------
|
||||||
// PLAYER OVERRIDES
|
// PLAYER OVERRIDES
|
||||||
// ----------------
|
// ----------------
|
||||||
|
@ -1,34 +1,33 @@
|
|||||||
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||||
|
import { globalScene } from "#app/global-scene";
|
||||||
|
import Overrides from "#app/overrides";
|
||||||
|
import { FieldPhase } from "#app/phases/field-phase";
|
||||||
|
import { NumberHolder } from "#app/utils/common";
|
||||||
import { Stat } from "#enums/stat";
|
import { Stat } from "#enums/stat";
|
||||||
import { StatusEffect } from "#enums/status-effect";
|
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 i18next from "i18next";
|
||||||
import { NumberHolder } from "#app/utils/common";
|
|
||||||
import { PokemonPhase } from "./pokemon-phase";
|
|
||||||
import { globalScene } from "#app/global-scene";
|
|
||||||
|
|
||||||
export class AttemptRunPhase extends PokemonPhase {
|
export class AttemptRunPhase extends FieldPhase {
|
||||||
public readonly phaseName = "AttemptRunPhase";
|
public readonly phaseName = "AttemptRunPhase";
|
||||||
/** For testing purposes: this is to force the pokemon to fail and escape */
|
|
||||||
public forceFailEscape = false;
|
|
||||||
|
|
||||||
start() {
|
public start() {
|
||||||
super.start();
|
super.start();
|
||||||
|
|
||||||
const playerField = globalScene.getPlayerField();
|
// Increment escape attempts count on entry
|
||||||
|
const currentAttempts = globalScene.currentBattle.escapeAttempts++;
|
||||||
|
|
||||||
|
const activePlayerField = globalScene.getPlayerField(true);
|
||||||
const enemyField = globalScene.getEnemyField();
|
const enemyField = globalScene.getEnemyField();
|
||||||
|
|
||||||
const playerPokemon = this.getPokemon();
|
const escapeRoll = globalScene.randBattleSeedInt(100);
|
||||||
|
const escapeChance = new NumberHolder(this.calculateEscapeChance(currentAttempts));
|
||||||
|
|
||||||
const escapeChance = new NumberHolder(0);
|
activePlayerField.forEach(pokemon => {
|
||||||
|
applyAbAttrs("RunSuccessAbAttr", { pokemon, chance: escapeChance });
|
||||||
|
});
|
||||||
|
|
||||||
this.attemptRunAway(playerField, enemyField, escapeChance);
|
if (escapeRoll < escapeChance.value) {
|
||||||
|
enemyField.forEach(pokemon => applyAbAttrs("PreLeaveFieldAbAttr", { pokemon }));
|
||||||
applyAbAttrs("RunSuccessAbAttr", { pokemon: playerPokemon, chance: escapeChance });
|
|
||||||
|
|
||||||
if (playerPokemon.randBattleSeedInt(100) < escapeChance.value && !this.forceFailEscape) {
|
|
||||||
enemyField.forEach(enemyPokemon => applyAbAttrs("PreLeaveFieldAbAttr", { pokemon: enemyPokemon }));
|
|
||||||
|
|
||||||
globalScene.playSound("se/flee");
|
globalScene.playSound("se/flee");
|
||||||
globalScene.phaseManager.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500);
|
globalScene.phaseManager.queueMessage(i18next.t("battle:runAwaySuccess"), null, true, 500);
|
||||||
@ -57,24 +56,35 @@ export class AttemptRunPhase extends PokemonPhase {
|
|||||||
|
|
||||||
globalScene.phaseManager.pushNew("NewBattlePhase");
|
globalScene.phaseManager.pushNew("NewBattlePhase");
|
||||||
} else {
|
} else {
|
||||||
playerPokemon.turnData.failedRunAway = true;
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.end();
|
this.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
attemptRunAway(playerField: PlayerPokemon[], enemyField: EnemyPokemon[], escapeChance: NumberHolder) {
|
/**
|
||||||
/** Sum of the speed of all enemy pokemon on the field */
|
* Calculate the chance for the player's team to successfully run away from battle.
|
||||||
const enemySpeed = enemyField.reduce(
|
*
|
||||||
(total: number, enemyPokemon: Pokemon) => total + enemyPokemon.getStat(Stat.SPD),
|
* @param escapeAttempts - The number of prior failed escape attempts in the current battle
|
||||||
0,
|
* @returns The final escape chance, as percentage out of 100.
|
||||||
);
|
*/
|
||||||
/** Sum of the speed of all player pokemon on the field */
|
public calculateEscapeChance(escapeAttempts: number): number {
|
||||||
const playerSpeed = playerField.reduce(
|
// Check for override, guaranteeing or forbidding random flee attempts as applicable.
|
||||||
(total: number, playerPokemon: Pokemon) => total + playerPokemon.getStat(Stat.SPD),
|
if (Overrides.RUN_SUCCESS_OVERRIDE !== null) {
|
||||||
0,
|
return Overrides.RUN_SUCCESS_OVERRIDE ? 100 : 0;
|
||||||
);
|
}
|
||||||
|
|
||||||
|
const enemyField = globalScene.getEnemyField();
|
||||||
|
const activePlayerField = globalScene.getPlayerField(true);
|
||||||
|
|
||||||
|
// Cf https://bulbapedia.bulbagarden.net/wiki/Escape#Generation_V_onwards
|
||||||
|
// From gen 5 onwards, running takes the _base_ speed totals of both party sides.
|
||||||
|
const enemySpeed = enemyField.reduce((total, enemy) => total + enemy.getStat(Stat.SPD), 0);
|
||||||
|
const playerSpeed = activePlayerField.reduce((total, player) => total + player.getStat(Stat.SPD), 0);
|
||||||
|
|
||||||
/* The way the escape chance works is by looking at the difference between your speed and the enemy field's average speed as a ratio. The higher this ratio, the higher your chance of success.
|
/* The way the escape chance works is by looking at the difference between your speed and the enemy field's average speed as a ratio. The higher this ratio, the higher your chance of success.
|
||||||
* However, there is a cap for the ratio of your speed vs enemy speed which beyond that point, you won't gain any advantage. It also looks at how many times you've tried to escape.
|
* However, there is a cap for the ratio of your speed vs enemy speed which beyond that point, you won't gain any advantage. It also looks at how many times you've tried to escape.
|
||||||
@ -92,10 +102,8 @@ export class AttemptRunPhase extends PokemonPhase {
|
|||||||
* From the above, we can calculate the below values
|
* From the above, we can calculate the below values
|
||||||
*/
|
*/
|
||||||
|
|
||||||
let isBoss = false;
|
/** Whether at least 1 pokemon on the enemy field is a boss. */
|
||||||
for (let e = 0; e < enemyField.length; e++) {
|
const isBoss = enemyField.some(e => e.isBoss());
|
||||||
isBoss = isBoss || enemyField[e].isBoss(); // this line checks if any of the enemy pokemon on the field are bosses; if so, the calculation for escaping is different
|
|
||||||
}
|
|
||||||
|
|
||||||
/** The ratio between the speed of your active pokemon and the speed of the enemy field */
|
/** The ratio between the speed of your active pokemon and the speed of the enemy field */
|
||||||
const speedRatio = playerSpeed / enemySpeed;
|
const speedRatio = playerSpeed / enemySpeed;
|
||||||
@ -111,8 +119,8 @@ export class AttemptRunPhase extends PokemonPhase {
|
|||||||
const escapeSlope = (maxChance - minChance) / speedCap;
|
const escapeSlope = (maxChance - minChance) / speedCap;
|
||||||
|
|
||||||
// This will calculate the escape chance given all of the above and clamp it to the range of [`minChance`, `maxChance`]
|
// This will calculate the escape chance given all of the above and clamp it to the range of [`minChance`, `maxChance`]
|
||||||
escapeChance.value = Phaser.Math.Clamp(
|
return Phaser.Math.Clamp(
|
||||||
Math.round(escapeSlope * speedRatio + minChance + escapeBonus * globalScene.currentBattle.escapeAttempts++),
|
Math.round(escapeSlope * speedRatio + minChance + escapeBonus * escapeAttempts),
|
||||||
minChance,
|
minChance,
|
||||||
maxChance,
|
maxChance,
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
import { applyAbAttrs } from "#app/data/abilities/apply-ab-attrs";
|
||||||
import { allMoves } from "#app/data/data-lists";
|
import { allMoves } from "#app/data/data-lists";
|
||||||
import { AbilityId } from "#enums/ability-id";
|
|
||||||
import { Stat } from "#app/enums/stat";
|
import { Stat } from "#app/enums/stat";
|
||||||
import type Pokemon from "#app/field/pokemon";
|
import type Pokemon from "#app/field/pokemon";
|
||||||
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
import { PokemonMove } from "#app/data/moves/pokemon-move";
|
||||||
@ -213,27 +212,8 @@ export class TurnStartPhase extends FieldPhase {
|
|||||||
break;
|
break;
|
||||||
case Command.RUN:
|
case Command.RUN:
|
||||||
{
|
{
|
||||||
let runningPokemon = pokemon;
|
// Running (like ball throwing) is a team action taking up both Pokemon's turns.
|
||||||
if (globalScene.currentBattle.double) {
|
phaseManager.unshiftNew("AttemptRunPhase");
|
||||||
const playerActivePokemon = field.filter(pokemon => {
|
|
||||||
if (pokemon) {
|
|
||||||
return pokemon.isPlayer() && pokemon.isActive();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
});
|
|
||||||
// if only one pokemon is alive, use that one
|
|
||||||
if (playerActivePokemon.length > 1) {
|
|
||||||
// find which active pokemon has faster speed
|
|
||||||
const fasterPokemon =
|
|
||||||
playerActivePokemon[0].getStat(Stat.SPD) > playerActivePokemon[1].getStat(Stat.SPD)
|
|
||||||
? playerActivePokemon[0]
|
|
||||||
: playerActivePokemon[1];
|
|
||||||
// check if either active pokemon has the ability "Run Away"
|
|
||||||
const hasRunAway = playerActivePokemon.find(p => p.hasAbility(AbilityId.RUN_AWAY));
|
|
||||||
runningPokemon = hasRunAway !== undefined ? hasRunAway : fasterPokemon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
phaseManager.unshiftNew("AttemptRunPhase", runningPokemon.getFieldIndex());
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
|
@ -6,6 +6,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, expect, it, vi } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
|
import Overrides from "#app/overrides";
|
||||||
|
|
||||||
describe("Abilities - Honey Gather", () => {
|
describe("Abilities - Honey Gather", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -63,6 +64,8 @@ describe("Abilities - Honey Gather", () => {
|
|||||||
// something weird is going on with the test framework, so this is required to prevent a crash
|
// something weird is going on with the test framework, so this is required to prevent a crash
|
||||||
const enemy = game.scene.getEnemyPokemon()!;
|
const enemy = game.scene.getEnemyPokemon()!;
|
||||||
vi.spyOn(enemy, "scene", "get").mockReturnValue(game.scene);
|
vi.spyOn(enemy, "scene", "get").mockReturnValue(game.scene);
|
||||||
|
// Expects next wave so run must succeed
|
||||||
|
vi.spyOn(Overrides, "RUN_SUCCESS_OVERRIDE", "get").mockReturnValue(true);
|
||||||
|
|
||||||
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);
|
||||||
|
@ -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);
|
||||||
|
@ -4,10 +4,11 @@ import { MoveId } from "#enums/move-id";
|
|||||||
import { SpeciesId } from "#enums/species-id";
|
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, expect, it } from "vitest";
|
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
import type { CommandPhase } from "#app/phases/command-phase";
|
import type { CommandPhase } from "#app/phases/command-phase";
|
||||||
import { Command } from "#enums/command";
|
import { Command } from "#enums/command";
|
||||||
import { AttemptRunPhase } from "#app/phases/attempt-run-phase";
|
import { AttemptRunPhase } from "#app/phases/attempt-run-phase";
|
||||||
|
import Overrides from "#app/overrides";
|
||||||
|
|
||||||
describe("Abilities - Speed Boost", () => {
|
describe("Abilities - Speed Boost", () => {
|
||||||
let phaserGame: Phaser.Game;
|
let phaserGame: Phaser.Game;
|
||||||
@ -96,12 +97,15 @@ describe("Abilities - Speed Boost", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("should not trigger if pokemon fails to escape", async () => {
|
it("should not trigger if pokemon fails to escape", async () => {
|
||||||
|
//Account for doubles, should not trigger on either pokemon
|
||||||
|
game.override.battleStyle("double");
|
||||||
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
await game.classicMode.startBattle([SpeciesId.SHUCKLE]);
|
||||||
|
|
||||||
|
vi.spyOn(Overrides, "RUN_SUCCESS_OVERRIDE", "get").mockReturnValue(false);
|
||||||
|
|
||||||
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);
|
||||||
const runPhase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
|
||||||
runPhase.forceFailEscape = true;
|
|
||||||
await game.phaseInterceptor.to(AttemptRunPhase);
|
await game.phaseInterceptor.to(AttemptRunPhase);
|
||||||
await game.toNextTurn();
|
await game.toNextTurn();
|
||||||
|
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
import { AttemptRunPhase } from "#app/phases/attempt-run-phase";
|
import { AttemptRunPhase } from "#app/phases/attempt-run-phase";
|
||||||
import type { CommandPhase } from "#app/phases/command-phase";
|
import type { CommandPhase } from "#app/phases/command-phase";
|
||||||
import { Command } from "#enums/command";
|
import { Command } from "#enums/command";
|
||||||
import { NumberHolder } from "#app/utils/common";
|
|
||||||
import { AbilityId } from "#enums/ability-id";
|
import { AbilityId } from "#enums/ability-id";
|
||||||
import { SpeciesId } from "#enums/species-id";
|
import { SpeciesId } from "#enums/species-id";
|
||||||
import GameManager from "#test/testUtils/gameManager";
|
import GameManager from "#test/testUtils/gameManager";
|
||||||
@ -45,8 +44,6 @@ describe("Escape chance calculations", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
||||||
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
||||||
const escapePercentage = new NumberHolder(0);
|
|
||||||
|
|
||||||
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
||||||
const escapeChances: {
|
const escapeChances: {
|
||||||
pokemonSpeedRatio: number;
|
pokemonSpeedRatio: number;
|
||||||
@ -91,8 +88,8 @@ describe("Escape chance calculations", () => {
|
|||||||
20,
|
20,
|
||||||
escapeChances[i].pokemonSpeedRatio * enemySpeed,
|
escapeChances[i].pokemonSpeedRatio * enemySpeed,
|
||||||
]);
|
]);
|
||||||
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
const chance = phase.calculateEscapeChance(game.scene.currentBattle.escapeAttempts);
|
||||||
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
expect(chance).toBe(escapeChances[i].expectedEscapeChance);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -118,8 +115,6 @@ describe("Escape chance calculations", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
||||||
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
||||||
const escapePercentage = new NumberHolder(0);
|
|
||||||
|
|
||||||
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
||||||
const escapeChances: {
|
const escapeChances: {
|
||||||
pokemonSpeedRatio: number;
|
pokemonSpeedRatio: number;
|
||||||
@ -172,9 +167,9 @@ describe("Escape chance calculations", () => {
|
|||||||
20,
|
20,
|
||||||
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5],
|
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5],
|
||||||
]);
|
]);
|
||||||
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
const chance = phase.calculateEscapeChance(game.scene.currentBattle.escapeAttempts);
|
||||||
// checks to make sure the escape values are the same
|
// checks to make sure the escape values are the same
|
||||||
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
expect(chance).toBe(escapeChances[i].expectedEscapeChance);
|
||||||
// checks to make sure the sum of the player's speed for all pokemon is equal to the appropriate ratio of the total enemy speed
|
// checks to make sure the sum of the player's speed for all pokemon is equal to the appropriate ratio of the total enemy speed
|
||||||
expect(playerPokemon[0].stats[5] + playerPokemon[1].stats[5]).toBe(
|
expect(playerPokemon[0].stats[5] + playerPokemon[1].stats[5]).toBe(
|
||||||
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
||||||
@ -197,7 +192,6 @@ describe("Escape chance calculations", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
||||||
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
||||||
const escapePercentage = new NumberHolder(0);
|
|
||||||
|
|
||||||
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
||||||
const escapeChances: {
|
const escapeChances: {
|
||||||
@ -256,8 +250,8 @@ describe("Escape chance calculations", () => {
|
|||||||
20,
|
20,
|
||||||
escapeChances[i].pokemonSpeedRatio * enemySpeed,
|
escapeChances[i].pokemonSpeedRatio * enemySpeed,
|
||||||
]);
|
]);
|
||||||
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
const chance = phase.calculateEscapeChance(game.scene.currentBattle.escapeAttempts);
|
||||||
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
expect(chance).toBe(escapeChances[i].expectedEscapeChance);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -283,7 +277,6 @@ describe("Escape chance calculations", () => {
|
|||||||
|
|
||||||
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
await game.phaseInterceptor.to(AttemptRunPhase, false);
|
||||||
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
const phase = game.scene.phaseManager.getCurrentPhase() as AttemptRunPhase;
|
||||||
const escapePercentage = new NumberHolder(0);
|
|
||||||
|
|
||||||
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
// this sets up an object for multiple attempts. The pokemonSpeedRatio is your speed divided by the enemy speed, the escapeAttempts are the number of escape attempts and the expectedEscapeChance is the chance it should be escaping
|
||||||
const escapeChances: {
|
const escapeChances: {
|
||||||
@ -349,9 +342,9 @@ describe("Escape chance calculations", () => {
|
|||||||
20,
|
20,
|
||||||
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5],
|
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed - playerPokemon[0].stats[5],
|
||||||
]);
|
]);
|
||||||
phase.attemptRunAway(playerPokemon, enemyField, escapePercentage);
|
const chance = phase.calculateEscapeChance(game.scene.currentBattle.escapeAttempts);
|
||||||
// checks to make sure the escape values are the same
|
// checks to make sure the escape values are the same
|
||||||
expect(escapePercentage.value).toBe(escapeChances[i].expectedEscapeChance);
|
expect(chance).toBe(escapeChances[i].expectedEscapeChance);
|
||||||
// checks to make sure the sum of the player's speed for all pokemon is equal to the appropriate ratio of the total enemy speed
|
// checks to make sure the sum of the player's speed for all pokemon is equal to the appropriate ratio of the total enemy speed
|
||||||
expect(playerPokemon[0].stats[5] + playerPokemon[1].stats[5]).toBe(
|
expect(playerPokemon[0].stats[5] + playerPokemon[1].stats[5]).toBe(
|
||||||
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
escapeChances[i].pokemonSpeedRatio * totalEnemySpeed,
|
||||||
|
Loading…
Reference in New Issue
Block a user