From a85a2a9b8bb8c63e4ebe66e9503e58f94d7db5df Mon Sep 17 00:00:00 2001 From: Zach Day Date: Thu, 13 Jun 2024 09:49:40 -0400 Subject: [PATCH] [Bug] Fix type-immunity abilities activating on self-targeted status moves (#2168) * Fix type immunity given by abilities only applying to attacking moves * Add tests for type immunity granted by abilities * Use Sap Sipper as base for testing * Fix type-immunity abilities activating on self-targeted status moves * Add tests for self-targeted moves on mons with type-immunity abilitiies * Volt absorb tests --- src/data/ability.ts | 2 +- src/test/abilities/sap_sipper.test.ts | 29 ++++++++++++- src/test/abilities/volt_absorb.test.ts | 56 ++++++++++++++++++++++++++ 3 files changed, 84 insertions(+), 3 deletions(-) create mode 100644 src/test/abilities/volt_absorb.test.ts diff --git a/src/data/ability.ts b/src/data/ability.ts index 08f6712d4c7..11a3f48eff9 100755 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -372,7 +372,7 @@ export class TypeImmunityAbAttr extends PreDefendAbAttr { return false; } - if (move.type === this.immuneType) { + if (attacker !== pokemon && move.type === this.immuneType) { (args[0] as Utils.NumberHolder).value = 0; return true; } diff --git a/src/test/abilities/sap_sipper.test.ts b/src/test/abilities/sap_sipper.test.ts index 5207ae8bb43..e2b3099f28f 100644 --- a/src/test/abilities/sap_sipper.test.ts +++ b/src/test/abilities/sap_sipper.test.ts @@ -5,7 +5,7 @@ import * as overrides from "#app/overrides"; import {Species} from "#app/data/enums/species"; import { CommandPhase, - EnemyCommandPhase, TurnEndPhase, + EnemyCommandPhase, MoveEndPhase, TurnEndPhase, } from "#app/phases"; import {Mode} from "#app/ui/ui"; import {Moves} from "#app/data/enums/moves"; @@ -14,8 +14,9 @@ import {Command} from "#app/ui/command-ui-handler"; import { Abilities } from "#app/data/enums/abilities.js"; import { BattleStat } from "#app/data/battle-stat.js"; import { TerrainType } from "#app/data/terrain.js"; +import { BattlerTagType } from "#app/data/enums/battler-tag-type.js"; -// See also: ArenaTypeAbAttr +// See also: TypeImmunityAbAttr describe("Abilities - Sap Sipper", () => { let phaserGame: Phaser.Game; let game: GameManager; @@ -113,4 +114,28 @@ describe("Abilities - Sap Sipper", () => { expect(game.scene.arena.terrain.terrainType).toBe(TerrainType.GRASSY); expect(game.scene.getEnemyParty()[0].summonData.battleStats[BattleStat.ATK]).toBe(0); }); + + it("do not activate against status moves that target the user", async() => { + const moveToUse = Moves.SPIKY_SHIELD; + const ability = Abilities.SAP_SIPPER; + + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.RATTATA); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + + await game.startBattle(); + + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); + + await game.phaseInterceptor.to(MoveEndPhase); + + expect(game.scene.getParty()[0].getTag(BattlerTagType.SPIKY_SHIELD)).toBeDefined(); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.getParty()[0].summonData.battleStats[BattleStat.ATK]).toBe(0); + expect(game.phaseInterceptor.log).not.toContain("ShowAbilityPhase"); + }); }); diff --git a/src/test/abilities/volt_absorb.test.ts b/src/test/abilities/volt_absorb.test.ts new file mode 100644 index 00000000000..1f0827780ac --- /dev/null +++ b/src/test/abilities/volt_absorb.test.ts @@ -0,0 +1,56 @@ +import {afterEach, beforeAll, beforeEach, describe, expect, it, vi} from "vitest"; +import Phaser from "phaser"; +import GameManager from "#app/test/utils/gameManager"; +import * as overrides from "#app/overrides"; +import {Species} from "#app/data/enums/species"; +import { + TurnEndPhase, +} from "#app/phases"; +import {Moves} from "#app/data/enums/moves"; +import {getMovePosition} from "#app/test/utils/gameManagerUtils"; +import { Abilities } from "#app/data/enums/abilities.js"; +import { BattleStat } from "#app/data/battle-stat.js"; +import { BattlerTagType } from "#app/data/enums/battler-tag-type.js"; + +// See also: TypeImmunityAbAttr +describe("Abilities - Volt Absorb", () => { + let phaserGame: Phaser.Game; + let game: GameManager; + + beforeAll(() => { + phaserGame = new Phaser.Game({ + type: Phaser.HEADLESS, + }); + }); + + afterEach(() => { + game.phaseInterceptor.restoreOg(); + }); + + beforeEach(() => { + game = new GameManager(phaserGame); + vi.spyOn(overrides, "SINGLE_BATTLE_OVERRIDE", "get").mockReturnValue(true); + vi.spyOn(overrides, "NEVER_CRIT_OVERRIDE", "get").mockReturnValue(true); + }); + + it("does not activate when CHARGE is used", async () => { + const moveToUse = Moves.CHARGE; + const ability = Abilities.VOLT_ABSORB; + + vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([moveToUse]); + vi.spyOn(overrides, "ABILITY_OVERRIDE", "get").mockReturnValue(ability); + vi.spyOn(overrides, "OPP_MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SPLASH, Moves.NONE, Moves.NONE, Moves.NONE]); + vi.spyOn(overrides, "OPP_SPECIES_OVERRIDE", "get").mockReturnValue(Species.DUSKULL); + vi.spyOn(overrides, "OPP_ABILITY_OVERRIDE", "get").mockReturnValue(Abilities.NONE); + + await game.startBattle(); + + game.doAttack(getMovePosition(game.scene, 0, moveToUse)); + + await game.phaseInterceptor.to(TurnEndPhase); + + expect(game.scene.getParty()[0].summonData.battleStats[BattleStat.SPDEF]).toBe(1); + expect(game.scene.getParty()[0].getTag(BattlerTagType.CHARGED)).toBeDefined(); + expect(game.phaseInterceptor.log).not.toContain("ShowAbilityPhase"); + }); +});