diff --git a/src/phases/move-effect-phase.ts b/src/phases/move-effect-phase.ts index 6ada6bd7fac..e9984232335 100644 --- a/src/phases/move-effect-phase.ts +++ b/src/phases/move-effect-phase.ts @@ -98,8 +98,8 @@ export class MoveEffectPhase extends PokemonPhase { const targetHitChecks = Object.fromEntries(targets.map(p => [p.getBattlerIndex(), this.hitCheck(p)])); const hasActiveTargets = targets.some(t => t.isActive(true)); - /** Check if the target is immune via ability */ - const isImmune = targets[0].hasAbilityWithAttr(TypeImmunityAbAttr) && targets[0].getAbility().getAttrs(TypeImmunityAbAttr)[0].getImmuneType() === user.getMoveType(move); + /** Check if the target is immune via ability to the attacking move */ + const isImmune = targets[0].hasAbilityWithAttr(TypeImmunityAbAttr) && (targets[0].getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move)); /** * If no targets are left for the move to hit (FAIL), or the invoked move is single-target @@ -148,7 +148,7 @@ export class MoveEffectPhase extends PokemonPhase { || (this.move.getMove().category !== MoveCategory.STATUS && target.findTags(t => t instanceof DamageProtectedTag).find(t => target.lapseTag(t.tagType)))); /** Is the pokemon immune due to an ablility? */ - const isImmune = target.hasAbilityWithAttr(TypeImmunityAbAttr) && target.getAbility().getAttrs(TypeImmunityAbAttr)[0].getImmuneType() === user.getMoveType(move); + const isImmune = target.hasAbilityWithAttr(TypeImmunityAbAttr) && (target.getAbility()?.getAttrs(TypeImmunityAbAttr)?.[0]?.getImmuneType() === user.getMoveType(move)); /** * If the move missed a target, stop all future hits against that target @@ -415,7 +415,7 @@ export class MoveEffectPhase extends PokemonPhase { const accuracyMultiplier = user.getAccuracyMultiplier(target, this.move.getMove()); const rand = user.randSeedInt(100); - return rand < accuracyMultiplier * moveAccuracy; + return (rand < accuracyMultiplier * moveAccuracy); } /** Returns the {@linkcode Pokemon} using this phase's invoked move */ diff --git a/src/test/abilities/volt_absorb.test.ts b/src/test/abilities/volt_absorb.test.ts index 7f3e160c7d0..db14a5a2dba 100644 --- a/src/test/abilities/volt_absorb.test.ts +++ b/src/test/abilities/volt_absorb.test.ts @@ -39,7 +39,7 @@ describe("Abilities - Volt Absorb", () => { game.override.enemySpecies(Species.DUSKULL); game.override.enemyAbility(Abilities.BALL_FETCH); - await game.startBattle(); + await game.classicMode.startBattle(); const playerPokemon = game.scene.getPlayerPokemon()!; @@ -51,4 +51,21 @@ describe("Abilities - Volt Absorb", () => { expect(playerPokemon.getTag(BattlerTagType.CHARGED)).toBeDefined(); expect(game.phaseInterceptor.log).not.toContain("ShowAbilityPhase"); }); + it("should activate regardless of accuracy checks", async () => { + game.override.moveset(Moves.THUNDERBOLT); + game.override.enemyMoveset(Moves.SPLASH); + game.override.enemySpecies(Species.MAGIKARP); + game.override.enemyAbility(Abilities.VOLT_ABSORB); + + await game.classicMode.startBattle(); + + const enemyPokemon = game.scene.getEnemyPokemon()!; + + game.move.select(Moves.THUNDERBOLT); + await game.phaseInterceptor.to("MoveEffectPhase"); + + await game.move.forceMiss(); + await game.phaseInterceptor.to("BerryPhase", false); + expect(enemyPokemon.hp).toBe(enemyPokemon.getMaxHp()); + }); });