From 01f3b00bc4bd854e31b4dc02036ef3b920e42959 Mon Sep 17 00:00:00 2001 From: innerthunder Date: Tue, 1 Oct 2024 15:50:39 -0700 Subject: [PATCH] Apply Tera Shell to all hits for multi-hit moves --- src/data/ability.ts | 1 + src/field/pokemon.ts | 4 ++++ src/phases/move-effect-phase.ts | 2 ++ src/test/abilities/tera_shell.test.ts | 23 +++++++++++++++++++++++ 4 files changed, 30 insertions(+) diff --git a/src/data/ability.ts b/src/data/ability.ts index a698831a1eb..8a7365b2c28 100644 --- a/src/data/ability.ts +++ b/src/data/ability.ts @@ -519,6 +519,7 @@ export class FullHpResistTypeAbAttr extends PreDefendAbAttr { if (pokemon.isFullHp() && typeMultiplier.value > 0.5) { typeMultiplier.value = 0.5; + pokemon.turnData.moveEffectiveness = 0.5; return true; } return false; diff --git a/src/field/pokemon.ts b/src/field/pokemon.ts index 6afc0770a7f..0a13be36c58 100644 --- a/src/field/pokemon.ts +++ b/src/field/pokemon.ts @@ -1538,6 +1538,9 @@ export default abstract class Pokemon extends Phaser.GameObjects.Container { * @returns The type damage multiplier, indicating the effectiveness of the move */ getMoveEffectiveness(source: Pokemon, move: Move, ignoreAbility: boolean = false, simulated: boolean = true, cancelled?: Utils.BooleanHolder): TypeDamageMultiplier { + if (this.turnData.moveEffectiveness !== null) { + return this.turnData.moveEffectiveness; + } if (move.hasAttr(TypelessAttr)) { return 1; } @@ -5019,6 +5022,7 @@ export class PokemonTurnData { public order: number; public statStagesIncreased: boolean = false; public statStagesDecreased: boolean = false; + public moveEffectiveness: TypeDamageMultiplier | null = null; } export enum AiType { diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 263a576c4f0..d4403558b7b 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -360,6 +360,8 @@ export class MoveEffectPhase extends PokemonPhase { this.scene.queueMessage(i18next.t("battle:attackHitsCount", { count: hitsTotal })); } this.scene.applyModifiers(HitHealModifier, this.player, user); + // Clear all cached move effectiveness values among targets + this.getTargets().forEach((target) => target.turnData.moveEffectiveness = null); } } diff --git a/src/test/abilities/tera_shell.test.ts b/src/test/abilities/tera_shell.test.ts index 13df49136ca..9995f7c34c3 100644 --- a/src/test/abilities/tera_shell.test.ts +++ b/src/test/abilities/tera_shell.test.ts @@ -1,3 +1,4 @@ +import { BattlerIndex } from "#app/battle"; import { Abilities } from "#app/enums/abilities"; import { Moves } from "#app/enums/moves"; import { Species } from "#app/enums/species"; @@ -106,4 +107,26 @@ describe("Abilities - Tera Shell", () => { expect(playerPokemon.hp).toBe(playerPokemon.getMaxHp() - 40); } ); + + it( + "should change the effectiveness of all strikes of a multi-strike move", + async () => { + game.override.enemyMoveset([Moves.DOUBLE_HIT]); + + await game.classicMode.startBattle([Species.SNORLAX]); + + const playerPokemon = game.scene.getPlayerPokemon()!; + vi.spyOn(playerPokemon, "apply"); + + game.move.select(Moves.SPLASH); + + await game.setTurnOrder([BattlerIndex.ENEMY, BattlerIndex.PLAYER]); + await game.move.forceHit(); + for (let i = 0; i < 2; i++) { + await game.phaseInterceptor.to("MoveEffectPhase"); + expect(playerPokemon.apply).toHaveLastReturnedWith(HitResult.NOT_VERY_EFFECTIVE); + } + expect(playerPokemon.apply).toHaveReturnedTimes(2); + } + ); });