diff --git a/src/data/move.ts b/src/data/move.ts index c4e920b773a..529a9508acf 100644 --- a/src/data/move.ts +++ b/src/data/move.ts @@ -1420,6 +1420,11 @@ export class RecoilAttr extends MoveEffectAttr { return false; } + // Chloroblast and Struggle should not deal recoil damage if the move was not successful + if (this.useHp && [ MoveResult.FAIL, MoveResult.MISS ].includes(user.getLastXMoves(1)[0]?.result)) { + return false; + } + const damageValue = (!this.useHp ? user.turnData.damageDealt : user.getMaxHp()) * this.damageRatio; const minValue = user.turnData.damageDealt ? 1 : 0; const recoilDamage = Utils.toDmgValue(damageValue, minValue); diff --git a/src/test/moves/chloroblast.test.ts b/src/test/moves/chloroblast.test.ts new file mode 100644 index 00000000000..5e55bf46958 --- /dev/null +++ b/src/test/moves/chloroblast.test.ts @@ -0,0 +1,42 @@ +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("Moves - Chloroblast", () => { + 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.CHLOROBLAST ]) + .ability(Abilities.BALL_FETCH) + .battleType("single") + .disableCrits() + .enemySpecies(Species.MAGIKARP) + .enemyAbility(Abilities.BALL_FETCH) + .enemyMoveset(Moves.PROTECT); + }); + + it("should not deal recoil damage if the opponent uses protect", async () => { + await game.classicMode.startBattle([ Species.FEEBAS ]); + + game.move.select(Moves.CHLOROBLAST); + await game.phaseInterceptor.to("BerryPhase"); + + expect(game.scene.getPlayerPokemon()!.isFullHp()).toBe(true); + }); +});