From 757cbc2e7d736c38459c69a371fb1beb3068d197 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Mon, 16 Feb 2026 13:25:19 +0000 Subject: [PATCH] Fixes Protective Pads preventing Poison Touch activation (#9222) --- src/battle_util.c | 6 ++--- test/battle/ability/fluffy.c | 22 +++++++++++++++++++ test/battle/ability/pickpocket.c | 29 +++++++++++++++++++++++++ test/battle/ability/poison_touch.c | 35 ++++++++++++++++++++++++++++++ test/battle/ability/tough_claws.c | 24 ++++++++++++++++++++ test/battle/ability/unseen_fist.c | 31 ++++++++++++++++++++++++++ 6 files changed, 144 insertions(+), 3 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 9760173f68..dd08a155ef 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5418,7 +5418,7 @@ u32 AbilityBattleEffects(enum AbilityEffect caseID, u32 battler, enum Ability ab if (IsBattlerAlive(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && CanBePoisoned(gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerTarget)) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) + && IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker), move) && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target && RandomPercentage(RNG_POISON_TOUCH, 30)) { @@ -8383,12 +8383,12 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(struct DamageContext *ctx) } break; case ABILITY_FLUFFY: - if (ctx->moveType == TYPE_FIRE && !IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ABILITY_NONE, ctx->holdEffectAtk, ctx->move)) + if (ctx->moveType == TYPE_FIRE && !IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ctx->abilityAtk, ctx->holdEffectAtk, ctx->move)) { modifier = UQ_4_12(2.0); recordAbility = TRUE; } - if (ctx->moveType != TYPE_FIRE && IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ABILITY_NONE, ctx->holdEffectAtk, ctx->move)) + if (ctx->moveType != TYPE_FIRE && IsMoveMakingContact(ctx->battlerAtk, ctx->battlerDef, ctx->abilityAtk, ctx->holdEffectAtk, ctx->move)) { modifier = UQ_4_12(0.5); recordAbility = TRUE; diff --git a/test/battle/ability/fluffy.c b/test/battle/ability/fluffy.c index 68afbd8993..964e7d9b06 100644 --- a/test/battle/ability/fluffy.c +++ b/test/battle/ability/fluffy.c @@ -70,6 +70,7 @@ SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct conta PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { + ASSUME(MoveMakesContact(MOVE_THUNDER_PUNCH)); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PROTECTIVE_PADS); } OPPONENT(SPECIES_STUFFUL) { Ability(ability); } } WHEN { @@ -88,6 +89,8 @@ SINGLE_BATTLE_TEST("Fluffy does not halve damage taken from moves that make dire PARAMETRIZE { ability = ABILITY_KLUTZ; } PARAMETRIZE { ability = ABILITY_FLUFFY; } GIVEN { + ASSUME(MoveMakesContact(MOVE_THUNDER_PUNCH)); + ASSUME(IsPunchingMove(MOVE_THUNDER_PUNCH)); PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PUNCHING_GLOVE); } OPPONENT(SPECIES_STUFFUL) { Ability(ability); } } WHEN { @@ -99,3 +102,22 @@ SINGLE_BATTLE_TEST("Fluffy does not halve damage taken from moves that make dire EXPECT_EQ(results[0].damage, results[1].damage); } } + +SINGLE_BATTLE_TEST("Fluffy does not halve damage taken from moves that make direct contact but are ignored by Long Reach", s16 damage) +{ + enum Ability ability; + PARAMETRIZE { ability = ABILITY_KLUTZ; } + PARAMETRIZE { ability = ABILITY_FLUFFY; } + GIVEN { + ASSUME(MoveMakesContact(MOVE_THUNDER_PUNCH)); + PLAYER(SPECIES_ROWLET) { Ability(ABILITY_LONG_REACH); } + OPPONENT(SPECIES_STUFFUL) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_THUNDER_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_PUNCH, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} diff --git a/test/battle/ability/pickpocket.c b/test/battle/ability/pickpocket.c index e6b92a6e8e..559a8e2a21 100644 --- a/test/battle/ability/pickpocket.c +++ b/test/battle/ability/pickpocket.c @@ -310,3 +310,32 @@ SINGLE_BATTLE_TEST("Pickpocket does not prevent King's Rock or Razor Fang flinch EXPECT(player->item == ITEM_NONE); } } + +SINGLE_BATTLE_TEST("Pickpocket activates when user has Protective Pads, but not with Punching Glove or Long Reach") +{ + u32 item, ability; + + PARAMETRIZE { item = ITEM_PROTECTIVE_PADS; ability = ABILITY_OVERGROW; } + PARAMETRIZE { item = ITEM_PUNCHING_GLOVE; ability = ABILITY_OVERGROW; } + PARAMETRIZE { item = ITEM_NONE; ability = ABILITY_LONG_REACH; } + + GIVEN { + ASSUME(MoveMakesContact(MOVE_MACH_PUNCH)); + ASSUME(IsPunchingMove(MOVE_MACH_PUNCH)); + ASSUME(GetItemHoldEffect(ITEM_PROTECTIVE_PADS) == HOLD_EFFECT_PROTECTIVE_PADS); + ASSUME(GetItemHoldEffect(ITEM_PUNCHING_GLOVE) == HOLD_EFFECT_PUNCHING_GLOVE); + ASSUME(GetItemHoldEffect(ITEM_FOCUS_SASH) == HOLD_EFFECT_FOCUS_SASH); + PLAYER(SPECIES_DECIDUEYE) { Ability(ability); Item(item); } + OPPONENT(SPECIES_SNEASEL) { Ability(ABILITY_PICKPOCKET); Item(ITEM_FOCUS_SASH); } + } WHEN { + TURN { MOVE(player, MOVE_MACH_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MACH_PUNCH, player); + + if (item == ITEM_PROTECTIVE_PADS) { + ABILITY_POPUP(opponent, ABILITY_PICKPOCKET); + } else { + NOT ABILITY_POPUP(opponent, ABILITY_PICKPOCKET); + } + } +} diff --git a/test/battle/ability/poison_touch.c b/test/battle/ability/poison_touch.c index e3775d7427..b0c8c73329 100644 --- a/test/battle/ability/poison_touch.c +++ b/test/battle/ability/poison_touch.c @@ -75,3 +75,38 @@ SINGLE_BATTLE_TEST("Poison Touch applies between multi-hit move hits") STATUS_ICON(opponent, poison: TRUE); } } + +SINGLE_BATTLE_TEST("Poison Touch activates when user has Protective Pads, but not with Punching Glove") +{ + u32 item; + + PARAMETRIZE { item = ITEM_PROTECTIVE_PADS; } + PARAMETRIZE { item = ITEM_PUNCHING_GLOVE; } + + GIVEN { + ASSUME(MoveMakesContact(MOVE_MACH_PUNCH)); + ASSUME(IsPunchingMove(MOVE_MACH_PUNCH)); + ASSUME(GetItemHoldEffect(ITEM_PROTECTIVE_PADS) == HOLD_EFFECT_PROTECTIVE_PADS); + ASSUME(GetItemHoldEffect(ITEM_PUNCHING_GLOVE) == HOLD_EFFECT_PUNCHING_GLOVE); + PLAYER(SPECIES_GRIMER) { Ability(ABILITY_POISON_TOUCH); Item(item); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MACH_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MACH_PUNCH, player); + + if (item != ITEM_PUNCHING_GLOVE) { + ABILITY_POPUP(player, ABILITY_POISON_TOUCH); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + MESSAGE("The opposing Wobbuffet was poisoned by Grimer's Poison Touch!"); + STATUS_ICON(opponent, poison: TRUE); + } else { + NONE_OF { + ABILITY_POPUP(player, ABILITY_POISON_TOUCH); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + MESSAGE("The opposing Wobbuffet was poisoned by Grimer's Poison Touch!"); + STATUS_ICON(opponent, poison: TRUE); + } + } + } +} diff --git a/test/battle/ability/tough_claws.c b/test/battle/ability/tough_claws.c index 4e6f4ecf8b..f2dd887fe4 100644 --- a/test/battle/ability/tough_claws.c +++ b/test/battle/ability/tough_claws.c @@ -2,3 +2,27 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write Tough Claws (Ability) test titles") + +SINGLE_BATTLE_TEST("Tough Claws boosts contact moves when user has Protective Pads, but not with Punching Glove", s16 damage) +{ + u32 item; + + PARAMETRIZE { item = ITEM_PROTECTIVE_PADS; } + PARAMETRIZE { item = ITEM_PUNCHING_GLOVE; } + + GIVEN { + ASSUME(MoveMakesContact(MOVE_MACH_PUNCH)); + ASSUME(IsPunchingMove(MOVE_MACH_PUNCH)); + ASSUME(GetItemHoldEffect(ITEM_PROTECTIVE_PADS) == HOLD_EFFECT_PROTECTIVE_PADS); + ASSUME(GetItemHoldEffect(ITEM_PUNCHING_GLOVE) == HOLD_EFFECT_PUNCHING_GLOVE); + PLAYER(SPECIES_BARBARACLE) { Ability(ABILITY_TOUGH_CLAWS); Item(item); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_MACH_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MACH_PUNCH, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[1].damage, UQ_4_12(1.18), results[0].damage); // 1.3 / 1.1 ~= 1.18 + } +} diff --git a/test/battle/ability/unseen_fist.c b/test/battle/ability/unseen_fist.c index 046ef7d2fb..da5880c042 100644 --- a/test/battle/ability/unseen_fist.c +++ b/test/battle/ability/unseen_fist.c @@ -1,4 +1,35 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS +{ + ASSUME(MoveMakesContact(MOVE_SCRATCH)); + ASSUME(GetMoveEffect(MOVE_PROTECT) == EFFECT_PROTECT); +} + TO_DO_BATTLE_TEST("TODO: Write Unseen Fist (Ability) test titles") + +SINGLE_BATTLE_TEST("Unseen Fist ignores Protect when user has Protective Pads, but not with Punching Glove", s16 damage) +{ + u32 item; + + PARAMETRIZE { item = ITEM_PROTECTIVE_PADS; } + PARAMETRIZE { item = ITEM_PUNCHING_GLOVE; } + + GIVEN { + ASSUME(MoveMakesContact(MOVE_MACH_PUNCH)); + ASSUME(IsPunchingMove(MOVE_MACH_PUNCH)); + ASSUME(GetItemHoldEffect(ITEM_PROTECTIVE_PADS) == HOLD_EFFECT_PROTECTIVE_PADS); + ASSUME(GetItemHoldEffect(ITEM_PUNCHING_GLOVE) == HOLD_EFFECT_PUNCHING_GLOVE); + PLAYER(SPECIES_URSHIFU) { Ability(ABILITY_UNSEEN_FIST); Item(item); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_MACH_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent); + if (item != ITEM_PUNCHING_GLOVE) + ANIMATION(ANIM_TYPE_MOVE, MOVE_MACH_PUNCH, player); + else + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MACH_PUNCH, player); + } +}