Fixes cantBeSurpressed ability check for breakable abilities (#5043)
This commit is contained in:
commit
3c1fbbb06e
@ -146,7 +146,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility)
|
|||||||
u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg);
|
u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 moveArg);
|
||||||
bool32 TryPrimalReversion(u32 battler);
|
bool32 TryPrimalReversion(u32 battler);
|
||||||
bool32 IsNeutralizingGasOnField(void);
|
bool32 IsNeutralizingGasOnField(void);
|
||||||
bool32 IsMoldBreakerTypeAbility(u32 ability);
|
bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability);
|
||||||
u32 GetBattlerAbility(u32 battler);
|
u32 GetBattlerAbility(u32 battler);
|
||||||
u32 IsAbilityOnSide(u32 battler, u32 ability);
|
u32 IsAbilityOnSide(u32 battler, u32 ability);
|
||||||
u32 IsAbilityOnOpposingSide(u32 battler, u32 ability);
|
u32 IsAbilityOnOpposingSide(u32 battler, u32 ability);
|
||||||
|
|||||||
@ -1188,7 +1188,7 @@ bool32 DoesBattlerIgnoreAbilityChecks(u32 atkAbility, u32 move)
|
|||||||
if (AI_THINKING_STRUCT->aiFlags[sBattler_AI] & AI_FLAG_NEGATE_UNAWARE)
|
if (AI_THINKING_STRUCT->aiFlags[sBattler_AI] & AI_FLAG_NEGATE_UNAWARE)
|
||||||
return FALSE; // AI handicap flag: doesn't understand ability suppression concept
|
return FALSE; // AI handicap flag: doesn't understand ability suppression concept
|
||||||
|
|
||||||
if (IsMoldBreakerTypeAbility(atkAbility) || gMovesInfo[move].ignoresTargetAbility)
|
if (IsMoldBreakerTypeAbility(sBattler_AI, atkAbility) || gMovesInfo[move].ignoresTargetAbility)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -2766,7 +2766,7 @@ bool32 AI_CanBeInfatuated(u32 battlerAtk, u32 battlerDef, u32 defAbility)
|
|||||||
|
|
||||||
u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move)
|
u32 ShouldTryToFlinch(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbility, u32 move)
|
||||||
{
|
{
|
||||||
if (((!IsMoldBreakerTypeAbility(AI_DATA->abilities[battlerAtk]) && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS))
|
if (((!IsMoldBreakerTypeAbility(battlerAtk, AI_DATA->abilities[battlerAtk]) && (defAbility == ABILITY_SHIELD_DUST || defAbility == ABILITY_INNER_FOCUS))
|
||||||
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK
|
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK
|
||||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||||
|| AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)) // Opponent goes first
|
|| AI_WhoStrikesFirst(battlerAtk, battlerDef, move) == AI_IS_SLOWER)) // Opponent goes first
|
||||||
@ -2809,7 +2809,7 @@ bool32 ShouldFakeOut(u32 battlerAtk, u32 battlerDef, u32 move)
|
|||||||
|| AI_DATA->holdEffects[battlerAtk] == HOLD_EFFECT_CHOICE_BAND
|
|| AI_DATA->holdEffects[battlerAtk] == HOLD_EFFECT_CHOICE_BAND
|
||||||
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK
|
|| AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_COVERT_CLOAK
|
||||||
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
|| DoesSubstituteBlockMove(battlerAtk, battlerDef, move)
|
||||||
|| (!IsMoldBreakerTypeAbility(AI_DATA->abilities[battlerAtk])
|
|| (!IsMoldBreakerTypeAbility(battlerAtk, AI_DATA->abilities[battlerAtk])
|
||||||
&& (AI_DATA->abilities[battlerDef] == ABILITY_SHIELD_DUST || AI_DATA->abilities[battlerDef] == ABILITY_INNER_FOCUS)))
|
&& (AI_DATA->abilities[battlerDef] == ABILITY_SHIELD_DUST || AI_DATA->abilities[battlerDef] == ABILITY_INNER_FOCUS)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
|||||||
@ -6207,23 +6207,41 @@ bool32 IsNeutralizingGasOnField(void)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool32 IsMoldBreakerTypeAbility(u32 ability)
|
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
|
return (ability == ABILITY_MOLD_BREAKER || ability == ABILITY_TERAVOLT || ability == ABILITY_TURBOBLAZE
|
||||||
|| (ability == ABILITY_MYCELIUM_MIGHT && IS_MOVE_STATUS(gCurrentMove)));
|
|| (ability == ABILITY_MYCELIUM_MIGHT && IS_MOVE_STATUS(gCurrentMove)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32 ability)
|
||||||
|
{
|
||||||
|
return ((IsMoldBreakerTypeAbility(battlerAtk, ability) || gMovesInfo[gCurrentMove].ignoresTargetAbility)
|
||||||
|
&& battlerDef != battlerAtk
|
||||||
|
&& gAbilitiesInfo[gBattleMons[battlerDef].ability].breakable
|
||||||
|
&& gBattlerByTurnOrder[gCurrentTurnActionNumber] == battlerAtk
|
||||||
|
&& gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE
|
||||||
|
&& gCurrentTurnActionNumber < gBattlersCount);
|
||||||
|
}
|
||||||
|
|
||||||
u32 GetBattlerAbility(u32 battler)
|
u32 GetBattlerAbility(u32 battler)
|
||||||
{
|
{
|
||||||
bool32 noAbilityShield = GetBattlerHoldEffectIgnoreAbility(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD;
|
bool32 noAbilityShield = GetBattlerHoldEffectIgnoreAbility(battler, TRUE) != HOLD_EFFECT_ABILITY_SHIELD;
|
||||||
|
bool32 abilityCantBeSuppressed = gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed;
|
||||||
|
|
||||||
if (gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed)
|
if (abilityCantBeSuppressed)
|
||||||
{
|
{
|
||||||
// Edge case: pokemon under the effect of gastro acid transforms into a pokemon with Comatose (Todo: verify how other unsuppressable abilities behave)
|
// Edge case: pokemon under the effect of gastro acid transforms into a pokemon with Comatose (Todo: verify how other unsuppressable abilities behave)
|
||||||
if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED
|
if (gBattleMons[battler].status2 & STATUS2_TRANSFORMED
|
||||||
&& gStatuses3[battler] & STATUS3_GASTRO_ACID
|
&& gStatuses3[battler] & STATUS3_GASTRO_ACID
|
||||||
&& gBattleMons[battler].ability == ABILITY_COMATOSE)
|
&& gBattleMons[battler].ability == ABILITY_COMATOSE)
|
||||||
return ABILITY_NONE;
|
return ABILITY_NONE;
|
||||||
|
|
||||||
|
if (noAbilityShield && CanBreakThroughAbility(gBattlerAttacker, battler, gBattleMons[gBattlerAttacker].ability))
|
||||||
|
return ABILITY_NONE;
|
||||||
|
|
||||||
return gBattleMons[battler].ability;
|
return gBattleMons[battler].ability;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6235,15 +6253,7 @@ u32 GetBattlerAbility(u32 battler)
|
|||||||
&& noAbilityShield)
|
&& noAbilityShield)
|
||||||
return ABILITY_NONE;
|
return ABILITY_NONE;
|
||||||
|
|
||||||
if (((IsMoldBreakerTypeAbility(gBattleMons[gBattlerAttacker].ability)
|
if (noAbilityShield && CanBreakThroughAbility(gBattlerAttacker, battler, gBattleMons[gBattlerAttacker].ability))
|
||||||
&& !(gStatuses3[gBattlerAttacker] & STATUS3_GASTRO_ACID))
|
|
||||||
|| gMovesInfo[gCurrentMove].ignoresTargetAbility)
|
|
||||||
&& battler != gBattlerAttacker
|
|
||||||
&& gAbilitiesInfo[gBattleMons[battler].ability].breakable
|
|
||||||
&& noAbilityShield
|
|
||||||
&& gBattlerByTurnOrder[gCurrentTurnActionNumber] == gBattlerAttacker
|
|
||||||
&& gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE
|
|
||||||
&& gCurrentTurnActionNumber < gBattlersCount)
|
|
||||||
return ABILITY_NONE;
|
return ABILITY_NONE;
|
||||||
|
|
||||||
return gBattleMons[battler].ability;
|
return gBattleMons[battler].ability;
|
||||||
|
|||||||
@ -121,3 +121,16 @@ SINGLE_BATTLE_TEST("Disguised Mimikyu takes damage from Rough Skin without break
|
|||||||
EXPECT_EQ(player->species, SPECIES_MIMIKYU_DISGUISED);
|
EXPECT_EQ(player->species, SPECIES_MIMIKYU_DISGUISED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SINGLE_BATTLE_TEST("Disguised Mimikyu is ignored by Mold Breaker")
|
||||||
|
{
|
||||||
|
GIVEN {
|
||||||
|
PLAYER(SPECIES_MIMIKYU_DISGUISED) { Ability(ABILITY_DISGUISE); }
|
||||||
|
OPPONENT(SPECIES_PINSIR) { Ability(ABILITY_MOLD_BREAKER); }
|
||||||
|
} WHEN {
|
||||||
|
TURN { MOVE(opponent, MOVE_AERIAL_ACE); }
|
||||||
|
} SCENE {
|
||||||
|
ANIMATION(ANIM_TYPE_MOVE, MOVE_AERIAL_ACE, opponent);
|
||||||
|
NOT ABILITY_POPUP(player, ABILITY_DISGUISE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user