From 2afcd176706d5e86c75c57b11748480aeba977b9 Mon Sep 17 00:00:00 2001 From: innerthunder Date: Tue, 8 Oct 2024 02:50:58 -0700 Subject: [PATCH] Electro Shot integration tests --- src/data/move.ts | 2 +- src/phases/move-charge-phase.ts | 4 ++ src/test/moves/electro_shot.test.ts | 86 +++++++++++++++++++++++++++++ src/test/moves/solar_beam.test.ts | 1 - 4 files changed, 91 insertions(+), 2 deletions(-) create mode 100644 src/test/moves/electro_shot.test.ts diff --git a/src/data/move.ts b/src/data/move.ts index 188ca485ba0..e9b4b39103b 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -9940,7 +9940,7 @@ export function initMoves() { .makesContact(false), new ChargingAttackMove(Moves.ELECTRO_SHOT, Type.ELECTRIC, MoveCategory.SPECIAL, 130, 100, 10, -1, 0, 9) .chargeText(i18next.t("moveTriggers:absorbedElectricity", { pokemonName: "{USER}" })) - .chargeAttr(StatStageChangeAttr, [ Stat.SPATK ], 1) + .chargeAttr(StatStageChangeAttr, [ Stat.SPATK ], 1, true) .chargeAttr(WeatherInstantChargeAttr, [ WeatherType.RAIN, WeatherType.HEAVY_RAIN ]) .ignoresVirtual(), new AttackMove(Moves.TERA_STARSTORM, Type.NORMAL, MoveCategory.SPECIAL, 120, 100, 5, -1, 0, 9) diff --git a/src/phases/move-charge-phase.ts b/src/phases/move-charge-phase.ts index 444e8c0291e..826a08f9d04 100644 --- a/src/phases/move-charge-phase.ts +++ b/src/phases/move-charge-phase.ts @@ -7,6 +7,7 @@ import { BooleanHolder } from "#app/utils"; import { MovePhase } from "#app/phases/move-phase"; import { PokemonPhase } from "#app/phases/pokemon-phase"; import { BattlerTagType } from "#enums/battler-tag-type"; +import { MoveEndPhase } from "./move-end-phase"; export class MoveChargePhase extends PokemonPhase { @@ -54,6 +55,9 @@ export class MoveChargePhase extends PokemonPhase { applyMoveChargeAttrs(InstantChargeAttr, user, null, move, instantCharge); if (instantCharge.value) { + // this MoveEndPhase will be duplicated by the queued MovePhase if not removed + this.scene.tryRemovePhase((phase) => phase instanceof MoveEndPhase && phase.getPokemon() === user); + // queue a new MovePhase for this move's attack phase this.scene.unshiftPhase(new MovePhase(this.scene, user, [ this.targetIndex ], this.move, false)); } else { user.getMoveQueue().push({ move: move.id, targets: [ this.targetIndex ]}); diff --git a/src/test/moves/electro_shot.test.ts b/src/test/moves/electro_shot.test.ts new file mode 100644 index 00000000000..4e218cb739b --- /dev/null +++ b/src/test/moves/electro_shot.test.ts @@ -0,0 +1,86 @@ +import { BattlerTagType } from "#enums/battler-tag-type"; +import { Stat } from "#enums/stat"; +import { WeatherType } from "#enums/weather-type"; +import { MoveResult } from "#app/field/pokemon"; +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, it, expect } from "vitest"; + +describe("Moves - Electro Shot", () => { + 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.ELECTRO_SHOT) + .battleType("single") + .startingLevel(100) + .enemySpecies(Species.SNORLAX) + .enemyLevel(100) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.SPLASH); + }); + + it("should increase the user's Sp. Atk on the first turn, then attack on the second turn", async () => { + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.ELECTRO_SHOT); + + await game.phaseInterceptor.to("TurnEndPhase"); + expect(playerPokemon.getTag(BattlerTagType.CHARGING)).toBeDefined(); + expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + expect(playerPokemon.getLastXMoves(1)[0].result).toBe(MoveResult.OTHER); + expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1); + + await game.phaseInterceptor.to("TurnEndPhase"); + expect(playerPokemon.getTag(BattlerTagType.CHARGING)).toBeUndefined(); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + expect(playerPokemon.getMoveHistory()).toHaveLength(2); + expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1); + expect(playerPokemon.getLastXMoves(1)[0].result).toBe(MoveResult.SUCCESS); + + const playerElectroShot = playerPokemon.getMoveset().find(mv => mv && mv.moveId === Moves.ELECTRO_SHOT); + expect(playerElectroShot?.ppUsed).toBe(1); + }); + + it.each([ + { weatherType: WeatherType.RAIN, name: "Rain" }, + { weatherType: WeatherType.HEAVY_RAIN, name: "Heavy Rain" } + ])("should fully resolve in one turn if $name is active", async ({ weatherType }) => { + game.override.weather(weatherType); + + await game.classicMode.startBattle([ Species.MAGIKARP ]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + const enemyPokemon = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.ELECTRO_SHOT); + + await game.phaseInterceptor.to("MoveEndPhase"); + expect(playerPokemon.getTag(BattlerTagType.CHARGING)).toBeUndefined(); + expect(enemyPokemon.hp).toBeLessThan(enemyPokemon.getMaxHp()); + expect(playerPokemon.getMoveHistory()).toHaveLength(2); + expect(playerPokemon.getStatStage(Stat.SPATK)).toBe(1); + expect(playerPokemon.getLastXMoves(1)[0].result).toBe(MoveResult.SUCCESS); + + const playerElectroShot = playerPokemon.getMoveset().find(mv => mv && mv.moveId === Moves.ELECTRO_SHOT); + expect(playerElectroShot?.ppUsed).toBe(1); + }); +}); diff --git a/src/test/moves/solar_beam.test.ts b/src/test/moves/solar_beam.test.ts index e367810879e..ebec338932a 100644 --- a/src/test/moves/solar_beam.test.ts +++ b/src/test/moves/solar_beam.test.ts @@ -47,7 +47,6 @@ describe("Moves - Solar Beam", () => { expect(playerPokemon.getTag(BattlerTagType.CHARGING)).toBeDefined(); expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); expect(playerPokemon.getLastXMoves(1)[0].result).toBe(MoveResult.OTHER); - // expect(playerSolarBeam?.ppUsed).toBe(0); await game.phaseInterceptor.to("TurnEndPhase"); expect(playerPokemon.getTag(BattlerTagType.CHARGING)).toBeUndefined();