diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a353b44ba8..26ee741f71 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -6834,10 +6834,11 @@ BattleScript_PowderMoveNoEffect:: pause B_WAIT_TIME_SHORT jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_PowderMoveNoEffectPrint jumpifability BS_TARGET, ABILITY_OVERCOAT, BattleScript_PowderMoveNoEffectOvercoat + setlastuseditem BS_TARGET printstring STRINGID_SAFETYGOGGLESPROTECTED goto BattleScript_PowderMoveNoEffectWaitMsg BattleScript_PowderMoveNoEffectOvercoat: - call BattleScript_AbilityPopUp + call BattleScript_AbilityPopUpTarget BattleScript_PowderMoveNoEffectPrint: printstring STRINGID_ITDOESNTAFFECT BattleScript_PowderMoveNoEffectWaitMsg: diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 1964e45d53..46e1e2d7b7 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -151,7 +151,6 @@ u32 CountPositiveStatStages(u32 battlerId); u32 CountNegativeStatStages(u32 battlerId); // move checks -bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category); enum MoveComparisonResult AI_WhichMoveBetter(u32 move1, u32 move2, u32 battlerAtk, u32 battlerDef, s32 noOfHitsToKo); struct SimulatedDamage AI_CalcDamageSaveBattlers(u32 move, u32 battlerAtk, u32 battlerDef, uq4_12_t *typeEffectiveness, enum AIConsiderGimmick considerGimmickAtk, enum AIConsiderGimmick considerGimmickDef); diff --git a/include/battle_util.h b/include/battle_util.h index 7bb8bc7292..fc88ee02c6 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -416,5 +416,6 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u bool32 IsSemiInvulnerable(u32 battler, enum SemiInvulnerableExclusion excludeCommander); bool32 BreaksThroughSemiInvulnerablity(u32 battler, u32 move); bool32 HasPartnerTrainer(u32 battler); +bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum ItemHoldEffect holdEffect); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/battle.h b/include/config/battle.h index 2b9e9fdecc..67008ba027 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -166,6 +166,7 @@ #define B_BATTLE_BOND GEN_LATEST // In Gen9+, Battle Bond increases Atk, SpAtk and Speed by one stage, once per battle #define B_ATE_MULTIPLIER GEN_LATEST // In Gen7+, -ate abilities (Aerilate, Galvanize, Normalize, Pixilate, Refrigerate) multiply damage by 1.2. Otherwise, it's 1.3, except Normalize which has no multiplier. #define B_DEFIANT_STICKY_WEB GEN_LATEST // In Gen9+, Defiant activates on Sticky Web regardless of who set it up. In Gen8, Defiant does not activate on Sticky Web set up by an ally after Court Change swaps its side. +#define B_POWDER_OVERCOAT GEN_LATEST // In Gen6+, Overcoat blocks powder and spore moves from affecting the user. // Item settings #define B_HP_BERRIES GEN_LATEST // In Gen4+, berries which restore HP activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn. diff --git a/include/constants/generational_changes.h b/include/constants/generational_changes.h index 7be7998d9e..88584e9978 100644 --- a/include/constants/generational_changes.h +++ b/include/constants/generational_changes.h @@ -42,6 +42,7 @@ enum GenConfigTag GEN_CONFIG_DESTINY_BOND_FAIL, GEN_CONFIG_POWDER_RAIN, GEN_CONFIG_POWDER_GRASS, + GEN_CONFIG_POWDER_OVERCOAT, GEN_CONFIG_OBLIVIOUS_TAUNT, GEN_CONFIG_TOXIC_NEVER_MISS, GEN_CONFIG_PARALYZE_ELECTRIC, diff --git a/include/generational_changes.h b/include/generational_changes.h index 9b6b385c7e..e8b701d096 100644 --- a/include/generational_changes.h +++ b/include/generational_changes.h @@ -45,6 +45,7 @@ static const u8 sGenerationalChanges[GEN_CONFIG_COUNT] = [GEN_CONFIG_DESTINY_BOND_FAIL] = B_DESTINY_BOND_FAIL, [GEN_CONFIG_POWDER_RAIN] = B_POWDER_RAIN, [GEN_CONFIG_POWDER_GRASS] = B_POWDER_GRASS, + [GEN_CONFIG_POWDER_OVERCOAT] = B_POWDER_OVERCOAT, [GEN_CONFIG_OBLIVIOUS_TAUNT] = B_OBLIVIOUS_TAUNT, [GEN_CONFIG_TOXIC_NEVER_MISS] = B_TOXIC_NEVER_MISS, [GEN_CONFIG_PARALYZE_ELECTRIC] = B_PARALYZE_ELECTRIC, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 0c8c0bb1cd..23c008fdc3 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1089,7 +1089,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) SetTypeBeforeUsingMove(move, battlerAtk); moveType = GetBattleMoveType(move); - if (IsPowderMove(move) && !IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) + if (IsPowderMove(move) && !IsAffectedByPowderMove(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) RETURN_SCORE_MINUS(10); if (!BreaksThroughSemiInvulnerablity(battlerDef, move) && moveEffect != EFFECT_SEMI_INVULNERABLE && AI_IsFaster(battlerAtk, battlerDef, move, predictedMoveSpeedCheck, CONSIDER_PRIORITY)) @@ -4768,7 +4768,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) if (hasPartner && GetMoveTarget(move) == MOVE_TARGET_USER && !IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - && (!IsPowderMove(move) || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))) + && (!IsPowderMove(move) || IsAffectedByPowderMove(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef]))) // Rage Powder doesn't affect powder immunities { u32 predictedMoveOnPartner = gLastMoves[BATTLE_PARTNER(battlerAtk)]; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 8bed0234ee..fe97577ac7 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -530,16 +530,6 @@ bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler) return FALSE; } -// move checks -bool32 IsAffectedByPowder(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) -{ - if (ability == ABILITY_OVERCOAT - || (GetGenConfig(GEN_CONFIG_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) - || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES) - return FALSE; - return TRUE; -} - // This function checks if all physical/special moves are either unusable or unreasonable to use. // Consider a pokemon boosting their attack against a ghost pokemon having only normal-type physical attacks. bool32 MovesWithCategoryUnusable(u32 attacker, u32 target, enum DamageCategory category) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index face6eeb08..a98e023ff6 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1040,31 +1040,15 @@ u32 NumFaintedBattlersByAttacker(u32 battlerAtk) return numMonsFainted; } -bool32 IsMovePowderBlocked(u32 battlerAtk, u32 battlerDef, u32 move) +bool32 IsPowderMoveBlocked(u32 battlerAtk, u32 battlerDef, u32 move) { - bool32 effect = FALSE; + if (!IsPowderMove(move) + || battlerAtk == battlerDef + || IsAffectedByPowderMove(battlerDef, GetBattlerAbility(battlerDef), GetBattlerHoldEffect(battlerDef, TRUE))) + return FALSE; - if (IsPowderMove(move) && (battlerAtk != battlerDef)) - { - if (GetGenConfig(GEN_CONFIG_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; + gBattlescriptCurrInstr = BattleScript_PowderMoveNoEffect; + return TRUE; } bool32 EmergencyExitCanBeTriggered(u32 battler) @@ -1151,7 +1135,7 @@ static void Cmd_attackcanceler(void) return; } - if (IsMovePowderBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + if (IsPowderMoveBlocked(gBattlerAttacker, gBattlerTarget, gCurrentMove)) return; if (!gBattleMons[gBattlerAttacker].pp[gCurrMovePos] && gCurrentMove != MOVE_STRUGGLE diff --git a/src/battle_util.c b/src/battle_util.c index f6a61ffde4..a5039231e4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -310,7 +310,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) if (effect == EFFECT_PURSUIT && IsPursuitTargetSet()) return FALSE; - if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) + if (gSideTimers[defSide].followmePowder && !IsAffectedByPowderMove(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) return FALSE; return TRUE; @@ -4689,9 +4689,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_EFFECT_SPORE: { u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); - if ((GetGenConfig(GEN_CONFIG_POWDER_GRASS) < GEN_6 || !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS)) - && abilityAtk != ABILITY_OVERCOAT - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) + enum ItemHoldEffect holdEffectAtk = GetBattlerHoldEffect(gBattlerAttacker, TRUE); + if (IsAffectedByPowderMove(gBattlerAttacker, abilityAtk, holdEffectAtk)) { u32 poison, paralysis, sleep; @@ -4718,7 +4717,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && CanBeSlept(gBattlerTarget, gBattlerAttacker, abilityAtk, NOT_BLOCKED_BY_SLEEP_CLAUSE) - && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, abilityAtk, holdEffectAtk, move)) { if (IsSleepClauseEnabled()) gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; @@ -11965,3 +11964,12 @@ static bool32 IsOpposingSideEmpty(u32 battler) return FALSE; return TRUE; } + +bool32 IsAffectedByPowderMove(u32 battler, u32 ability, enum ItemHoldEffect holdEffect) +{ + if ((GetGenConfig(GEN_CONFIG_POWDER_OVERCOAT) >= GEN_6 && ability == ABILITY_OVERCOAT) + || (GetGenConfig(GEN_CONFIG_POWDER_GRASS) >= GEN_6 && IS_BATTLER_OF_TYPE(battler, TYPE_GRASS)) + || holdEffect == HOLD_EFFECT_SAFETY_GOGGLES) + return FALSE; + return TRUE; +} diff --git a/test/battle/ability/overcoat.c b/test/battle/ability/overcoat.c index 6d7b5f2a8d..cfdbad7de3 100644 --- a/test/battle/ability/overcoat.c +++ b/test/battle/ability/overcoat.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("Overcoat blocks powder and spore moves (Gen6+)") PARAMETRIZE { gen = GEN_5; } PARAMETRIZE { gen = GEN_6; } GIVEN { - WITH_CONFIG(GEN_CONFIG_POWDER_GRASS, gen); + WITH_CONFIG(GEN_CONFIG_POWDER_OVERCOAT, gen); ASSUME(IsPowderMove(MOVE_STUN_SPORE)); PLAYER(SPECIES_WYNAUT); OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); }