diff --git a/src/data/ability.ts b/src/data/ability.ts index ee1e17998d8..e3c59f709c0 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -6593,7 +6593,6 @@ export function initAbilities() { .attr(PostSummonFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .attr(PostTurnFormChangeAbAttr, p => p.formIndex % 7 + (p.getHpRatio() <= 0.5 ? 7 : 0)) .conditionalAttr(p => p.formIndex !== 7, StatusEffectImmunityAbAttr) - .conditionalAttr(p => p.formIndex !== 7, PostSummonHealStatusAbAttr) .conditionalAttr(p => p.formIndex !== 7, BattlerTagImmunityAbAttr, BattlerTagType.DROWSY) .attr(UncopiableAbilityAbAttr) .attr(UnswappableAbilityAbAttr) diff --git a/test/abilities/comatose.test.ts b/test/abilities/comatose.test.ts new file mode 100644 index 00000000000..f4510c44ad0 --- /dev/null +++ b/test/abilities/comatose.test.ts @@ -0,0 +1,55 @@ +import { BattlerIndex } from "#app/battle"; +import { allAbilities } from "#app/data/ability"; +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Comatose", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove status when reactivated", async () => { + game.override.enemyAbility(Abilities.BALL_FETCH) + .moveset([ Moves.SPORE, Moves.SPLASH ]) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + game.move.select(Moves.SPORE); + await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.ENEMY ]); + await game.phaseInterceptor.to("MoveEndPhase"); + + expect(enemy?.status?.effect).toBe(StatusEffect.SLEEP); + + enemy?.setTempAbility(allAbilities[Abilities.COMATOSE]); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/immunity.test.ts b/test/abilities/immunity.test.ts new file mode 100644 index 00000000000..51e9598720b --- /dev/null +++ b/test/abilities/immunity.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Immunity", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove poison when gained", async () => { + game.override.ability(Abilities.IMMUNITY) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.POISON); + expect(enemy?.status?.effect).toBe(StatusEffect.POISON); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/insomnia.test.ts b/test/abilities/insomnia.test.ts new file mode 100644 index 00000000000..91fdc3fc668 --- /dev/null +++ b/test/abilities/insomnia.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Insomnia", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove sleep when gained", async () => { + game.override.ability(Abilities.INSOMNIA) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.SLEEP); + expect(enemy?.status?.effect).toBe(StatusEffect.SLEEP); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/limber.test.ts b/test/abilities/limber.test.ts new file mode 100644 index 00000000000..2b167cc155f --- /dev/null +++ b/test/abilities/limber.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Limber", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove paralysis when gained", async () => { + game.override.ability(Abilities.LIMBER) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.PARALYSIS); + expect(enemy?.status?.effect).toBe(StatusEffect.PARALYSIS); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/magma_armor.test.ts b/test/abilities/magma_armor.test.ts new file mode 100644 index 00000000000..b1d62f948d2 --- /dev/null +++ b/test/abilities/magma_armor.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Magma Armor", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove freeze when gained", async () => { + game.override.ability(Abilities.MAGMA_ARMOR) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.FREEZE); + expect(enemy?.status?.effect).toBe(StatusEffect.FREEZE); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/thermal_exchange.test.ts b/test/abilities/thermal_exchange.test.ts new file mode 100644 index 00000000000..124c1dba286 --- /dev/null +++ b/test/abilities/thermal_exchange.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Thermal Exchange", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove burn when gained", async () => { + game.override.ability(Abilities.THERMAL_EXCHANGE) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.BURN); + expect(enemy?.status?.effect).toBe(StatusEffect.BURN); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/vital_spirit.test.ts b/test/abilities/vital_spirit.test.ts new file mode 100644 index 00000000000..3a53c3f520e --- /dev/null +++ b/test/abilities/vital_spirit.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Vital 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove sleep when gained", async () => { + game.override.ability(Abilities.INSOMNIA) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.SLEEP); + expect(enemy?.status?.effect).toBe(StatusEffect.SLEEP); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/water_bubble.test.ts b/test/abilities/water_bubble.test.ts new file mode 100644 index 00000000000..0b85a5814da --- /dev/null +++ b/test/abilities/water_bubble.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Water Bubble", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove burn when gained", async () => { + game.override.ability(Abilities.THERMAL_EXCHANGE) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.BURN); + expect(enemy?.status?.effect).toBe(StatusEffect.BURN); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +}); diff --git a/test/abilities/water_veil.test.ts b/test/abilities/water_veil.test.ts new file mode 100644 index 00000000000..38c9a05600b --- /dev/null +++ b/test/abilities/water_veil.test.ts @@ -0,0 +1,51 @@ +import { Abilities } from "#enums/abilities"; +import { Moves } from "#enums/moves"; +import { Species } from "#enums/species"; +import { StatusEffect } from "#enums/status-effect"; +import GameManager from "#test/testUtils/gameManager"; +import Phaser from "phaser"; +import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; + +describe("Abilities - Water Veil", () => { + 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.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should remove burn when gained", async () => { + game.override.ability(Abilities.THERMAL_EXCHANGE) + .enemyAbility(Abilities.BALL_FETCH) + .moveset(Moves.SKILL_SWAP) + .enemyMoveset(Moves.SPLASH), + + await game.classicMode.startBattle([ Species.FEEBAS ]); + const enemy = game.scene.getEnemyPokemon(); + enemy?.trySetStatus(StatusEffect.BURN); + expect(enemy?.status?.effect).toBe(StatusEffect.BURN); + + game.move.select(Moves.SKILL_SWAP); + await game.phaseInterceptor.to("BerryPhase"); + + expect(enemy?.status).toBeNull(); + }); +});