From ab1838ffd88c5d26f0d2fa1402f121eff1ff0194 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 18 Jun 2025 12:56:03 +0200 Subject: [PATCH] Repurposes IsMagicGuardProtected into a general function (#7114) --- include/battle_util.h | 2 +- src/battle_end_turn.c | 31 +++------ src/battle_main.c | 2 +- src/battle_script_commands.c | 21 +++--- src/battle_util.c | 126 +++++++++++++++++++++++------------ 5 files changed, 105 insertions(+), 77 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 24519ce022..8201d19432 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -236,7 +236,7 @@ u8 CheckMoveLimitations(u32 battler, u8 unusableMoves, u16 check); bool32 AreAllMovesUnusable(u32 battler); u8 GetImprisonedMovesCount(u32 battler, u16 move); s32 GetDrainedBigRootHp(u32 battler, s32 hp); -bool32 IsMagicGuardProtected(u32 battler, u32 ability); +bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck); u32 DoEndTurnEffects(void); bool32 HandleFaintedMonActions(void); void TryClearRageAndFuryCutter(void); diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 6cf45ded4d..11ccfdf745 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -108,15 +108,6 @@ enum FourthEventBlock FOURTH_EVENT_BLOCK_EJECT_PACK, }; -static inline bool32 IsBattlerProtectedByMagicGuard(u32 battler, u32 ability) -{ - if (ability != ABILITY_MAGIC_GUARD) - return FALSE; - - RecordAbilityBattle(battler, ability); - return TRUE; -} - static u32 GetBattlerSideForMessage(u32 side) { u32 battler = 0; @@ -244,7 +235,7 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) && !IS_BATTLER_ANY_TYPE(gBattlerAttacker, TYPE_ROCK, TYPE_GROUND, TYPE_STEEL) && !(gStatuses3[gBattlerAttacker] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES - && !IsBattlerProtectedByMagicGuard(battler, ability)) + && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; if (gBattleStruct->moveDamage[battler] == 0) @@ -268,7 +259,7 @@ static bool32 HandleEndTurnWeatherDamage(u32 battler) && !IS_BATTLER_OF_TYPE(battler, TYPE_ICE) && !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) && GetBattlerHoldEffect(battler, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES - && !IsBattlerProtectedByMagicGuard(battler, ability)) + && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; if (gBattleStruct->moveDamage[battler] == 0) @@ -443,7 +434,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) { if (IsBattlerAlive(battler) && !IS_BATTLER_OF_TYPE(battler, gSideTimers[side].damageNonTypesType) - && !IsBattlerProtectedByMagicGuard(battler, GetBattlerAbility(battler))) + && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { gBattlerAttacker = battler; gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 6; @@ -583,7 +574,7 @@ static bool32 HandleEndTurnLeechSeed(u32 battler) if (gStatuses3[battler] & STATUS3_LEECHSEED && IsBattlerAlive(gStatuses3[battler] & STATUS3_LEECHSEED_BATTLER) && IsBattlerAlive(battler) - && !IsBattlerProtectedByMagicGuard(battler, GetBattlerAbility(battler))) + && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { gBattlerTarget = gStatuses3[battler] & STATUS3_LEECHSEED_BATTLER; // Notice gBattlerTarget is actually the HP receiver. gBattleScripting.animArg1 = gBattlerTarget; @@ -622,7 +613,7 @@ static bool32 HandleEndTurnPoison(u32 battler) if ((gBattleMons[battler].status1 & STATUS1_POISON || gBattleMons[battler].status1 & STATUS1_TOXIC_POISON) && IsBattlerAlive(battler) - && !IsBattlerProtectedByMagicGuard(battler, ability)) + && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { if (ability == ABILITY_POISON_HEAL) { @@ -670,7 +661,7 @@ static bool32 HandleEndTurnBurn(u32 battler) if (gBattleMons[battler].status1 & STATUS1_BURN && IsBattlerAlive(battler) - && !IsBattlerProtectedByMagicGuard(battler, ability)) + && !IsAbilityAndRecord(battler, ability, ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); if (ability == ABILITY_HEATPROOF) @@ -696,7 +687,7 @@ static bool32 HandleEndTurnFrostbite(u32 battler) if (gBattleMons[battler].status1 & STATUS1_FROSTBITE && IsBattlerAlive(battler) - && !IsBattlerProtectedByMagicGuard(battler, GetBattlerAbility(battler))) + && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / (B_BURN_DAMAGE >= GEN_7 ? 16 : 8); if (gBattleStruct->moveDamage[battler] == 0) @@ -716,7 +707,7 @@ static bool32 HandleEndTurnNightmare(u32 battler) if (gBattleMons[battler].status2 & STATUS2_NIGHTMARE && IsBattlerAlive(battler) - && !IsBattlerProtectedByMagicGuard(battler, GetBattlerAbility(battler))) + && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { if (gBattleMons[battler].status1 & STATUS1_SLEEP) { @@ -743,7 +734,7 @@ static bool32 HandleEndTurnCurse(u32 battler) if (gBattleMons[battler].status2 & STATUS2_CURSED && IsBattlerAlive(battler) - && !IsBattlerProtectedByMagicGuard(battler, GetBattlerAbility(battler))) + && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 4; if (gBattleStruct->moveDamage[battler] == 0) @@ -765,7 +756,7 @@ static bool32 HandleEndTurnWrap(u32 battler) { if (--gDisableStructs[battler].wrapTurns != 0) { - if (IsBattlerProtectedByMagicGuard(battler, GetBattlerAbility(battler))) + if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) return effect; gBattleScripting.animArg1 = gBattleStruct->wrappedMove[battler]; @@ -800,7 +791,7 @@ static bool32 HandleEndTurnSaltCure(u32 battler) if (gStatuses4[battler] & STATUS4_SALT_CURE && IsBattlerAlive(battler) - && !IsBattlerProtectedByMagicGuard(battler, GetBattlerAbility(battler))) + && !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MAGIC_GUARD)) { if (IS_BATTLER_ANY_TYPE(battler, TYPE_STEEL, TYPE_WATER)) gBattleStruct->moveDamage[battler] = gBattleMons[battler].maxHP / 4; diff --git a/src/battle_main.c b/src/battle_main.c index ebf1ce36c6..98697e4f97 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4810,7 +4810,7 @@ s32 GetBattleMovePriority(u32 battler, u32 ability, u32 move) { priority++; } - else if (ability == ABILITY_PRANKSTER && IsBattleMoveStatus(move)) + else if (IsBattleMoveStatus(move) && IsAbilityAndRecord(battler, ability, ABILITY_PRANKSTER)) { gProtectStructs[battler].pranksterElevated = 1; priority++; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 23c0aeaa0d..6ad315d144 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3090,11 +3090,8 @@ u8 GetBattlerTurnOrderNum(u8 battler) static void CheckSetUnburden(u8 battler) { - if (GetBattlerAbility(battler) == ABILITY_UNBURDEN) - { + if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_UNBURDEN)) gDisableStructs[battler].unburdenActive = TRUE; - RecordAbilityBattle(battler, ABILITY_UNBURDEN); - } } // battlerStealer steals the item of battlerItem @@ -6331,7 +6328,7 @@ static void Cmd_moveend(void) case PROTECT_SPIKY_SHIELD: if (moveEffect != EFFECT_COUNTER && !IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) - && !IsMagicGuardProtected(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) + && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 8; @@ -12924,11 +12921,11 @@ static void Cmd_tryKO(void) } else { - if ((((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS) + if (gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level + && ((gStatuses3[gBattlerTarget] & STATUS3_ALWAYS_HITS && gDisableStructs[gBattlerTarget].battlerWithSureHit == gBattlerAttacker) - || GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD - || targetAbility == ABILITY_NO_GUARD) - && gBattleMons[gBattlerAttacker].level >= gBattleMons[gBattlerTarget].level) + || IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_NO_GUARD) + || IsAbilityAndRecord(gBattlerTarget, targetAbility, ABILITY_NO_GUARD))) { lands = TRUE; } @@ -15458,7 +15455,7 @@ bool32 DoesSubstituteBlockMove(u32 battlerAtk, u32 battlerDef, u32 move) return FALSE; else if (MoveIgnoresSubstitute(move)) return FALSE; - else if (GetBattlerAbility(battlerAtk) == ABILITY_INFILTRATOR) + else if (IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_INFILTRATOR)) return FALSE; else return TRUE; @@ -15470,7 +15467,7 @@ bool32 DoesDisguiseBlockMove(u32 battler, u32 move) || gBattleMons[battler].status2 & STATUS2_TRANSFORMED || (!gProtectStructs[battler].confusionSelfDmg && (IsBattleMoveStatus(move) || gHitMarker & HITMARKER_PASSIVE_DAMAGE)) || gHitMarker & HITMARKER_IGNORE_DISGUISE - || GetBattlerAbility(battler) != ABILITY_DISGUISE) + || !IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_DISGUISE)) return FALSE; else return TRUE; @@ -17758,7 +17755,7 @@ void BS_TryGulpMissile(void) if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) && (gCurrentMove == MOVE_DIVE) - && (GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE) + && GetBattlerAbility(gBattlerAttacker) == ABILITY_GULP_MISSILE && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) gBattlescriptCurrInstr = BattleScript_GulpMissileFormChange; else diff --git a/src/battle_util.c b/src/battle_util.c index 8d6504d186..52aa01c535 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -310,8 +310,8 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) || (!IsBattlerAlive(gSideTimers[defSide].followmeTarget) && !IsDragonDartsSecondHit(effect)) || effect == EFFECT_SNIPE_SHOT || effect == EFFECT_SKY_DROP - || ability == ABILITY_PROPELLER_TAIL - || ability == ABILITY_STALWART) + || IsAbilityAndRecord(battlerAtk, ability, ABILITY_PROPELLER_TAIL) + || IsAbilityAndRecord(battlerAtk, ability, ABILITY_STALWART)) return FALSE; if (effect == EFFECT_PURSUIT && IsPursuitTargetSet()) @@ -346,6 +346,7 @@ bool32 HandleMoveTargetRedirection(void) || (ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { // Find first battler that redirects the move (in turn order) + u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); u32 battler; for (battler = 0; battler < gBattlersCount; battler++) { @@ -358,8 +359,8 @@ bool32 HandleMoveTargetRedirection(void) && GetBattlerTurnOrderNum(battler) < redirectorOrderNum && moveEffect != EFFECT_SNIPE_SHOT && moveEffect != EFFECT_PLEDGE - && GetBattlerAbility(gBattlerAttacker) != ABILITY_PROPELLER_TAIL - && GetBattlerAbility(gBattlerAttacker) != ABILITY_STALWART) + && !IsAbilityAndRecord(gBattlerAttacker, abilityAtk, ABILITY_PROPELLER_TAIL) + && !IsAbilityAndRecord(gBattlerAttacker, abilityAtk, ABILITY_STALWART)) { redirectorOrderNum = GetBattlerTurnOrderNum(battler); } @@ -1062,8 +1063,8 @@ const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) // If the target can be confused, confuse them. // Don't use CanBeConfused, can cause issues in edge cases. - if (!(GetBattlerAbility(otherSkyDropper) == ABILITY_OWN_TEMPO - || gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION + if (!(gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION + || IsAbilityAndRecord(otherSkyDropper, GetBattlerAbility(otherSkyDropper), ABILITY_OWN_TEMPO) || IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN))) { // Set confused status @@ -1675,13 +1676,11 @@ bool32 MoodyCantLowerStat(u32 stat) void TryToRevertMimicryAndFlags(void) { - u32 i; - - for (i = 0; i < gBattlersCount; i++) + for (u32 battler = 0; battler < gBattlersCount; battler++) { - gDisableStructs[i].terrainAbilityDone = FALSE; - if (GetBattlerAbility(i) == ABILITY_MIMICRY) - RESTORE_BATTLER_TYPE(i); + gDisableStructs[battler].terrainAbilityDone = FALSE; + if (IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_MIMICRY)) + RESTORE_BATTLER_TYPE(battler); } } @@ -1717,13 +1716,13 @@ s32 GetDrainedBigRootHp(u32 battler, s32 hp) return hp * -1; } -// This should always be the last check. Otherwise the ability might be recorded when it is not supposed to be -bool32 IsMagicGuardProtected(u32 battler, u32 ability) +// Should always be the last check. Otherwise the ability might be wrongly recorded. +bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck) { - if (ability != ABILITY_MAGIC_GUARD) + if (battlerAbility != abilityToCheck) return FALSE; - RecordAbilityBattle(battler, ability); + RecordAbilityBattle(battler, abilityToCheck); return TRUE; } @@ -1919,7 +1918,7 @@ static void CancellerAsleep(u32 *effect) else { u8 toSub; - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_EARLY_BIRD) + if (IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_EARLY_BIRD)) toSub = 2; else toSub = 1; @@ -2196,7 +2195,7 @@ static void CancellerParalysed(u32 *effect) { if (!gBattleStruct->isAtkCancelerForCalledMove && (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) - && !(B_MAGIC_GUARD == GEN_4 && GetBattlerAbility(gBattlerAttacker) == ABILITY_MAGIC_GUARD) + && !(B_MAGIC_GUARD == GEN_4 && IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) && !RandomPercentage(RNG_PARALYSIS, 75)) { gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE; @@ -2309,7 +2308,7 @@ static void CancellerPowderStatus(u32 *effect) if (TryActivatePowderStatus(gCurrentMove)) { gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE; - if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) + if (!IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 4; if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE @@ -4727,9 +4726,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3)) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget) - && GetBattlerAbility(gBattlerAttacker) != ABILITY_OBLIVIOUS && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker) + && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_OBLIVIOUS) && !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL)) { gBattleMons[gBattlerAttacker].status2 |= STATUS2_INFATUATED_WITH(gBattlerTarget); @@ -5351,8 +5350,16 @@ bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability) if (gStatuses3[battler] & STATUS3_GASTRO_ACID) return FALSE; - return (ability == ABILITY_MOLD_BREAKER || ability == ABILITY_TERAVOLT || ability == ABILITY_TURBOBLAZE - || (ability == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gCurrentMove))); + if (ability == ABILITY_MOLD_BREAKER + || ability == ABILITY_TERAVOLT + || ability == ABILITY_TURBOBLAZE + || (ability == ABILITY_MYCELIUM_MIGHT && IsBattleMoveStatus(gCurrentMove))) + { + RecordAbilityBattle(battler, ability); + return TRUE; + } + + return FALSE; } static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32 ability, u32 hasAbilityShield, u32 ignoreMoldBreaker) @@ -5815,9 +5822,9 @@ static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum NonV bool32 CanBeConfused(u32 battler) { - if (GetBattlerAbility(battler) == ABILITY_OWN_TEMPO - || gBattleMons[battler].status2 & STATUS2_CONFUSION - || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN)) + if (gBattleMons[battler].status2 & STATUS2_CONFUSION + || IsBattlerTerrainAffected(battler, STATUS_FIELD_MISTY_TERRAIN) + || IsAbilityAndRecord(battler, GetBattlerAbility(battler),ABILITY_OWN_TEMPO)) return FALSE; return TRUE; } @@ -5837,12 +5844,10 @@ bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId) if (gBattleMons[battler].hp <= gBattleMons[battler].maxHP / hpFraction) return TRUE; - if (hpFraction <= 4 && GetBattlerAbility(battler) == ABILITY_GLUTTONY && isBerry - && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 2) - { - RecordAbilityBattle(battler, ABILITY_GLUTTONY); + if (hpFraction <= 4 && isBerry + && gBattleMons[battler].hp <= gBattleMons[battler].maxHP / 2 + && IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_GLUTTONY)) return TRUE; - } return FALSE; } @@ -7057,9 +7062,9 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && !IsBattleMoveStatus(gCurrentMove) && (IsBattlerTurnDamaged(gBattlerTarget) || !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Needs the second check in case of Substitute - && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + && !IsFutureSightAttackerInParty(gBattlerAttacker, gBattlerTarget, gCurrentMove) + && !IsAbilityAndRecord(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), ABILITY_MAGIC_GUARD)) { gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 10; if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) @@ -7628,7 +7633,7 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) { if (IsZMove(move) || IsMaxMove(move)) return FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard). - if (IsMoveMakingContact(move, battlerAtk) && GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST) + if (IsMoveMakingContact(move, battlerAtk) && IsAbilityAndRecord(battlerAtk, GetBattlerAbility(battlerAtk), ABILITY_UNSEEN_FIST)) return FALSE; } @@ -7727,7 +7732,7 @@ static bool32 IsBattlerGroundedInverseCheck(u32 battler, enum InverseBattleCheck return FALSE; if (holdEffect == HOLD_EFFECT_AIR_BALLOON) return FALSE; - if ((gAiLogicData->aiCalcInProgress ? gAiLogicData->abilities[battler] : GetBattlerAbility(battler)) == ABILITY_LEVITATE) + if (gAiLogicData->aiCalcInProgress ? gAiLogicData->abilities[battler] == ABILITY_LEVITATE : IsAbilityAndRecord(battler, GetBattlerAbility(battler), ABILITY_LEVITATE)) return FALSE; if (IS_BATTLER_OF_TYPE(battler, TYPE_FLYING) && (!(checkInverse == INVERSE_BATTLE) || !FlagGet(B_FLAG_INVERSE_BATTLE))) return FALSE; @@ -9094,10 +9099,20 @@ static inline uq4_12_t GetScreensModifier(struct DamageContext *ctx) bool32 reflect = (sideStatus & SIDE_STATUS_REFLECT) && IsBattleMovePhysical(ctx->move); bool32 auroraVeil = sideStatus & SIDE_STATUS_AURORA_VEIL; - if (ctx->isCrit || ctx->abilityAtk == ABILITY_INFILTRATOR || gProtectStructs[ctx->battlerAtk].confusionSelfDmg) + if (ctx->isCrit || gProtectStructs[ctx->battlerAtk].confusionSelfDmg) + { return UQ_4_12(1.0); + } + if (ctx->abilityAtk == ABILITY_INFILTRATOR) + { + if (ctx->updateFlags) + RecordAbilityBattle(ctx->battlerAtk, ctx->abilityDef); + return UQ_4_12(1.0); + } if (reflect || lightScreen || auroraVeil) + { return (IsDoubleBattle()) ? UQ_4_12(0.667) : UQ_4_12(0.5); + } return UQ_4_12(1.0); } @@ -9130,35 +9145,60 @@ static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typ static inline uq4_12_t GetDefenderAbilitiesModifier(struct DamageContext *ctx) { + bool32 recordAbility = FALSE; + uq4_12_t modifier = UQ_4_12(1.0); + switch (ctx->abilityDef) { case ABILITY_MULTISCALE: case ABILITY_SHADOW_SHIELD: if (IsBattlerAtMaxHp(ctx->battlerDef)) - return UQ_4_12(0.5); + { + modifier = UQ_4_12(0.5); + recordAbility = TRUE; + } break; case ABILITY_FILTER: case ABILITY_SOLID_ROCK: case ABILITY_PRISM_ARMOR: if (ctx->typeEffectivenessModifier >= UQ_4_12(2.0)) - return UQ_4_12(0.75); + { + modifier = UQ_4_12(0.75); + recordAbility = TRUE; + } break; case ABILITY_FLUFFY: if (!IsMoveMakingContact(ctx->move, ctx->battlerAtk) && ctx->moveType == TYPE_FIRE) - return UQ_4_12(2.0); - if (IsMoveMakingContact(ctx->move, ctx->battlerAtk) && ctx->moveType != TYPE_FIRE) - return UQ_4_12(0.5); + { + modifier = UQ_4_12(2.0); + recordAbility = TRUE; + } + else if (IsMoveMakingContact(ctx->move, ctx->battlerAtk) && ctx->moveType != TYPE_FIRE) + { + modifier = UQ_4_12(0.5); + recordAbility = TRUE; + } break; case ABILITY_PUNK_ROCK: if (IsSoundMove(ctx->move)) - return UQ_4_12(0.5); + { + modifier = UQ_4_12(0.5); + recordAbility = TRUE; + } break; case ABILITY_ICE_SCALES: if (IsBattleMoveSpecial(ctx->move)) - return UQ_4_12(0.5); + { + modifier = UQ_4_12(0.5); + recordAbility = TRUE; + } break; } - return UQ_4_12(1.0); + + if (recordAbility && ctx->updateFlags) + RecordAbilityBattle(ctx->battlerAtk, ctx->abilityDef); + + return modifier; } static inline uq4_12_t GetDefenderPartnerAbilitiesModifier(u32 battlerPartnerDef)