diff --git a/include/config/battle.h b/include/config/battle.h index 8ef347cdcd..478210101e 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -186,6 +186,7 @@ #define B_SAFARI_BALL_MODIFIER GEN_LATEST // In Gen8+, Safari Ball's catch multiplier was reduced from x1.5 to x1. #define B_FRIEND_BALL_MODIFIER GEN_LATEST // In Gen8+, Friend Ball's friendship boost was reduced from 200 to 150. #define B_SERENE_GRACE_BOOST GEN_LATEST // In Gen5+, Serene Grace boosts the added flinch chance of King's Rock and Razor Fang. +#define B_IRON_BALL GEN_LATEST // In Gen5+, Flying-type Pokemon holding Iron Ball take x1 damage from Ground-type moves regardless of their other types, except during Inverse Battles or if the Pokemon is grounded by any other effect. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/src/battle_util.c b/src/battle_util.c index afa9b5b94a..ccd4d6fb2d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8816,12 +8816,24 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) return isProtected; } -// Only called directly when calculating damage type effectiveness -static bool32 IsBattlerGroundedInverseCheck(u32 battler, bool32 considerInverse) +enum InverseBattleCheck +{ + INVERSE_BATTLE, + NOT_INVERSE_BATTLE +}; + +enum IronBallCheck +{ + CHECK_IRON_BALL, + IGNORE_IRON_BALL +}; + +// Only called directly when calculating damage type effectiveness, and Iron Ball's type effectiveness mechanics +static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck checkInverse, enum IronBallCheck checkIronBall) { u32 holdEffect = GetBattlerHoldEffect(battler, TRUE); - if (holdEffect == HOLD_EFFECT_IRON_BALL) + if (!(checkIronBall == IGNORE_IRON_BALL) && holdEffect == HOLD_EFFECT_IRON_BALL) return TRUE; if (gFieldStatuses & STATUS_FIELD_GRAVITY) return TRUE; @@ -8837,14 +8849,14 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, bool32 considerInverse) return FALSE; if ((AI_DATA->aiCalcInProgress ? AI_DATA->abilities[battler] : GetBattlerAbility(battler)) == ABILITY_LEVITATE) return FALSE; - if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!considerInverse || !FlagGet(B_FLAG_INVERSE_BATTLE))) + if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!(checkInverse == INVERSE_BATTLE) || !FlagGet(B_FLAG_INVERSE_BATTLE))) return FALSE; return TRUE; } bool32 IsBattlerGrounded(u32 battler) { - return IsBattlerGroundedInverseCheck(battler, FALSE); + return IsBattlerGroundedInverseCheck(battler, NOT_INVERSE_BATTLE, CHECK_IRON_BALL); } u32 GetMoveSlot(u16 *moves, u32 move) @@ -10685,7 +10697,7 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov if (B_GLARE_GHOST < GEN_4 && move == MOVE_GLARE && IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST)) modifier = UQ_4_12(0.0); } - else if (moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(battlerDef, TRUE) && !(MoveIgnoresTypeIfFlyingAndUngrounded(move))) + else if (moveType == TYPE_GROUND && !IsBattlerGroundedInverseCheck(battlerDef, INVERSE_BATTLE, CHECK_IRON_BALL) && !(MoveIgnoresTypeIfFlyingAndUngrounded(move))) { modifier = UQ_4_12(0.0); if (recordAbilities && defAbility == ABILITY_LEVITATE) @@ -10710,6 +10722,17 @@ static inline uq4_12_t CalcTypeEffectivenessMultiplierInternal(u32 move, u32 mov modifier = UQ_4_12(1.0); } + // Iron Ball ignores type modifiers for flying-type mons if it is the only source of grounding + if (B_IRON_BALL >= GEN_5 + && moveType == TYPE_GROUND + && IS_BATTLER_OF_TYPE(battlerDef, TYPE_FLYING) + && GetBattlerHoldEffect(battlerDef, TRUE) == HOLD_EFFECT_IRON_BALL + && !IsBattlerGroundedInverseCheck(battlerDef, NOT_INVERSE_BATTLE, IGNORE_IRON_BALL) + && !FlagGet(B_FLAG_INVERSE_BATTLE)) + { + modifier = UQ_4_12(1.0); + } + if (((defAbility == ABILITY_WONDER_GUARD && modifier <= UQ_4_12(1.0)) || (defAbility == ABILITY_TELEPATHY && battlerDef == BATTLE_PARTNER(battlerAtk))) && GetMovePower(move) != 0) diff --git a/test/battle/hold_effect/iron_ball.c b/test/battle/hold_effect/iron_ball.c new file mode 100644 index 0000000000..134c47d9af --- /dev/null +++ b/test/battle/hold_effect/iron_ball.c @@ -0,0 +1,22 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS{ + ASSUME(gItemsInfo[ITEM_IRON_BALL].holdEffect == HOLD_EFFECT_IRON_BALL); +} + +SINGLE_BATTLE_TEST("Ground-type moves do neutral damage to non-grounded Flying types holding Iron Ball regardless of other typings") //gen5+ only +{ + ASSUME(B_IRON_BALL >= GEN_5); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SKARMORY) { Item(ITEM_IRON_BALL); }; + } WHEN { + TURN { MOVE(player, MOVE_EARTHQUAKE); }; + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, player); + NONE_OF { + MESSAGE("It's super effective!"); + } + } +}