[Test] Add `STATUS_ACTIVATION_OVERRIDE` to `overrides.ts` (#4689)

This applies to Paralysis and Freeze

Added Paralysis test to demonstrate usage

- Consolidate `this.cancel()` calls
This commit is contained in:
NightKev 2024-10-22 20:11:02 -07:00 committed by GitHub
parent 0fe57b44b5
commit 1ad4f3b376
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 203 additions and 128 deletions

View File

@ -75,6 +75,8 @@ class DefaultOverrides {
readonly ITEM_UNLOCK_OVERRIDE: Unlockables[] = []; readonly ITEM_UNLOCK_OVERRIDE: Unlockables[] = [];
/** Set to `true` to show all tutorials */ /** Set to `true` to show all tutorials */
readonly BYPASS_TUTORIAL_SKIP_OVERRIDE: boolean = false; readonly BYPASS_TUTORIAL_SKIP_OVERRIDE: boolean = false;
/** Set to `true` to force Paralysis and Freeze to always activate, or `false` to force them to not activate */
readonly STATUS_ACTIVATION_OVERRIDE: boolean | null = null;
// ---------------- // ----------------
// PLAYER OVERRIDES // PLAYER OVERRIDES

View File

@ -11,6 +11,7 @@ import { getTerrainBlockMessage } from "#app/data/weather";
import { MoveUsedEvent } from "#app/events/battle-scene"; import { MoveUsedEvent } from "#app/events/battle-scene";
import Pokemon, { MoveResult, PokemonMove, TurnMove } from "#app/field/pokemon"; import Pokemon, { MoveResult, PokemonMove, TurnMove } from "#app/field/pokemon";
import { getPokemonNameWithAffix } from "#app/messages"; import { getPokemonNameWithAffix } from "#app/messages";
import Overrides from "#app/overrides";
import { BattlePhase } from "#app/phases/battle-phase"; import { BattlePhase } from "#app/phases/battle-phase";
import { CommonAnimPhase } from "#app/phases/common-anim-phase"; import { CommonAnimPhase } from "#app/phases/common-anim-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase";
@ -168,10 +169,7 @@ export class MovePhase extends BattlePhase {
switch (this.pokemon.status.effect) { switch (this.pokemon.status.effect) {
case StatusEffect.PARALYSIS: case StatusEffect.PARALYSIS:
if (!this.pokemon.randSeedInt(4)) { activated = (!this.pokemon.randSeedInt(4) || Overrides.STATUS_ACTIVATION_OVERRIDE === true) && Overrides.STATUS_ACTIVATION_OVERRIDE !== false;
activated = true;
this.cancelled = true;
}
break; break;
case StatusEffect.SLEEP: case StatusEffect.SLEEP:
applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove()); applyMoveAttrs(BypassSleepAttr, this.pokemon, null, this.move.getMove());
@ -180,16 +178,22 @@ export class MovePhase extends BattlePhase {
this.pokemon.status.sleepTurnsRemaining = turnsRemaining.value; this.pokemon.status.sleepTurnsRemaining = turnsRemaining.value;
healed = this.pokemon.status.sleepTurnsRemaining <= 0; healed = this.pokemon.status.sleepTurnsRemaining <= 0;
activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP); activated = !healed && !this.pokemon.getTag(BattlerTagType.BYPASS_SLEEP);
this.cancelled = activated;
break; break;
case StatusEffect.FREEZE: case StatusEffect.FREEZE:
healed = !!this.move.getMove().findAttr(attr => attr instanceof HealStatusEffectAttr && attr.selfTarget && attr.isOfEffect(StatusEffect.FREEZE)) || !this.pokemon.randSeedInt(5); healed =
!!this.move.getMove().findAttr((attr) =>
attr instanceof HealStatusEffectAttr
&& attr.selfTarget
&& attr.isOfEffect(StatusEffect.FREEZE))
|| (!this.pokemon.randSeedInt(5) && Overrides.STATUS_ACTIVATION_OVERRIDE !== true)
|| Overrides.STATUS_ACTIVATION_OVERRIDE === false;
activated = !healed; activated = !healed;
this.cancelled = activated;
break; break;
} }
if (activated) { if (activated) {
this.cancel();
this.scene.queueMessage(getStatusEffectActivationText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon))); this.scene.queueMessage(getStatusEffectActivationText(this.pokemon.status.effect, getPokemonNameWithAffix(this.pokemon)));
this.scene.unshiftPhase(new CommonAnimPhase(this.scene, this.pokemon.getBattlerIndex(), undefined, CommonAnim.POISON + (this.pokemon.status.effect - 1))); this.scene.unshiftPhase(new CommonAnimPhase(this.scene, this.pokemon.getBattlerIndex(), undefined, CommonAnim.POISON + (this.pokemon.status.effect - 1)));
} else if (healed) { } else if (healed) {

View File

@ -8,10 +8,10 @@ import {
getStatusEffectOverlapText, getStatusEffectOverlapText,
} from "#app/data/status-effect"; } from "#app/data/status-effect";
import { MoveResult } from "#app/field/pokemon"; import { MoveResult } from "#app/field/pokemon";
import GameManager from "#app/test/utils/gameManager";
import { Abilities } from "#enums/abilities"; import { Abilities } from "#enums/abilities";
import { Moves } from "#enums/moves"; import { Moves } from "#enums/moves";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import GameManager from "#test/utils/gameManager";
import { mockI18next } from "#test/utils/testUtils"; import { mockI18next } from "#test/utils/testUtils";
import i18next from "i18next"; import i18next from "i18next";
import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; import { afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest";
@ -306,58 +306,98 @@ describe("Status Effect Messages", () => {
}); });
}); });
describe("Status Effects - Sleep", () => { describe("Status Effects", () => {
let phaserGame: Phaser.Game; describe("Paralysis", () => {
let game: GameManager; let phaserGame: Phaser.Game;
let game: GameManager;
beforeAll(() => { beforeAll(() => {
phaserGame = new Phaser.Game({ phaserGame = new Phaser.Game({
type: Phaser.HEADLESS, type: Phaser.HEADLESS,
});
});
afterEach(() => {
game.phaseInterceptor.restoreOg();
});
beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.enemySpecies(Species.MAGIKARP)
.enemyMoveset(Moves.SPLASH)
.enemyAbility(Abilities.BALL_FETCH)
.moveset([ Moves.QUICK_ATTACK ])
.ability(Abilities.BALL_FETCH)
.statusEffect(StatusEffect.PARALYSIS);
});
it("causes the pokemon's move to fail when activated", async () => {
await game.classicMode.startBattle([ Species.FEEBAS ]);
game.move.select(Moves.QUICK_ATTACK);
await game.move.forceStatusActivation(true);
await game.toNextTurn();
expect(game.scene.getEnemyPokemon()!.isFullHp()).toBe(true);
expect(game.scene.getPlayerPokemon()!.getLastXMoves(1)[0].result).toBe(MoveResult.FAIL);
}); });
}); });
afterEach(() => { describe("Sleep", () => {
game.phaseInterceptor.restoreOg(); let phaserGame: Phaser.Game;
}); let game: GameManager;
beforeEach(() => { beforeAll(() => {
game = new GameManager(phaserGame); phaserGame = new Phaser.Game({
game.override type: Phaser.HEADLESS,
.moveset([ Moves.SPLASH ]) });
.ability(Abilities.BALL_FETCH) });
.battleType("single")
.disableCrits()
.enemySpecies(Species.MAGIKARP)
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.SPLASH);
});
it("should last the appropriate number of turns", async () => { afterEach(() => {
await game.classicMode.startBattle([ Species.FEEBAS ]); game.phaseInterceptor.restoreOg();
});
const player = game.scene.getPlayerPokemon()!; beforeEach(() => {
player.status = new Status(StatusEffect.SLEEP, 0, 4); game = new GameManager(phaserGame);
game.override
.moveset([ Moves.SPLASH ])
.ability(Abilities.BALL_FETCH)
.battleType("single")
.disableCrits()
.enemySpecies(Species.MAGIKARP)
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.SPLASH);
});
game.move.select(Moves.SPLASH); it("should last the appropriate number of turns", async () => {
await game.toNextTurn(); await game.classicMode.startBattle([ Species.FEEBAS ]);
expect(player.status.effect).toBe(StatusEffect.SLEEP); const player = game.scene.getPlayerPokemon()!;
player.status = new Status(StatusEffect.SLEEP, 0, 4);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(player.status.effect).toBe(StatusEffect.SLEEP); expect(player.status.effect).toBe(StatusEffect.SLEEP);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(player.status.effect).toBe(StatusEffect.SLEEP); expect(player.status.effect).toBe(StatusEffect.SLEEP);
expect(player.getLastXMoves(1)[0].result).toBe(MoveResult.FAIL);
game.move.select(Moves.SPLASH); game.move.select(Moves.SPLASH);
await game.toNextTurn(); await game.toNextTurn();
expect(player.status?.effect).toBeUndefined(); expect(player.status.effect).toBe(StatusEffect.SLEEP);
expect(player.getLastXMoves(1)[0].result).toBe(MoveResult.SUCCESS); expect(player.getLastXMoves(1)[0].result).toBe(MoveResult.FAIL);
game.move.select(Moves.SPLASH);
await game.toNextTurn();
expect(player.status?.effect).toBeUndefined();
expect(player.getLastXMoves(1)[0].result).toBe(MoveResult.SUCCESS);
});
}); });
}); });

View File

@ -1,12 +1,13 @@
import { BattlerIndex } from "#app/battle"; import { BattlerIndex } from "#app/battle";
import { Moves } from "#app/enums/moves"; import Overrides from "#app/overrides";
import { CommandPhase } from "#app/phases/command-phase"; import { CommandPhase } from "#app/phases/command-phase";
import { MoveEffectPhase } from "#app/phases/move-effect-phase"; import { MoveEffectPhase } from "#app/phases/move-effect-phase";
import { Command } from "#app/ui/command-ui-handler"; import { Command } from "#app/ui/command-ui-handler";
import { Mode } from "#app/ui/ui"; import { Mode } from "#app/ui/ui";
import { Moves } from "#enums/moves";
import { getMovePosition } from "#test/utils/gameManagerUtils";
import { GameManagerHelper } from "#test/utils/helpers/gameManagerHelper";
import { vi } from "vitest"; import { vi } from "vitest";
import { getMovePosition } from "../gameManagerUtils";
import { GameManagerHelper } from "./gameManagerHelper";
/** /**
* Helper to handle a Pokemon's move * Helper to handle a Pokemon's move
@ -17,7 +18,7 @@ export class MoveHelper extends GameManagerHelper {
* {@linkcode MoveEffectPhase.hitCheck | hitCheck}'s return value to `true`. * {@linkcode MoveEffectPhase.hitCheck | hitCheck}'s return value to `true`.
* Used to force a move to hit. * Used to force a move to hit.
*/ */
async forceHit(): Promise<void> { public async forceHit(): Promise<void> {
await this.game.phaseInterceptor.to(MoveEffectPhase, false); await this.game.phaseInterceptor.to(MoveEffectPhase, false);
vi.spyOn(this.game.scene.getCurrentPhase() as MoveEffectPhase, "hitCheck").mockReturnValue(true); vi.spyOn(this.game.scene.getCurrentPhase() as MoveEffectPhase, "hitCheck").mockReturnValue(true);
} }
@ -26,9 +27,9 @@ export class MoveHelper extends GameManagerHelper {
* Intercepts {@linkcode MoveEffectPhase} and mocks the * Intercepts {@linkcode MoveEffectPhase} and mocks the
* {@linkcode MoveEffectPhase.hitCheck | hitCheck}'s return value to `false`. * {@linkcode MoveEffectPhase.hitCheck | hitCheck}'s return value to `false`.
* Used to force a move to miss. * Used to force a move to miss.
* @param firstTargetOnly Whether the move should force miss on the first target only, in the case of multi-target moves. * @param firstTargetOnly - Whether the move should force miss on the first target only, in the case of multi-target moves.
*/ */
async forceMiss(firstTargetOnly: boolean = false): Promise<void> { public async forceMiss(firstTargetOnly: boolean = false): Promise<void> {
await this.game.phaseInterceptor.to(MoveEffectPhase, false); await this.game.phaseInterceptor.to(MoveEffectPhase, false);
const hitCheck = vi.spyOn(this.game.scene.getCurrentPhase() as MoveEffectPhase, "hitCheck"); const hitCheck = vi.spyOn(this.game.scene.getCurrentPhase() as MoveEffectPhase, "hitCheck");
@ -40,12 +41,12 @@ export class MoveHelper extends GameManagerHelper {
} }
/** /**
* Select the move to be used by the given Pokemon(-index). Triggers during the next {@linkcode CommandPhase} * Select the move to be used by the given Pokemon(-index). Triggers during the next {@linkcode CommandPhase}
* @param move the move to use * @param move - the move to use
* @param pkmIndex the pokemon index. Relevant for double-battles only (defaults to 0) * @param pkmIndex - the pokemon index. Relevant for double-battles only (defaults to 0)
* @param targetIndex The {@linkcode BattlerIndex} of the Pokemon to target for single-target moves, or `null` if a manual call to `selectTarget()` is required * @param targetIndex - The {@linkcode BattlerIndex} of the Pokemon to target for single-target moves, or `null` if a manual call to `selectTarget()` is required
*/ */
select(move: Moves, pkmIndex: 0 | 1 = 0, targetIndex?: BattlerIndex | null) { public select(move: Moves, pkmIndex: 0 | 1 = 0, targetIndex?: BattlerIndex | null) {
const movePosition = getMovePosition(this.game.scene, pkmIndex, move); const movePosition = getMovePosition(this.game.scene, pkmIndex, move);
this.game.onNextPrompt("CommandPhase", Mode.COMMAND, () => { this.game.onNextPrompt("CommandPhase", Mode.COMMAND, () => {
@ -59,4 +60,15 @@ export class MoveHelper extends GameManagerHelper {
this.game.selectTarget(movePosition, targetIndex); this.game.selectTarget(movePosition, targetIndex);
} }
} }
/**
* Forces the Paralysis or Freeze status to activate on the next move by temporarily mocking {@linkcode Overrides.STATUS_ACTIVATION_OVERRIDE},
* advancing to the next `MovePhase`, and then resetting the override to `null`
* @param activated - `true` to force the status to activate, `false` to force the status to not activate (will cause Freeze to heal)
*/
public async forceStatusActivation(activated: boolean): Promise<void> {
vi.spyOn(Overrides, "STATUS_ACTIVATION_OVERRIDE", "get").mockReturnValue(activated);
await this.game.phaseInterceptor.to("MovePhase");
vi.spyOn(Overrides, "STATUS_ACTIVATION_OVERRIDE", "get").mockReturnValue(null);
}
} }

View File

@ -29,7 +29,7 @@ export class OverridesHelper extends GameManagerHelper {
* @warning Any event listeners that are attached to [NewArenaEvent](events\battle-scene.ts) may need to be handled down the line * @warning Any event listeners that are attached to [NewArenaEvent](events\battle-scene.ts) may need to be handled down the line
* @param biome the biome to set * @param biome the biome to set
*/ */
startingBiome(biome: Biome): this { public startingBiome(biome: Biome): this {
this.game.scene.newArena(biome); this.game.scene.newArena(biome);
this.log(`Starting biome set to ${Biome[biome]} (=${biome})!`); this.log(`Starting biome set to ${Biome[biome]} (=${biome})!`);
return this; return this;
@ -38,9 +38,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the starting wave (index) * Override the starting wave (index)
* @param wave the wave (index) to set. Classic: `1`-`200` * @param wave the wave (index) to set. Classic: `1`-`200`
* @returns this * @returns `this`
*/ */
startingWave(wave: number): this { public startingWave(wave: number): this {
vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(wave); vi.spyOn(Overrides, "STARTING_WAVE_OVERRIDE", "get").mockReturnValue(wave);
this.log(`Starting wave set to ${wave}!`); this.log(`Starting wave set to ${wave}!`);
return this; return this;
@ -49,9 +49,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) starting level * Override the player (pokemon) starting level
* @param level the (pokemon) level to set * @param level the (pokemon) level to set
* @returns this * @returns `this`
*/ */
startingLevel(level: Species | number): this { public startingLevel(level: Species | number): this {
vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(level); vi.spyOn(Overrides, "STARTING_LEVEL_OVERRIDE", "get").mockReturnValue(level);
this.log(`Player Pokemon starting level set to ${level}!`); this.log(`Player Pokemon starting level set to ${level}!`);
return this; return this;
@ -62,7 +62,7 @@ export class OverridesHelper extends GameManagerHelper {
* @param value the XP multiplier to set * @param value the XP multiplier to set
* @returns `this` * @returns `this`
*/ */
xpMultiplier(value: number): this { public xpMultiplier(value: number): this {
vi.spyOn(Overrides, "XP_MULTIPLIER_OVERRIDE", "get").mockReturnValue(value); vi.spyOn(Overrides, "XP_MULTIPLIER_OVERRIDE", "get").mockReturnValue(value);
this.log(`XP Multiplier set to ${value}!`); this.log(`XP Multiplier set to ${value}!`);
return this; return this;
@ -71,9 +71,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) starting held items * Override the player (pokemon) starting held items
* @param items the items to hold * @param items the items to hold
* @returns this * @returns `this`
*/ */
startingHeldItems(items: ModifierOverride[]) { public startingHeldItems(items: ModifierOverride[]): this {
vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue(items); vi.spyOn(Overrides, "STARTING_HELD_ITEMS_OVERRIDE", "get").mockReturnValue(items);
this.log("Player Pokemon starting held items set to:", items); this.log("Player Pokemon starting held items set to:", items);
return this; return this;
@ -82,9 +82,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) {@linkcode Species | species} * Override the player (pokemon) {@linkcode Species | species}
* @param species the (pokemon) {@linkcode Species | species} to set * @param species the (pokemon) {@linkcode Species | species} to set
* @returns this * @returns `this`
*/ */
starterSpecies(species: Species | number): this { public starterSpecies(species: Species | number): this {
vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(species); vi.spyOn(Overrides, "STARTER_SPECIES_OVERRIDE", "get").mockReturnValue(species);
this.log(`Player Pokemon species set to ${Species[species]} (=${species})!`); this.log(`Player Pokemon species set to ${Species[species]} (=${species})!`);
return this; return this;
@ -92,9 +92,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) to be a random fusion * Override the player (pokemon) to be a random fusion
* @returns this * @returns `this`
*/ */
enableStarterFusion(): this { public enableStarterFusion(): this {
vi.spyOn(Overrides, "STARTER_FUSION_OVERRIDE", "get").mockReturnValue(true); vi.spyOn(Overrides, "STARTER_FUSION_OVERRIDE", "get").mockReturnValue(true);
this.log("Player Pokemon is a random fusion!"); this.log("Player Pokemon is a random fusion!");
return this; return this;
@ -103,9 +103,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) fusion species * Override the player (pokemon) fusion species
* @param species the fusion species to set * @param species the fusion species to set
* @returns this * @returns `this`
*/ */
starterFusionSpecies(species: Species | number): this { public starterFusionSpecies(species: Species | number): this {
vi.spyOn(Overrides, "STARTER_FUSION_SPECIES_OVERRIDE", "get").mockReturnValue(species); vi.spyOn(Overrides, "STARTER_FUSION_SPECIES_OVERRIDE", "get").mockReturnValue(species);
this.log(`Player Pokemon fusion species set to ${Species[species]} (=${species})!`); this.log(`Player Pokemon fusion species set to ${Species[species]} (=${species})!`);
return this; return this;
@ -114,9 +114,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemons) forms * Override the player (pokemons) forms
* @param forms the (pokemon) forms to set * @param forms the (pokemon) forms to set
* @returns this * @returns `this`
*/ */
starterForms(forms: Partial<Record<Species, number>>): this { public starterForms(forms: Partial<Record<Species, number>>): this {
vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue(forms); vi.spyOn(Overrides, "STARTER_FORM_OVERRIDES", "get").mockReturnValue(forms);
const formsStr = Object.entries(forms) const formsStr = Object.entries(forms)
.map(([ speciesId, formIndex ]) => `${Species[speciesId]}=${formIndex}`) .map(([ speciesId, formIndex ]) => `${Species[speciesId]}=${formIndex}`)
@ -128,9 +128,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player's starting modifiers * Override the player's starting modifiers
* @param modifiers the modifiers to set * @param modifiers the modifiers to set
* @returns this * @returns `this`
*/ */
startingModifier(modifiers: ModifierOverride[]): this { public startingModifier(modifiers: ModifierOverride[]): this {
vi.spyOn(Overrides, "STARTING_MODIFIER_OVERRIDE", "get").mockReturnValue(modifiers); vi.spyOn(Overrides, "STARTING_MODIFIER_OVERRIDE", "get").mockReturnValue(modifiers);
this.log(`Player starting modifiers set to: ${modifiers}`); this.log(`Player starting modifiers set to: ${modifiers}`);
return this; return this;
@ -139,9 +139,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) {@linkcode Abilities | ability} * Override the player (pokemon) {@linkcode Abilities | ability}
* @param ability the (pokemon) {@linkcode Abilities | ability} to set * @param ability the (pokemon) {@linkcode Abilities | ability} to set
* @returns this * @returns `this`
*/ */
ability(ability: Abilities): this { public ability(ability: Abilities): this {
vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); vi.spyOn(Overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability);
this.log(`Player Pokemon ability set to ${Abilities[ability]} (=${ability})!`); this.log(`Player Pokemon ability set to ${Abilities[ability]} (=${ability})!`);
return this; return this;
@ -150,9 +150,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) **passive** {@linkcode Abilities | ability} * Override the player (pokemon) **passive** {@linkcode Abilities | ability}
* @param passiveAbility the (pokemon) **passive** {@linkcode Abilities | ability} to set * @param passiveAbility the (pokemon) **passive** {@linkcode Abilities | ability} to set
* @returns this * @returns `this`
*/ */
passiveAbility(passiveAbility: Abilities): this { public passiveAbility(passiveAbility: Abilities): this {
vi.spyOn(Overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(passiveAbility); vi.spyOn(Overrides, "PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(passiveAbility);
this.log(`Player Pokemon PASSIVE ability set to ${Abilities[passiveAbility]} (=${passiveAbility})!`); this.log(`Player Pokemon PASSIVE ability set to ${Abilities[passiveAbility]} (=${passiveAbility})!`);
return this; return this;
@ -161,9 +161,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the player (pokemon) {@linkcode Moves | moves}set * Override the player (pokemon) {@linkcode Moves | moves}set
* @param moveset the {@linkcode Moves | moves}set to set * @param moveset the {@linkcode Moves | moves}set to set
* @returns this * @returns `this`
*/ */
moveset(moveset: Moves | Moves[]): this { public moveset(moveset: Moves | Moves[]): this {
vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(moveset); vi.spyOn(Overrides, "MOVESET_OVERRIDE", "get").mockReturnValue(moveset);
if (!Array.isArray(moveset)) { if (!Array.isArray(moveset)) {
moveset = [ moveset ]; moveset = [ moveset ];
@ -178,7 +178,7 @@ export class OverridesHelper extends GameManagerHelper {
* @param statusEffect the {@linkcode StatusEffect | status-effect} to set * @param statusEffect the {@linkcode StatusEffect | status-effect} to set
* @returns * @returns
*/ */
statusEffect(statusEffect: StatusEffect): this { public statusEffect(statusEffect: StatusEffect): this {
vi.spyOn(Overrides, "STATUS_OVERRIDE", "get").mockReturnValue(statusEffect); vi.spyOn(Overrides, "STATUS_OVERRIDE", "get").mockReturnValue(statusEffect);
this.log(`Player Pokemon status-effect set to ${StatusEffect[statusEffect]} (=${statusEffect})!`); this.log(`Player Pokemon status-effect set to ${StatusEffect[statusEffect]} (=${statusEffect})!`);
return this; return this;
@ -186,9 +186,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override each wave to not have standard trainer battles * Override each wave to not have standard trainer battles
* @returns this * @returns `this`
*/ */
disableTrainerWaves(): this { public disableTrainerWaves(): this {
const realFn = getGameMode; const realFn = getGameMode;
vi.spyOn(GameMode, "getGameMode").mockImplementation((gameMode: GameModes) => { vi.spyOn(GameMode, "getGameMode").mockImplementation((gameMode: GameModes) => {
const mode = realFn(gameMode); const mode = realFn(gameMode);
@ -201,9 +201,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override each wave to not have critical hits * Override each wave to not have critical hits
* @returns this * @returns `this`
*/ */
disableCrits() { public disableCrits(): this {
vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); vi.spyOn(Overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true);
this.log("Critical hits are disabled!"); this.log("Critical hits are disabled!");
return this; return this;
@ -212,9 +212,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the {@linkcode WeatherType | weather (type)} * Override the {@linkcode WeatherType | weather (type)}
* @param type {@linkcode WeatherType | weather type} to set * @param type {@linkcode WeatherType | weather type} to set
* @returns this * @returns `this`
*/ */
weather(type: WeatherType): this { public weather(type: WeatherType): this {
vi.spyOn(Overrides, "WEATHER_OVERRIDE", "get").mockReturnValue(type); vi.spyOn(Overrides, "WEATHER_OVERRIDE", "get").mockReturnValue(type);
this.log(`Weather set to ${Weather[type]} (=${type})!`); this.log(`Weather set to ${Weather[type]} (=${type})!`);
return this; return this;
@ -223,9 +223,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the seed * Override the seed
* @param seed the seed to set * @param seed the seed to set
* @returns this * @returns `this`
*/ */
seed(seed: string): this { public seed(seed: string): this {
vi.spyOn(this.game.scene, "resetSeed").mockImplementation(() => { vi.spyOn(this.game.scene, "resetSeed").mockImplementation(() => {
this.game.scene.waveSeed = seed; this.game.scene.waveSeed = seed;
Phaser.Math.RND.sow([ seed ]); Phaser.Math.RND.sow([ seed ]);
@ -239,9 +239,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the battle type (single or double) * Override the battle type (single or double)
* @param battleType battle type to set * @param battleType battle type to set
* @returns this * @returns `this`
*/ */
battleType(battleType: "single" | "double" | null): this { public battleType(battleType: "single" | "double" | null): this {
vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue(battleType); vi.spyOn(Overrides, "BATTLE_TYPE_OVERRIDE", "get").mockReturnValue(battleType);
this.log(`Battle type set to ${battleType} only!`); this.log(`Battle type set to ${battleType} only!`);
return this; return this;
@ -250,9 +250,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) {@linkcode Species | species} * Override the enemy (pokemon) {@linkcode Species | species}
* @param species the (pokemon) {@linkcode Species | species} to set * @param species the (pokemon) {@linkcode Species | species} to set
* @returns this * @returns `this`
*/ */
enemySpecies(species: Species | number): this { public enemySpecies(species: Species | number): this {
vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(species); vi.spyOn(Overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(species);
this.log(`Enemy Pokemon species set to ${Species[species]} (=${species})!`); this.log(`Enemy Pokemon species set to ${Species[species]} (=${species})!`);
return this; return this;
@ -260,9 +260,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) to be a random fusion * Override the enemy (pokemon) to be a random fusion
* @returns this * @returns `this`
*/ */
enableEnemyFusion(): this { public enableEnemyFusion(): this {
vi.spyOn(Overrides, "OPP_FUSION_OVERRIDE", "get").mockReturnValue(true); vi.spyOn(Overrides, "OPP_FUSION_OVERRIDE", "get").mockReturnValue(true);
this.log("Enemy Pokemon is a random fusion!"); this.log("Enemy Pokemon is a random fusion!");
return this; return this;
@ -271,9 +271,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) fusion species * Override the enemy (pokemon) fusion species
* @param species the fusion species to set * @param species the fusion species to set
* @returns this * @returns `this`
*/ */
enemyFusionSpecies(species: Species | number): this { public enemyFusionSpecies(species: Species | number): this {
vi.spyOn(Overrides, "OPP_FUSION_SPECIES_OVERRIDE", "get").mockReturnValue(species); vi.spyOn(Overrides, "OPP_FUSION_SPECIES_OVERRIDE", "get").mockReturnValue(species);
this.log(`Enemy Pokemon fusion species set to ${Species[species]} (=${species})!`); this.log(`Enemy Pokemon fusion species set to ${Species[species]} (=${species})!`);
return this; return this;
@ -282,9 +282,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) {@linkcode Abilities | ability} * Override the enemy (pokemon) {@linkcode Abilities | ability}
* @param ability the (pokemon) {@linkcode Abilities | ability} to set * @param ability the (pokemon) {@linkcode Abilities | ability} to set
* @returns this * @returns `this`
*/ */
enemyAbility(ability: Abilities): this { public enemyAbility(ability: Abilities): this {
vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(ability); vi.spyOn(Overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(ability);
this.log(`Enemy Pokemon ability set to ${Abilities[ability]} (=${ability})!`); this.log(`Enemy Pokemon ability set to ${Abilities[ability]} (=${ability})!`);
return this; return this;
@ -293,9 +293,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) **passive** {@linkcode Abilities | ability} * Override the enemy (pokemon) **passive** {@linkcode Abilities | ability}
* @param passiveAbility the (pokemon) **passive** {@linkcode Abilities | ability} to set * @param passiveAbility the (pokemon) **passive** {@linkcode Abilities | ability} to set
* @returns this * @returns `this`
*/ */
enemyPassiveAbility(passiveAbility: Abilities): this { public enemyPassiveAbility(passiveAbility: Abilities): this {
vi.spyOn(Overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(passiveAbility); vi.spyOn(Overrides, "OPP_PASSIVE_ABILITY_OVERRIDE", "get").mockReturnValue(passiveAbility);
this.log(`Enemy Pokemon PASSIVE ability set to ${Abilities[passiveAbility]} (=${passiveAbility})!`); this.log(`Enemy Pokemon PASSIVE ability set to ${Abilities[passiveAbility]} (=${passiveAbility})!`);
return this; return this;
@ -304,9 +304,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) {@linkcode Moves | moves}set * Override the enemy (pokemon) {@linkcode Moves | moves}set
* @param moveset the {@linkcode Moves | moves}set to set * @param moveset the {@linkcode Moves | moves}set to set
* @returns this * @returns `this`
*/ */
enemyMoveset(moveset: Moves | Moves[]): this { public enemyMoveset(moveset: Moves | Moves[]): this {
vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(moveset); vi.spyOn(Overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue(moveset);
if (!Array.isArray(moveset)) { if (!Array.isArray(moveset)) {
moveset = [ moveset ]; moveset = [ moveset ];
@ -319,9 +319,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) level * Override the enemy (pokemon) level
* @param level the level to set * @param level the level to set
* @returns this * @returns `this`
*/ */
enemyLevel(level: number): this { public enemyLevel(level: number): this {
vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(level); vi.spyOn(Overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(level);
this.log(`Enemy Pokemon level set to ${level}!`); this.log(`Enemy Pokemon level set to ${level}!`);
return this; return this;
@ -332,7 +332,7 @@ export class OverridesHelper extends GameManagerHelper {
* @param statusEffect the {@linkcode StatusEffect | status-effect} to set * @param statusEffect the {@linkcode StatusEffect | status-effect} to set
* @returns * @returns
*/ */
enemyStatusEffect(statusEffect: StatusEffect): this { public enemyStatusEffect(statusEffect: StatusEffect): this {
vi.spyOn(Overrides, "OPP_STATUS_OVERRIDE", "get").mockReturnValue(statusEffect); vi.spyOn(Overrides, "OPP_STATUS_OVERRIDE", "get").mockReturnValue(statusEffect);
this.log(`Enemy Pokemon status-effect set to ${StatusEffect[statusEffect]} (=${statusEffect})!`); this.log(`Enemy Pokemon status-effect set to ${StatusEffect[statusEffect]} (=${statusEffect})!`);
return this; return this;
@ -341,9 +341,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (pokemon) held items * Override the enemy (pokemon) held items
* @param items the items to hold * @param items the items to hold
* @returns this * @returns `this`
*/ */
enemyHeldItems(items: ModifierOverride[]) { public enemyHeldItems(items: ModifierOverride[]): this {
vi.spyOn(Overrides, "OPP_HELD_ITEMS_OVERRIDE", "get").mockReturnValue(items); vi.spyOn(Overrides, "OPP_HELD_ITEMS_OVERRIDE", "get").mockReturnValue(items);
this.log("Enemy Pokemon held items set to:", items); this.log("Enemy Pokemon held items set to:", items);
return this; return this;
@ -354,7 +354,7 @@ export class OverridesHelper extends GameManagerHelper {
* @param unlockable The Unlockable(s) to enable. * @param unlockable The Unlockable(s) to enable.
* @returns `this` * @returns `this`
*/ */
enableUnlockable(unlockable: Unlockables[]) { public enableUnlockable(unlockable: Unlockables[]): this {
vi.spyOn(Overrides, "ITEM_UNLOCK_OVERRIDE", "get").mockReturnValue(unlockable); vi.spyOn(Overrides, "ITEM_UNLOCK_OVERRIDE", "get").mockReturnValue(unlockable);
this.log("Temporarily unlocked the following content: ", unlockable); this.log("Temporarily unlocked the following content: ", unlockable);
return this; return this;
@ -363,9 +363,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the items rolled at the end of a battle * Override the items rolled at the end of a battle
* @param items the items to be rolled * @param items the items to be rolled
* @returns this * @returns `this`
*/ */
itemRewards(items: ModifierOverride[]) { public itemRewards(items: ModifierOverride[]): this {
vi.spyOn(Overrides, "ITEM_REWARD_OVERRIDE", "get").mockReturnValue(items); vi.spyOn(Overrides, "ITEM_REWARD_OVERRIDE", "get").mockReturnValue(items);
this.log("Item rewards set to:", items); this.log("Item rewards set to:", items);
return this; return this;
@ -375,8 +375,9 @@ export class OverridesHelper extends GameManagerHelper {
* Override player shininess * Override player shininess
* @param shininess - `true` or `false` to force the player's pokemon to be shiny or not shiny, * @param shininess - `true` or `false` to force the player's pokemon to be shiny or not shiny,
* `null` to disable the override and re-enable RNG shinies. * `null` to disable the override and re-enable RNG shinies.
* @returns `this`
*/ */
shiny(shininess: boolean | null): this { public shiny(shininess: boolean | null): this {
vi.spyOn(Overrides, "SHINY_OVERRIDE", "get").mockReturnValue(shininess); vi.spyOn(Overrides, "SHINY_OVERRIDE", "get").mockReturnValue(shininess);
if (shininess === null) { if (shininess === null) {
this.log("Disabled player Pokemon shiny override!"); this.log("Disabled player Pokemon shiny override!");
@ -389,8 +390,9 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override player shiny variant * Override player shiny variant
* @param variant - The player's shiny variant. * @param variant - The player's shiny variant.
* @returns `this`
*/ */
shinyVariant(variant: Variant): this { public shinyVariant(variant: Variant): this {
vi.spyOn(Overrides, "VARIANT_OVERRIDE", "get").mockReturnValue(variant); vi.spyOn(Overrides, "VARIANT_OVERRIDE", "get").mockReturnValue(variant);
this.log(`Set player Pokemon's shiny variant to ${variant}!`); this.log(`Set player Pokemon's shiny variant to ${variant}!`);
return this; return this;
@ -420,23 +422,38 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the enemy (Pokemon) to have the given amount of health segments * Override the enemy (Pokemon) to have the given amount of health segments
* @param healthSegments the number of segments to give * @param healthSegments the number of segments to give
* default: 0, the health segments will be handled like in the game based on wave, level and species * - `0` (default): the health segments will be handled like in the game based on wave, level and species
* 1: the Pokemon will not be a boss * - `1`: the Pokemon will not be a boss
* 2+: the Pokemon will be a boss with the given number of health segments * - `2`+: the Pokemon will be a boss with the given number of health segments
* @returns this * @returns `this`
*/ */
enemyHealthSegments(healthSegments: number) { public enemyHealthSegments(healthSegments: number): this {
vi.spyOn(Overrides, "OPP_HEALTH_SEGMENTS_OVERRIDE", "get").mockReturnValue(healthSegments); vi.spyOn(Overrides, "OPP_HEALTH_SEGMENTS_OVERRIDE", "get").mockReturnValue(healthSegments);
this.log("Enemy Pokemon health segments set to:", healthSegments); this.log("Enemy Pokemon health segments set to:", healthSegments);
return this; return this;
} }
/**
* Override statuses (Paralysis and Freeze) to always or never activate
* @param activate - `true` to force activation, `false` to force no activation, `null` to disable the override
* @returns `this`
*/
public statusActivation(activate: boolean | null): this {
vi.spyOn(Overrides, "STATUS_ACTIVATION_OVERRIDE", "get").mockReturnValue(activate);
if (activate !== null) {
this.log(`Paralysis and Freeze forced to ${activate ? "always" : "never"} activate!`);
} else {
this.log("Status activation override disabled!");
}
return this;
}
/** /**
* Override the encounter chance for a mystery encounter. * Override the encounter chance for a mystery encounter.
* @param percentage the encounter chance in % * @param percentage the encounter chance in %
* @returns spy instance * @returns `this`
*/ */
mysteryEncounterChance(percentage: number) { public mysteryEncounterChance(percentage: number): this {
const maxRate: number = 256; // 100% const maxRate: number = 256; // 100%
const rate = maxRate * (percentage / 100); const rate = maxRate * (percentage / 100);
vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_RATE_OVERRIDE", "get").mockReturnValue(rate); vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_RATE_OVERRIDE", "get").mockReturnValue(rate);
@ -446,10 +463,10 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the encounter chance for a mystery encounter. * Override the encounter chance for a mystery encounter.
* @returns spy instance * @param tier - The {@linkcode MysteryEncounterTier} to encounter
* @param tier * @returns `this`
*/ */
mysteryEncounterTier(tier: MysteryEncounterTier) { public mysteryEncounterTier(tier: MysteryEncounterTier): this {
vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_TIER_OVERRIDE", "get").mockReturnValue(tier); vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_TIER_OVERRIDE", "get").mockReturnValue(tier);
this.log(`Mystery encounter tier set to ${tier}!`); this.log(`Mystery encounter tier set to ${tier}!`);
return this; return this;
@ -457,10 +474,10 @@ export class OverridesHelper extends GameManagerHelper {
/** /**
* Override the encounter that spawns for the scene * Override the encounter that spawns for the scene
* @param encounterType * @param encounterType - The {@linkcode MysteryEncounterType} of the encounter
* @returns spy instance * @returns `this`
*/ */
mysteryEncounter(encounterType: MysteryEncounterType) { public mysteryEncounter(encounterType: MysteryEncounterType): this {
vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_OVERRIDE", "get").mockReturnValue(encounterType); vi.spyOn(Overrides, "MYSTERY_ENCOUNTER_OVERRIDE", "get").mockReturnValue(encounterType);
this.log(`Mystery encounter override set to ${encounterType}!`); this.log(`Mystery encounter override set to ${encounterType}!`);
return this; return this;