Fixes Protective Pads preventing Poison Touch activation (#9222)

This commit is contained in:
PhallenTree 2026-02-16 13:25:19 +00:00 committed by GitHub
parent a3ab5bf693
commit 757cbc2e7d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 144 additions and 3 deletions

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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);
}
}
}

View File

@ -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);
}
}
}
}

View File

@ -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
}
}

View File

@ -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);
}
}