Fixes Neutralizing Gas / Mold Breaker / Dragon Darts interaction (#8389)

This commit is contained in:
Alex 2025-11-30 09:10:43 +01:00 committed by GitHub
parent cbcb720286
commit dfd8daac2e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 53 additions and 12 deletions

View File

@ -667,7 +667,7 @@ struct BattleStruct
u8 multipleSwitchInState:2;
u8 multipleSwitchInCursor:3;
u8 sleepClauseNotBlocked:1;
u8 padding1:1;
u8 moldBreakerActive:1;
u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT];
void (*savedCallback)(void);
u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle

View File

@ -7020,6 +7020,7 @@ static void Cmd_moveend(void)
gSpecialStatuses[gBattlerTarget].berryReduced = FALSE;
gSpecialStatuses[gBattlerTarget].distortedTypeMatchups = FALSE;
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
gBattleStruct->moldBreakerActive = FALSE;
gBattleStruct->isAtkCancelerForCalledMove = FALSE;
gBattleStruct->swapDamageCategory = FALSE;
gBattleStruct->categoryOverride = FALSE;

View File

@ -490,6 +490,9 @@ void HandleAction_UseMove(void)
gCurrentMove = gChosenMove = GetMaxMove(gBattlerAttacker, gCurrentMove);
}
if (IsMoldBreakerTypeAbility(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) || MoveIgnoresTargetAbility(gCurrentMove))
gBattleStruct->moldBreakerActive = TRUE;
moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
if (!HandleMoveTargetRedirection())
@ -933,6 +936,7 @@ void HandleAction_ActionFinished(void)
gBattleStruct->dynamicMoveType = 0;
gBattleStruct->bouncedMoveIsUsed = FALSE;
gBattleStruct->snatchedMoveIsUsed = FALSE;
gBattleStruct->moldBreakerActive = FALSE;
gBattleScripting.moveendState = 0;
gBattleCommunication[3] = 0;
gBattleCommunication[4] = 0;
@ -5360,17 +5364,11 @@ bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability)
return FALSE;
}
static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32 ability, u32 hasAbilityShield, u32 ignoreMoldBreaker)
static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32 hasAbilityShield, u32 ignoreMoldBreaker)
{
if (hasAbilityShield || ignoreMoldBreaker)
if (hasAbilityShield || ignoreMoldBreaker || battlerDef == battlerAtk)
return FALSE;
return ((IsMoldBreakerTypeAbility(battlerAtk, ability) || MoveIgnoresTargetAbility(gCurrentMove))
&& battlerDef != battlerAtk
&& gAbilitiesInfo[gBattleMons[battlerDef].ability].breakable
&& gBattlerByTurnOrder[gCurrentTurnActionNumber] == battlerAtk
&& gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE
&& gCurrentTurnActionNumber < gBattlersCount);
return gBattleStruct->moldBreakerActive && gAbilitiesInfo[gBattleMons[battlerDef].ability].breakable;
}
u32 GetBattlerAbilityNoAbilityShield(u32 battler)
@ -5401,7 +5399,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS
&& gBattleMons[battler].ability == ABILITY_COMATOSE)
return ABILITY_NONE;
if (CanBreakThroughAbility(gBattlerAttacker, battler, gBattleMons[gBattlerAttacker].ability, hasAbilityShield, ignoreMoldBreaker))
if (CanBreakThroughAbility(gBattlerAttacker, battler, hasAbilityShield, ignoreMoldBreaker))
return ABILITY_NONE;
return gBattleMons[battler].ability;
@ -5415,7 +5413,7 @@ u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityS
&& (gBattleMons[battler].ability != ABILITY_NEUTRALIZING_GAS || gBattleMons[battler].volatiles.gastroAcid))
return ABILITY_NONE;
if (CanBreakThroughAbility(gBattlerAttacker, battler, gBattleMons[gBattlerAttacker].ability, hasAbilityShield, ignoreMoldBreaker))
if (CanBreakThroughAbility(gBattlerAttacker, battler, hasAbilityShield, ignoreMoldBreaker))
return ABILITY_NONE;
return gBattleMons[battler].ability;

View File

@ -353,3 +353,45 @@ SINGLE_BATTLE_TEST("Neutralizing Gas only displays exiting message for the last
NOT MESSAGE("The effects of the neutralizing gas wore off!");
}
}
DOUBLE_BATTLE_TEST("Neutralizing Gas is active for the duration of a Spread Move even if Neutralizing Gas is no longer on the field")
{
GIVEN {
ASSUME(GetMoveTarget(MOVE_ORIGIN_PULSE) == MOVE_TARGET_BOTH);
PLAYER(SPECIES_WEEZING) { HP(1); Ability(ABILITY_NEUTRALIZING_GAS); }
PLAYER(SPECIES_GOLEM) { Ability(ABILITY_STURDY); }
OPPONENT(SPECIES_BASCULEGION) { Ability(ABILITY_MOLD_BREAKER); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_ORIGIN_PULSE); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ORIGIN_PULSE, opponentLeft);
HP_BAR(playerLeft);
HP_BAR(playerRight);
MESSAGE("Weezing fainted!");
MESSAGE("Golem fainted!");
NOT ABILITY_POPUP(playerRight, ABILITY_STURDY);
}
}
DOUBLE_BATTLE_TEST("Neutralizing Gas is active until the last Dragon Darts hit even if Neutralizing Gas is no longer on the field")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_DRAGON_DARTS) == EFFECT_DRAGON_DARTS);
PLAYER(SPECIES_WEEZING) { HP(1); Ability(ABILITY_NEUTRALIZING_GAS); }
PLAYER(SPECIES_GOLEM) { HP(2); MaxHP(2); Ability(ABILITY_STURDY); }
OPPONENT(SPECIES_BASCULEGION) { Ability(ABILITY_MOLD_BREAKER); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentLeft, MOVE_DRAGON_DARTS, target: playerLeft); }
} SCENE {
ABILITY_POPUP(playerLeft, ABILITY_NEUTRALIZING_GAS);
ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_DARTS, opponentLeft);
HP_BAR(playerLeft);
MESSAGE("Weezing fainted!");
HP_BAR(playerRight);
NOT MESSAGE("Golem fainted!");
ABILITY_POPUP(playerRight, ABILITY_STURDY);
}
}