From 41939630960858bceabe9d794c7c415d1b9e474d Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 18 Mar 2025 15:41:37 +0100 Subject: [PATCH] Fixes Cotton Spore failing if one of the targets blocks it (#6418) Co-authored-by: Bassoonian Co-authored-by: DizzyEggg --- include/battle_util.h | 2 +- src/battle_script_commands.c | 2 ++ src/battle_util.c | 50 +++++++++++++++------------- test/battle/move_effect/speed_down.c | 31 +++++++++++++++++ 4 files changed, 61 insertions(+), 24 deletions(-) create mode 100644 test/battle/move_effect/speed_down.c diff --git a/include/battle_util.h b/include/battle_util.h index 21760a47a3..6f1223b684 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -129,7 +129,6 @@ enum CANCELLER_STANCE_CHANGE_2, CANCELLER_WEATHER_PRIMAL, CANCELLER_DYNAMAX_BLOCKED, - CANCELLER_POWDER_MOVE, CANCELLER_POWDER_STATUS, CANCELLER_PROTEAN, CANCELLER_PSYCHIC_TERRAIN, @@ -348,5 +347,6 @@ bool32 IsPursuitTargetSet(void); void ClearPursuitValuesIfSet(u32 battler); void ClearPursuitValues(void); bool32 HasWeatherEffect(void); +bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move); #endif // GUARD_BATTLE_UTIL_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index c22aca8187..937c007acd 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1199,6 +1199,8 @@ static void Cmd_attackcanceler(void) return; if (gMovesInfo[gCurrentMove].effect == EFFECT_PARALYZE && AbilityBattleEffects(ABILITYEFFECT_ABSORBING, gBattlerTarget, 0, 0, gCurrentMove)) return; + if (IsMovePowderBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + return; if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE && !(gHitMarker & (HITMARKER_ALLOW_NO_PP | HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT)) diff --git a/src/battle_util.c b/src/battle_util.c index 30479a060e..9fb321118f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3588,28 +3588,6 @@ static void CancellerDynamaxBlocked(u32 *effect) } } -static void CancellerPowderMove(u32 *effect) -{ - if (IsPowderMove(gCurrentMove) && (gBattlerAttacker != gBattlerTarget)) - { - if (B_POWDER_GRASS >= GEN_6 - && (IS_BATTLER_OF_TYPE(gBattlerTarget, TYPE_GRASS) || GetBattlerAbility(gBattlerTarget) == ABILITY_OVERCOAT)) - { - gBattlerAbility = gBattlerTarget; - *effect = 1; - } - else if (GetBattlerHoldEffect(gBattlerTarget, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) - { - RecordItemEffectBattle(gBattlerTarget, HOLD_EFFECT_SAFETY_GOGGLES); - gLastUsedItem = gBattleMons[gBattlerTarget].item; - *effect = 1; - } - - if (*effect != 0) - gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; - } -} - static void CancellerPowderStatus(u32 *effect) { if (TryActivatePowderStatus(gCurrentMove)) @@ -3842,7 +3820,6 @@ static const MoveSuccessOrderCancellers sMoveSuccessOrderCancellers[] = [CANCELLER_STANCE_CHANGE_2] = CancellerStanceChangeTwo, [CANCELLER_WEATHER_PRIMAL] = CancellerWeatherPrimal, [CANCELLER_DYNAMAX_BLOCKED] = CancellerDynamaxBlocked, - [CANCELLER_POWDER_MOVE] = CancellerPowderMove, [CANCELLER_POWDER_STATUS] = CancellerPowderStatus, [CANCELLER_PROTEAN] = CancellerProtean, [CANCELLER_PSYCHIC_TERRAIN] = CancellerPsychicTerrain, @@ -12295,3 +12272,30 @@ bool32 HasWeatherEffect(void) return FALSE; return TRUE; } + +bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move) +{ + bool32 effect = FALSE; + + if (IsPowderMove(move) && (battlerAtk != battlerDef)) + { + if (B_POWDER_GRASS >= GEN_6 + && (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || GetBattlerAbility(battlerDef) == ABILITY_OVERCOAT)) + { + gBattlerAbility = battlerDef; + RecordAbilityBattle(gBattlerTarget, ABILITY_OVERCOAT); + effect = TRUE; + } + else if (GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_SAFETY_GOGGLES) + { + RecordItemEffectBattle(battlerDef, HOLD_EFFECT_SAFETY_GOGGLES); + gLastUsedItem = gBattleMons[battlerDef].item; + effect = TRUE; + } + + if (effect) + gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; + } + + return effect; +} diff --git a/test/battle/move_effect/speed_down.c b/test/battle/move_effect/speed_down.c new file mode 100644 index 0000000000..a3b5e26be8 --- /dev/null +++ b/test/battle/move_effect/speed_down.c @@ -0,0 +1,31 @@ +#include "global.h" +#include "test/battle.h" + +DOUBLE_BATTLE_TEST("Speed Down: Cotton Spore does not fail if it is blocked by one target") +{ + u32 abilityOne, abilityTwo; + + PARAMETRIZE { abilityOne = ABILITY_OVERCOAT; abilityTwo = ABILITY_SKILL_LINK; } + PARAMETRIZE { abilityOne = ABILITY_SKILL_LINK; abilityTwo = ABILITY_OVERCOAT; } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_COTTON_SPORE) == EFFECT_SPEED_DOWN_2); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SHELLDER) { Ability(abilityOne); } + OPPONENT(SPECIES_SHELLDER) { Ability(abilityTwo); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_COTTON_SPORE); } + } SCENE { + if (abilityOne == ABILITY_OVERCOAT) { + ABILITY_POPUP(opponentLeft, ABILITY_OVERCOAT); + ANIMATION(ANIM_TYPE_MOVE, MOVE_COTTON_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + } + else if (abilityTwo == ABILITY_OVERCOAT) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COTTON_SPORE, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + ABILITY_POPUP(opponentRight, ABILITY_OVERCOAT); + } + } +}