From 0bd9dd6ee83a956ace9d048f7799a42b37febab7 Mon Sep 17 00:00:00 2001 From: ghostyboyy97 <106448956+ghostyboyy97@users.noreply.github.com> Date: Sat, 8 Nov 2025 11:21:16 -0500 Subject: [PATCH] fix (contrary): Contrary stat down handling in MoveEffectInPlus (#8165) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_ai_util.c | 43 ++++++++++++++++++++++++++++++++++ test/battle/ability/contrary.c | 27 +++++++++++++++++++++ 2 files changed, 70 insertions(+) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index d866e5b0d0..353705cefc 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1041,6 +1041,49 @@ static bool32 AI_IsMoveEffectInPlus(u32 battlerAtk, u32 battlerDef, u32 move, s3 { switch (additionalEffect->moveEffect) { + case MOVE_EFFECT_ATK_MINUS_1: + case MOVE_EFFECT_ATK_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK)) + return TRUE; + break; + case MOVE_EFFECT_DEF_MINUS_1: + case MOVE_EFFECT_DEF_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK)) + return TRUE; + break; + case MOVE_EFFECT_SPD_MINUS_1: + case MOVE_EFFECT_SPD_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF)) + return TRUE; + break; + case MOVE_EFFECT_SP_ATK_MINUS_1: + case MOVE_EFFECT_SP_ATK_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPATK)) + return TRUE; + break; + case MOVE_EFFECT_SP_DEF_MINUS_1: + case MOVE_EFFECT_SP_DEF_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPDEF)) + return TRUE; + break; + case MOVE_EFFECT_EVS_MINUS_1: + case MOVE_EFFECT_EVS_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_EVASION)) + return TRUE; + break; + case MOVE_EFFECT_ACC_MINUS_1: + case MOVE_EFFECT_ACC_MINUS_2: + if (abilityAtk == ABILITY_CONTRARY && BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ACC)) + return TRUE; + break; + case MOVE_EFFECT_ATK_DEF_DOWN: + if (abilityAtk == ABILITY_CONTRARY && (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK) || BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF))) + return TRUE; + break; + case MOVE_EFFECT_DEF_SPDEF_DOWN: + if (abilityAtk == ABILITY_CONTRARY && (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_DEF) || BattlerStatCanRise(battlerAtk, abilityAtk, STAT_SPDEF))) + return TRUE; + break; case MOVE_EFFECT_ATK_PLUS_1: case MOVE_EFFECT_ATK_PLUS_2: if (BattlerStatCanRise(battlerAtk, abilityAtk, STAT_ATK)) diff --git a/test/battle/ability/contrary.c b/test/battle/ability/contrary.c index c69360a1e1..850ca60734 100644 --- a/test/battle/ability/contrary.c +++ b/test/battle/ability/contrary.c @@ -242,4 +242,31 @@ SINGLE_BATTLE_TEST("Sticky Web raises Speed by 1 for Contrary mon on switch-in") } } +AI_SINGLE_BATTLE_TEST("AI sees Contrary-effected moves correctly in MoveEffectInPlus instead of as a neutral effect") +{ + GIVEN{ + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_HERACROSS){ + Level(44); + HP(1); + Speed(5); + Nature(NATURE_ADAMANT); + Item(ITEM_LOADED_DICE); + Moves(MOVE_PIN_MISSILE); + } + OPPONENT(SPECIES_SERPERIOR){ + Level(44); + Speed(10); + Nature(NATURE_TIMID); + Ability(ABILITY_CONTRARY); + Moves(MOVE_DRAGON_PULSE, MOVE_SPIN_OUT, MOVE_HIDDEN_POWER, MOVE_GLARE); + } + } WHEN { + TURN{ + MOVE(player, MOVE_PIN_MISSILE); + EXPECT_MOVE(opponent, MOVE_SPIN_OUT); // previously all 107, now sees speed can rise w/ Contrary + } + } +} + TO_DO_BATTLE_TEST("Contrary does not invert stat changes that have been Baton-passed")