Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug] Fix moves/abilities which modify abilities #5146

Open
wants to merge 40 commits into
base: beta
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 32 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
7d2cadb
Add setAbility method to pokemon.ts
emdeann Jan 18, 2025
5767c7b
Edit SwitchAbilitiesAttr to use setAbility
emdeann Jan 18, 2025
bdd570e
Change AbilityGiveAttr to use setAbility
emdeann Jan 18, 2025
8fa550b
Rename setAbility to be more accurate
emdeann Jan 18, 2025
9b32659
Fix AbilityCopyAttr
emdeann Jan 18, 2025
9388b5d
Fix AbilityChangeAttr
emdeann Jan 18, 2025
f8689c4
Fix Transform
emdeann Jan 18, 2025
bd53472
Fix imposter
emdeann Jan 18, 2025
e8ea7d0
Fix PostDefendAbilityGiveAbAttr
emdeann Jan 18, 2025
93fd028
Actually fix imposter
emdeann Jan 18, 2025
7634fe5
Actually fix transform
emdeann Jan 18, 2025
936568f
Fix CopyFaintedAllyAbilityAbAttr
emdeann Jan 18, 2025
2a971e7
Fix Trace
emdeann Jan 18, 2025
34d2919
Fix PostDefendAbilitySwapAbAttr
emdeann Jan 18, 2025
4171ecd
Add tests for skill swap
emdeann Jan 18, 2025
fc1f743
Add tests for doodle
emdeann Jan 18, 2025
fa1c937
Add tests for entrainment
emdeann Jan 18, 2025
a43cf92
Add tests for role play
emdeann Jan 18, 2025
5ded51a
Add test for simple beam
emdeann Jan 18, 2025
c1f7b55
Add test for transform
emdeann Jan 18, 2025
0e61801
Add test for imposter
emdeann Jan 18, 2025
3773f7d
Add tests for mummy
emdeann Jan 18, 2025
33deb7f
Add tests for trace
emdeann Jan 18, 2025
dc8ff07
Add tests for wandering spirit
emdeann Jan 18, 2025
0e9af6c
Consider legendary weather when changing ability
emdeann Jan 18, 2025
220d826
Ensure that passives are not (re)applied when main abilities change
emdeann Jan 19, 2025
bf6be8f
Merge branch 'pagefaultgames:beta' into midturnab
emdeann Jan 19, 2025
a7548ab
Merge branch 'beta' into midturnab
damocleas Jan 24, 2025
443c4ca
Merge branch 'beta' into midturnab
damocleas Jan 30, 2025
495e396
Add general ability swap test cases
emdeann Jan 30, 2025
62a797a
Fix test name
emdeann Jan 30, 2025
e90699a
Merge branch 'pagefaultgames:beta' into midturnab
emdeann Feb 4, 2025
af3532c
Add NoMidTurnActivationAttr
emdeann Feb 4, 2025
b68670e
Remove NoMidTurnActivationAttr from illusion
emdeann Feb 4, 2025
58f532f
Remove extraneous call to triggerWeatherBasedFormChanges
emdeann Feb 10, 2025
49669df
Merge branch 'beta' of https://github.com/pagefaultgames/pokerogue in…
emdeann Feb 10, 2025
89a4068
Fix primal weather clearing
emdeann Feb 10, 2025
3f9a3be
Merge branch 'pagefaultgames:beta' into midturnab
emdeann Feb 11, 2025
298afb4
Merge branch 'beta' into midturnab
emdeann Feb 15, 2025
93963aa
Change "MidTurn" to "OnGain"
emdeann Feb 15, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 25 additions & 8 deletions src/data/ability.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1056,9 +1056,9 @@ export class PostDefendAbilitySwapAbAttr extends PostDefendAbAttr {
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon)
&& !attacker.getAbility().hasAttr(UnswappableAbilityAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
if (!simulated) {
const tempAbilityId = attacker.getAbility().id;
attacker.summonData.ability = pokemon.getAbility().id;
pokemon.summonData.ability = tempAbilityId;
const tempAbility = attacker.getAbility();
attacker.setTempAbility(pokemon.getAbility());
pokemon.setTempAbility(tempAbility);
}
return true;
}
Expand All @@ -1083,7 +1083,7 @@ export class PostDefendAbilityGiveAbAttr extends PostDefendAbAttr {
if (move.checkFlag(MoveFlags.MAKES_CONTACT, attacker, pokemon) && !attacker.getAbility().hasAttr(UnsuppressableAbilityAbAttr)
&& !attacker.getAbility().hasAttr(PostDefendAbilityGiveAbAttr) && !move.hitsSubstitute(attacker, pokemon)) {
if (!simulated) {
attacker.summonData.ability = this.ability;
attacker.setTempAbility(allAbilities[this.ability]);
}

return true;
Expand Down Expand Up @@ -1920,8 +1920,8 @@ export class CopyFaintedAllyAbilityAbAttr extends PostKnockOutAbAttr {
applyPostKnockOut(pokemon: Pokemon, passive: boolean, simulated: boolean, knockedOut: Pokemon, args: any[]): boolean | Promise<boolean> {
if (pokemon.isPlayer() === knockedOut.isPlayer() && !knockedOut.getAbility().hasAttr(UncopiableAbilityAbAttr)) {
if (!simulated) {
pokemon.summonData.ability = knockedOut.getAbility().id;
globalScene.queueMessage(i18next.t("abilityTriggers:copyFaintedAllyAbility", { pokemonNameWithAffix: getPokemonNameWithAffix(knockedOut), abilityName: allAbilities[knockedOut.getAbility().id].name }));
pokemon.setTempAbility(knockedOut.getAbility());
}
return true;
}
Expand Down Expand Up @@ -2342,7 +2342,7 @@ export class PostSummonCopyAbilityAbAttr extends PostSummonAbAttr {
if (!simulated) {
this.target = target!;
this.targetAbilityName = allAbilities[target!.getAbility().id].name;
pokemon.summonData.ability = target!.getAbility().id;
pokemon.setTempAbility(target!.getAbility());
setAbilityRevealed(target!);
pokemon.updateInfo();
}
Expand Down Expand Up @@ -2474,7 +2474,6 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
}

pokemon.summonData.speciesForm = target.getSpeciesForm();
pokemon.summonData.ability = target.getAbility().id;
pokemon.summonData.gender = target.getGender();

// Copy all stats (except HP)
Expand Down Expand Up @@ -2504,6 +2503,8 @@ export class PostSummonTransformAbAttr extends PostSummonAbAttr {
promises.push(pokemon.loadAssets(false).then(() => {
pokemon.playAnim();
pokemon.updateInfo();
// If the new ability activates immediately, it needs to happen after all the transform animations
pokemon.setTempAbility(target.getAbility());
}));

await Promise.all(promises);
Expand Down Expand Up @@ -4866,9 +4867,10 @@ async function applyAbAttrsInternal<TAttr extends AbAttr>(
showAbilityInstant: boolean = false,
simulated: boolean = false,
messages: string[] = [],
considerPassive: boolean = true
) {
for (const passive of [ false, true ]) {
if (!pokemon?.canApplyAbility(passive) || (passive && pokemon.getPassiveAbility().id === pokemon.getAbility().id)) {
if (!pokemon?.canApplyAbility(passive) || (passive && (pokemon.getPassiveAbility().id === pokemon.getAbility().id || !considerPassive))) {
continue;
}

Expand Down Expand Up @@ -5294,6 +5296,21 @@ export function applyPostItemLostAbAttrs(attrType: Constructor<PostItemLostAbAtt
return applyAbAttrsInternal<PostItemLostAbAttr>(attrType, pokemon, (attr, passive) => attr.applyPostItemLost(pokemon, simulated, args), args);
}

/**
* Applies abilities when they become active mid-turn (ability switch)
*
* Ignores passives as they don't change and shouldn't be reapplied when main abilities change
*/
export function applyMidTurnAbAttrs(pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PostSummonAbAttr>(PostSummonAbAttr, pokemon, (attr, passive) => attr.applyPostSummon(pokemon, passive, simulated, args), args, false, simulated, [], false);
}

/**
* Clears primal weather during the turn if {@linkcode pokemon}'s ability corresponds to one
*/
export function applyMidTurnClearWeatherAbAttrs(pokemon: Pokemon, simulated: boolean = false, ...args: any[]): Promise<void> {
return applyAbAttrsInternal<PreSwitchOutAbAttr>(PreSwitchOutClearWeatherAbAttr, pokemon, (attr, passive) => attr.applyPreSwitchOut(pokemon, passive, simulated, args), args, true, simulated, [], false);
}
function queueShowAbility(pokemon: Pokemon, passive: boolean): void {
globalScene.unshiftPhase(new ShowAbilityPhase(pokemon.id, passive));
globalScene.clearPhaseQueueSplice();
Expand Down
26 changes: 14 additions & 12 deletions src/data/move.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7444,11 +7444,11 @@ export class AbilityChangeAttr extends MoveEffectAttr {

const moveTarget = this.selfTarget ? user : target;

moveTarget.summonData.ability = this.ability;
globalScene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger);

globalScene.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix((this.selfTarget ? user : target)), abilityName: allAbilities[this.ability].name }));

moveTarget.setTempAbility(allAbilities[this.ability]);
globalScene.triggerPokemonFormChange(moveTarget, SpeciesFormChangeRevertWeatherFormTrigger);

return true;
}

Expand All @@ -7471,13 +7471,13 @@ export class AbilityCopyAttr extends MoveEffectAttr {
return false;
}

user.summonData.ability = target.getAbility().id;

globalScene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name }));

user.setTempAbility(target.getAbility());

if (this.copyToPartner && globalScene.currentBattle?.double && user.getAlly().hp) {
user.getAlly().summonData.ability = target.getAbility().id;
globalScene.queueMessage(i18next.t("moveTriggers:copiedTargetAbility", { pokemonName: getPokemonNameWithAffix(user.getAlly()), targetName: getPokemonNameWithAffix(target), abilityName: allAbilities[target.getAbility().id].name }));
user.getAlly().setTempAbility(target.getAbility());
}

return true;
Expand Down Expand Up @@ -7508,10 +7508,10 @@ export class AbilityGiveAttr extends MoveEffectAttr {
return false;
}

target.summonData.ability = user.getAbility().id;

globalScene.queueMessage(i18next.t("moveTriggers:acquiredAbility", { pokemonName: getPokemonNameWithAffix(target), abilityName: allAbilities[user.getAbility().id].name }));

target.setTempAbility(user.getAbility());

return true;
}

Expand All @@ -7526,11 +7526,12 @@ export class SwitchAbilitiesAttr extends MoveEffectAttr {
return false;
}

const tempAbilityId = user.getAbility().id;
user.summonData.ability = target.getAbility().id;
target.summonData.ability = tempAbilityId;
const tempAbility = user.getAbility();

globalScene.queueMessage(i18next.t("moveTriggers:swappedAbilitiesWithTarget", { pokemonName: getPokemonNameWithAffix(user) }));

user.setTempAbility(target.getAbility());
target.setTempAbility(tempAbility);
// Swaps Forecast/Flower Gift from Castform/Cherrim
globalScene.arena.triggerWeatherBasedFormChangesToNormal();
// Swaps Forecast/Flower Gift to Castform/Cherrim (edge case)
emdeann marked this conversation as resolved.
Show resolved Hide resolved
Expand Down Expand Up @@ -7613,7 +7614,6 @@ export class TransformAttr extends MoveEffectAttr {

const promises: Promise<void>[] = [];
user.summonData.speciesForm = target.getSpeciesForm();
user.summonData.ability = target.getAbility().id;
user.summonData.gender = target.getGender();

// Power Trick's effect will not preserved after using Transform
Expand Down Expand Up @@ -7646,6 +7646,8 @@ export class TransformAttr extends MoveEffectAttr {
promises.push(user.loadAssets(false).then(() => {
user.playAnim();
user.updateInfo();
// If the new ability activates immediately, it needs to happen after all the transform animations
user.setTempAbility(target.getAbility());
}));

await Promise.all(promises);
Expand Down
14 changes: 13 additions & 1 deletion src/field/pokemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import { BattlerTag, BattlerTagLapseType, EncoreTag, GroundedTag, HighestStatBoo
import { WeatherType } from "#enums/weather-type";
import { ArenaTagSide, NoCritTag, WeakenMoveScreenTag } from "#app/data/arena-tag";
import type { Ability, AbAttr } from "#app/data/ability";
import { StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs, InfiltratorAbAttr, AlliedFieldDamageReductionAbAttr, PostDamageAbAttr, applyPostDamageAbAttrs, CommanderAbAttr, applyPostItemLostAbAttrs, PostItemLostAbAttr } from "#app/data/ability";
import { StatMultiplierAbAttr, BlockCritAbAttr, BonusCritAbAttr, BypassBurnDamageReductionAbAttr, FieldPriorityMoveImmunityAbAttr, IgnoreOpponentStatStagesAbAttr, MoveImmunityAbAttr, PreDefendFullHpEndureAbAttr, ReceivedMoveDamageMultiplierAbAttr, StabBoostAbAttr, StatusEffectImmunityAbAttr, TypeImmunityAbAttr, WeightMultiplierAbAttr, allAbilities, applyAbAttrs, applyStatMultiplierAbAttrs, applyPreApplyBattlerTagAbAttrs, applyPreAttackAbAttrs, applyPreDefendAbAttrs, applyPreSetStatusAbAttrs, UnsuppressableAbilityAbAttr, SuppressFieldAbilitiesAbAttr, NoFusionAbilityAbAttr, MultCritAbAttr, IgnoreTypeImmunityAbAttr, DamageBoostAbAttr, IgnoreTypeStatusEffectImmunityAbAttr, ConditionalCritAbAttr, applyFieldStatMultiplierAbAttrs, FieldMultiplyStatAbAttr, AddSecondStrikeAbAttr, UserFieldStatusEffectImmunityAbAttr, UserFieldBattlerTagImmunityAbAttr, BattlerTagImmunityAbAttr, MoveTypeChangeAbAttr, FullHpResistTypeAbAttr, applyCheckTrappedAbAttrs, CheckTrappedAbAttr, PostSetStatusAbAttr, applyPostSetStatusAbAttrs, InfiltratorAbAttr, AlliedFieldDamageReductionAbAttr, PostDamageAbAttr, applyPostDamageAbAttrs, CommanderAbAttr, applyPostItemLostAbAttrs, PostItemLostAbAttr, applyMidTurnAbAttrs, applyMidTurnClearWeatherAbAttrs } from "#app/data/ability";
import type PokemonData from "#app/system/pokemon-data";
import { BattlerIndex } from "#app/battle";
import { Mode } from "#app/ui/ui";
Expand Down Expand Up @@ -1413,6 +1413,18 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container {
return abilityAttrs;
}

/**
* Sets the {@linkcode Pokemon}'s ability and activates it if it normally activates on summon
*
* Also clears primal weather if it is from the ability being changed
* @param ability New Ability
*/
public setTempAbility(ability: Ability): void {
applyMidTurnClearWeatherAbAttrs(this);
this.summonData.ability = ability.id;
applyMidTurnAbAttrs(this);
}

/**
* Checks if a pokemon has a passive either from:
* - bought with starter candy
Expand Down
11 changes: 11 additions & 0 deletions src/test/abilities/imposter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,15 @@ describe("Abilities - Imposter", () => {
}
});
});

it("should activate its ability if it copies one that activates on summon", async () => {
game.override.enemyAbility(Abilities.INTIMIDATE);

await game.classicMode.startBattle([ Species.DITTO ]);

game.move.select(Moves.TACKLE);
await game.phaseInterceptor.to("MoveEndPhase");

expect(game.scene.getEnemyPokemon()?.getStatStage(Stat.ATK)).toBe(-1);
});
});
52 changes: 52 additions & 0 deletions src/test/abilities/mummy.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
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, expect, it } from "vitest";

describe("Abilities - Mummy", () => {
let phaserGame: Phaser.Game;
let game: GameManager;

beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});

afterEach(() => {
game.phaseInterceptor.restoreOg();
});

beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.moveset([ Moves.SPLASH ])
.ability(Abilities.MUMMY)
.battleType("single")
.disableCrits()
.enemySpecies(Species.MAGIKARP)
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.TACKLE);
});

it("should set the enemy's ability to mummy when hit by a contact move", async () => {
await game.classicMode.startBattle([ Species.FEEBAS ]);

game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase");

expect(game.scene.getEnemyPokemon()?.getAbility().id).toBe(Abilities.MUMMY);
});

it("should not change the enemy's ability hit by a non-contact move", async () => {
game.override.enemyMoveset(Moves.EARTHQUAKE);
await game.classicMode.startBattle([ Species.FEEBAS ]);

game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase");

expect(game.scene.getEnemyPokemon()?.getAbility().id).toBe(Abilities.BALL_FETCH);
});
});
53 changes: 53 additions & 0 deletions src/test/abilities/trace.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { Stat } from "#app/enums/stat";
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, expect, it } from "vitest";

describe("Abilities - Trace", () => {
let phaserGame: Phaser.Game;
let game: GameManager;

beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});

afterEach(() => {
game.phaseInterceptor.restoreOg();
});

beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.moveset([ Moves.SPLASH ])
.ability(Abilities.TRACE)
.battleType("single")
.disableCrits()
.enemySpecies(Species.MAGIKARP)
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.SPLASH);
});

it("should copy the opponent's ability", async () => {
await game.classicMode.startBattle([ Species.FEEBAS ]);

game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase");

expect(game.scene.getPlayerPokemon()?.getAbility().id).toBe(Abilities.BALL_FETCH);
});

it("should activate a copied post-summon ability", async () => {
game.override.enemyAbility(Abilities.INTIMIDATE);
await game.classicMode.startBattle([ Species.FEEBAS ]);

game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase");

expect(game.scene.getEnemyPokemon()?.getStatStage(Stat.ATK)).toBe(-1);
});
});
65 changes: 65 additions & 0 deletions src/test/abilities/wandering_spirit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import { Stat } from "#app/enums/stat";
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, expect, it } from "vitest";

describe("Abilities - Wandering Spirit", () => {
let phaserGame: Phaser.Game;
let game: GameManager;

beforeAll(() => {
phaserGame = new Phaser.Game({
type: Phaser.HEADLESS,
});
});

afterEach(() => {
game.phaseInterceptor.restoreOg();
});

beforeEach(() => {
game = new GameManager(phaserGame);
game.override
.moveset([ Moves.SPLASH ])
.ability(Abilities.WANDERING_SPIRIT)
.battleType("single")
.disableCrits()
.enemySpecies(Species.MAGIKARP)
.enemyAbility(Abilities.BALL_FETCH)
.enemyMoveset(Moves.TACKLE);
});

it("should exchange abilities when hit with a contact move", async () => {
await game.classicMode.startBattle([ Species.FEEBAS ]);

game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase");

expect(game.scene.getPlayerPokemon()?.getAbility().id).toBe(Abilities.BALL_FETCH);
expect(game.scene.getEnemyPokemon()?.getAbility().id).toBe(Abilities.WANDERING_SPIRIT);
});

it("should not exchange abilities when hit with a non-contact move", async () => {
game.override.enemyMoveset(Moves.EARTHQUAKE);
await game.classicMode.startBattle([ Species.FEEBAS ]);

game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase");

expect(game.scene.getPlayerPokemon()?.getAbility().id).toBe(Abilities.WANDERING_SPIRIT);
expect(game.scene.getEnemyPokemon()?.getAbility().id).toBe(Abilities.BALL_FETCH);
});

it("should activate post-summon abilities", async () => {
game.override.enemyAbility(Abilities.INTIMIDATE);
await game.classicMode.startBattle([ Species.FEEBAS ]);

game.move.select(Moves.SPLASH);
await game.phaseInterceptor.to("BerryPhase");

expect(game.scene.getEnemyPokemon()?.getStatStage(Stat.ATK)).toBe(-1);
});
});
Loading