[Bug] Fix ice face blocking all hits from multihit moves (#2391)

* fix ice face bug

* add multihit test
This commit is contained in:
Adrian T 2024-06-19 10:56:44 +08:00 committed by GitHub
parent 508f8eb3cf
commit 9463da8797
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 46 additions and 12 deletions

View File

@ -3682,13 +3682,21 @@ export class PostSummonStatChangeOnArenaAbAttr extends PostSummonStatChangeAbAtt
} }
/** /**
* Applies immunity to physical moves. * Takes no damage from the first hit of a physical move.
* This is used in Ice Face ability. * This is used in Ice Face ability.
*/ */
export class IceFaceMoveImmunityAbAttr extends MoveImmunityAbAttr { export class IceFaceBlockPhysicalAbAttr extends ReceivedMoveDamageMultiplierAbAttr {
private multiplier: number;
constructor(condition: PokemonDefendCondition, multiplier: number) {
super(condition, multiplier);
this.multiplier = multiplier;
}
/** /**
* Applies the Ice Face pre-defense ability to the Pokémon. * Applies the Ice Face pre-defense ability to the Pokémon.
* Removes BattlerTagType.ICE_FACE hit by physical attack and is in Ice Face form. * Removes BattlerTagType.ICE_FACE when hit by physical attack and is in Ice Face form.
* *
* @param {Pokemon} pokemon - The Pokémon with the Ice Face ability. * @param {Pokemon} pokemon - The Pokémon with the Ice Face ability.
* @param {boolean} passive - Whether the ability is passive. * @param {boolean} passive - Whether the ability is passive.
@ -3699,16 +3707,13 @@ export class IceFaceMoveImmunityAbAttr extends MoveImmunityAbAttr {
* @returns {boolean} - Whether the immunity was applied. * @returns {boolean} - Whether the immunity was applied.
*/ */
applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean { applyPreDefend(pokemon: Pokemon, passive: boolean, attacker: Pokemon, move: Move, cancelled: Utils.BooleanHolder, args: any[]): boolean {
const isImmune = super.applyPreDefend(pokemon, passive, attacker, move, cancelled, args); if (this.condition(pokemon, attacker, move)) {
(args[0] as Utils.NumberHolder).value = this.multiplier;
if (isImmune) { pokemon.removeTag(BattlerTagType.ICE_FACE);
const simulated = args.length > 1 && args[1]; return true;
if (!simulated) {
pokemon.removeTag(BattlerTagType.ICE_FACE);
}
} }
return isImmune; return false;
} }
/** /**
@ -4768,7 +4773,7 @@ export function initAbilities() {
.conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0) .conditionalAttr(getWeatherCondition(WeatherType.HAIL, WeatherType.SNOW), PostSummonAddBattlerTagAbAttr, BattlerTagType.ICE_FACE, 0)
// When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE // When weather changes to HAIL or SNOW while pokemon is fielded, add BattlerTagType.ICE_FACE
.attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW) .attr(PostWeatherChangeAddBattlerTagAttr, BattlerTagType.ICE_FACE, 0, WeatherType.HAIL, WeatherType.SNOW)
.attr(IceFaceMoveImmunityAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE)) .attr(IceFaceBlockPhysicalAbAttr, (target, user, move) => move.category === MoveCategory.PHYSICAL && !!target.getTag(BattlerTagType.ICE_FACE), 0)
.ignorable(), .ignorable(),
new Ability(Abilities.POWER_SPOT, 8) new Ability(Abilities.POWER_SPOT, 8)
.attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3), .attr(AllyMoveCategoryPowerBoostAbAttr, [MoveCategory.SPECIAL, MoveCategory.PHYSICAL], 1.3),

View File

@ -4,6 +4,7 @@ import GameManager from "#app/test/utils/gameManager";
import * as overrides from "#app/overrides"; import * as overrides from "#app/overrides";
import { Species } from "#enums/species"; import { Species } from "#enums/species";
import { import {
MoveEffectPhase,
MoveEndPhase, MoveEndPhase,
TurnEndPhase, TurnEndPhase,
TurnInitPhase, TurnInitPhase,
@ -52,6 +53,34 @@ describe("Abilities - Ice Face", () => {
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBe(undefined); expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBe(undefined);
}); });
it("takes no damage from multihit physical move and transforms to Noice", async () => {
vi.spyOn(overrides, "MOVESET_OVERRIDE", "get").mockReturnValue([Moves.SURGING_STRIKES]);
vi.spyOn(overrides, "OPP_LEVEL_OVERRIDE", "get").mockReturnValue(5);
await game.startBattle([Species.HITMONLEE]);
game.doAttack(getMovePosition(game.scene, 0, Moves.SURGING_STRIKES));
const eiscue = game.scene.getEnemyPokemon();
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeDefined();
// First hit
await game.phaseInterceptor.to(MoveEffectPhase);
expect(eiscue.hp).equals(eiscue.getMaxHp());
expect(eiscue.formIndex).toBe(icefaceForm);
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeUndefined();
// Second hit
await game.phaseInterceptor.to(MoveEffectPhase);
expect(eiscue.hp).lessThan(eiscue.getMaxHp());
expect(eiscue.formIndex).toBe(noiceForm);
await game.phaseInterceptor.to(MoveEndPhase);
expect(eiscue.hp).lessThan(eiscue.getMaxHp());
expect(eiscue.formIndex).toBe(noiceForm);
expect(eiscue.getTag(BattlerTagType.ICE_FACE)).toBeUndefined();
});
it("takes damage from special moves", async () => { it("takes damage from special moves", async () => {
await game.startBattle([Species.MAGIKARP]); await game.startBattle([Species.MAGIKARP]);