import { BattlerIndex } from "#app/battle"; import type { MovePhase } from "#app/phases/move-phase"; import { Abilities } from "#enums/abilities"; import { Moves } from "#enums/moves"; import { Species } from "#enums/species"; import GameManager from "#test/testUtils/gameManager"; import Phaser from "phaser"; import { afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest"; describe("Abilities - Dancer", () => { 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.battleType("double"); }); // Reference Link: https://bulbapedia.bulbagarden.net/wiki/Dancer_(Ability) it("triggers when dance moves are used, doesn't consume extra PP", async () => { game.override .enemyAbility(Abilities.DANCER) .enemySpecies(Species.MAGIKARP) .enemyMoveset(Moves.VICTORY_DANCE); await game.classicMode.startBattle([ Species.ORICORIO, Species.FEEBAS ]); const [ oricorio, feebas ] = game.scene.getPlayerField(); game.move.changeMoveset(oricorio, [ Moves.SWORDS_DANCE, Moves.VICTORY_DANCE, Moves.SPLASH ]); game.move.changeMoveset(feebas, [ Moves.SWORDS_DANCE, Moves.SPLASH ]); game.move.select(Moves.SPLASH); game.move.select(Moves.SWORDS_DANCE, 1); await game.setTurnOrder([ BattlerIndex.PLAYER_2, BattlerIndex.ENEMY, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2 ]); await game.phaseInterceptor.to("MovePhase"); // immediately copies ally move await game.phaseInterceptor.to("MovePhase", false); let currentPhase = game.scene.getCurrentPhase() as MovePhase; expect(currentPhase.pokemon).toBe(oricorio); expect(currentPhase.move.moveId).toBe(Moves.SWORDS_DANCE); await game.phaseInterceptor.to("MoveEndPhase"); await game.phaseInterceptor.to("MovePhase"); // immediately copies enemy move await game.phaseInterceptor.to("MovePhase", false); currentPhase = game.scene.getCurrentPhase() as MovePhase; expect(currentPhase.pokemon).toBe(oricorio); expect(currentPhase.move.moveId).toBe(Moves.VICTORY_DANCE); await game.phaseInterceptor.to("BerryPhase"); // doesn't use PP if copied move is also in moveset expect(oricorio.moveset[0]?.ppUsed).toBe(0); expect(oricorio.moveset[1]?.ppUsed).toBe(0); }); // TODO: Enable after Dancer rework to not push to move history it.todo("should not count as the last move used for mirror move/instruct", async () => { game.override .moveset([ Moves.FIERY_DANCE, Moves.REVELATION_DANCE ]) .enemyMoveset([ Moves.INSTRUCT, Moves.MIRROR_MOVE, Moves.SPLASH ]) .enemySpecies(Species.SHUCKLE) .enemyLevel(10); await game.classicMode.startBattle([ Species.ORICORIO, Species.FEEBAS ]); const [ oricorio ] = game.scene.getPlayerField(); const [ , shuckle2 ] = game.scene.getEnemyField(); game.move.select(Moves.REVELATION_DANCE, BattlerIndex.PLAYER, BattlerIndex.ENEMY_2); game.move.select(Moves.FIERY_DANCE, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2); await game.forceEnemyMove(Moves.INSTRUCT, BattlerIndex.PLAYER); await game.forceEnemyMove(Moves.MIRROR_MOVE, BattlerIndex.PLAYER); await game.setTurnOrder([ BattlerIndex.PLAYER, BattlerIndex.PLAYER_2, BattlerIndex.ENEMY_2, BattlerIndex.ENEMY ]); await game.phaseInterceptor.to("MovePhase"); // Oricorio rev dance await game.phaseInterceptor.to("MovePhase"); // Feebas fiery dance await game.phaseInterceptor.to("MovePhase"); // Oricorio fiery dance (from dancer) await game.phaseInterceptor.to("MoveEndPhase", false); // dancer copied move doesn't appear in move history expect(oricorio.getLastXMoves(-1)[0].move).toBe(Moves.REVELATION_DANCE); await game.phaseInterceptor.to("MovePhase"); // shuckle 2 mirror moves oricorio await game.phaseInterceptor.to("MovePhase"); // calls instructed rev dance let currentPhase = game.scene.getCurrentPhase() as MovePhase; expect(currentPhase.pokemon).toBe(shuckle2); expect(currentPhase.move.moveId).toBe(Moves.REVELATION_DANCE); await game.phaseInterceptor.to("MovePhase"); // shuckle 1 instructs oricorio await game.phaseInterceptor.to("MovePhase"); currentPhase = game.scene.getCurrentPhase() as MovePhase; expect(currentPhase.pokemon).toBe(oricorio); expect(currentPhase.move.moveId).toBe(Moves.REVELATION_DANCE); }); });