Attackcanceller clean up (#7210)

This commit is contained in:
Alex 2025-06-25 21:36:15 +02:00 committed by GitHub
parent f217344cb5
commit 6824e7d175
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 143 additions and 126 deletions

View File

@ -113,26 +113,23 @@ struct TypePower
u16 effect;
};
enum
enum MoveSuccessOrder
{
CANCELLER_FLAGS,
CANCELLER_STANCE_CHANGE_1,
CANCELLER_SKY_DROP,
CANCELLER_RECHARGE,
CANCELLER_ASLEEP,
CANCELLER_FROZEN,
CANCELLER_ASLEEP_OR_FROZEN,
CANCELLER_OBEDIENCE,
CANCELLER_TRUANT,
CANCELLER_FLINCH,
CANCELLER_IN_LOVE,
CANCELLER_DISABLED,
CANCELLER_HEAL_BLOCKED,
CANCELLER_GRAVITY,
CANCELLER_THROAT_CHOP,
CANCELLER_VOLATILE_BLOCKED,
CANCELLER_TAUNTED,
CANCELLER_IMPRISONED,
CANCELLER_CONFUSED,
CANCELLER_PARALYSED,
CANCELLER_INFATUATION,
CANCELLER_BIDE,
CANCELLER_THAW,
CANCELLER_STANCE_CHANGE_2,
@ -148,7 +145,8 @@ enum
CANCELLER_END,
};
enum {
enum Obedience
{
OBEYS,
DISOBEYS_LOAFS,
DISOBEYS_HITS_SELF,
@ -157,6 +155,13 @@ enum {
DISOBEYS_RANDOM_MOVE,
};
enum MoveCanceller
{
MOVE_STEP_SUCCESS,
MOVE_STEP_BREAK,
MOVE_STEP_REMOVES_STATUS,
};
extern const struct TypePower gNaturalGiftTable[];
struct DamageContext
@ -241,7 +246,7 @@ bool32 IsAbilityAndRecord(u32 battler, u32 battlerAbility, u32 abilityToCheck);
u32 DoEndTurnEffects(void);
bool32 HandleFaintedMonActions(void);
void TryClearRageAndFuryCutter(void);
u32 AtkCanceller_MoveSuccessOrder(void);
enum MoveCanceller AtkCanceller_MoveSuccessOrder(void);
void SetAtkCancellerForCalledMove(void);
bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2);
bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility);

View File

@ -1222,7 +1222,7 @@ static void Cmd_attackcanceler(void)
gBattlescriptCurrInstr = BattleScript_MoveEnd;
return;
}
if (AtkCanceller_MoveSuccessOrder())
if (AtkCanceller_MoveSuccessOrder() != MOVE_STEP_SUCCESS)
return;
if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF

View File

@ -58,7 +58,6 @@ match the ROM; this is also why sSoundMovesTable's declaration is in the middle
functions instead of at the top of the file with the other declarations.
*/
typedef void (*MoveSuccessOrderCancellers)(u32 *effect);
static bool32 TryRemoveScreens(u32 battler);
static bool32 IsUnnerveAbilityOnOpposingSide(u32 battler);
static u32 GetFlingPowerFromItemId(u32 itemId);
@ -1885,35 +1884,38 @@ static inline bool32 TryActivatePowderStatus(u32 move)
void SetAtkCancellerForCalledMove(void)
{
gBattleStruct->atkCancellerTracker = CANCELLER_HEAL_BLOCKED;
gBattleStruct->atkCancellerTracker = CANCELLER_VOLATILE_BLOCKED;
gBattleStruct->isAtkCancelerForCalledMove = TRUE;
}
static void CancellerFlags(u32 *effect)
static enum MoveCanceller CancellerFlags(void)
{
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_DESTINY_BOND;
gStatuses3[gBattlerAttacker] &= ~STATUS3_GRUDGE;
gStatuses4[gBattlerAttacker] &= ~STATUS4_GLAIVE_RUSH;
return MOVE_STEP_SUCCESS;
}
static void CancellerStanceChangeOne(u32 *effect)
static enum MoveCanceller CancellerStanceChangeOne(void)
{
if (B_STANCE_CHANGE_FAIL < GEN_7 && TryFormChangeBeforeMove())
*effect = 1;
return MOVE_STEP_BREAK;
return MOVE_STEP_SUCCESS;
}
static void CancellerSkyDrop(u32 *effect)
static enum MoveCanceller CancellerSkyDrop(void)
{
// If Pokemon is being held in Sky Drop
if (gStatuses3[gBattlerAttacker] & STATUS3_SKY_DROPPED)
{
gBattlescriptCurrInstr = BattleScript_MoveEnd;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerRecharge(u32 *effect)
static enum MoveCanceller CancellerRecharge(void)
{
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_RECHARGE)
{
@ -1922,11 +1924,12 @@ static void CancellerRecharge(u32 *effect)
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedMustRecharge;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerAsleep(u32 *effect)
static enum MoveCanceller CancellerAsleepOrFrozen(void)
{
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)
{
@ -1937,7 +1940,7 @@ static void CancellerAsleep(u32 *effect)
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP_UPROAR;
BattleScriptCall(BattleScript_MoveUsedWokeUp);
*effect = 2;
return MOVE_STEP_REMOVES_STATUS;
}
else
{
@ -1958,7 +1961,7 @@ static void CancellerAsleep(u32 *effect)
gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility = TRUE;
gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 2;
return MOVE_STEP_REMOVES_STATUS;
}
}
else
@ -1967,15 +1970,11 @@ static void CancellerAsleep(u32 *effect)
gBattleMons[gBattlerAttacker].status2 &= ~STATUS2_NIGHTMARE;
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WOKE_UP;
BattleScriptCall(BattleScript_MoveUsedWokeUp);
*effect = 2;
return MOVE_STEP_REMOVES_STATUS;
}
}
}
}
static void CancellerFrozen(u32 *effect)
{
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE && !MoveThawsUser(gCurrentMove))
else if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE && !MoveThawsUser(gCurrentMove))
{
if (!RandomPercentage(RNG_FROZEN, 20))
{
@ -1989,19 +1988,22 @@ static void CancellerFrozen(u32 *effect)
BattleScriptCall(BattleScript_MoveUsedUnfroze);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED;
}
*effect = 2;
return MOVE_STEP_REMOVES_STATUS;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerObedience(u32 *effect)
static enum MoveCanceller CancellerObedience(void)
{
u32 obedienceResult = GetAttackerObedienceForAction();
if (obedienceResult != OBEYS
&& !(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves
&& !(gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
enum Obedience obedienceResult = GetAttackerObedienceForAction();
if (!(gHitMarker & HITMARKER_NO_PPDEDUCT) // Don't check obedience after first hit of multi target move or multi hit moves
&& !gBattleMons[gBattlerAttacker].volatiles.multipleTurns)
{
switch (obedienceResult)
{
case OBEYS:
gHitMarker |= HITMARKER_OBEYS;
break;
case DISOBEYS_LOAFS:
// Randomly select, then print a disobedient string
// B_MSG_LOAFING, B_MSG_WONT_OBEY, B_MSG_TURNED_AWAY, or B_MSG_PRETEND_NOT_NOTICE
@ -2042,15 +2044,13 @@ static void CancellerObedience(u32 *effect)
gHitMarker |= HITMARKER_OBEYS;
break;
}
*effect = 1;
}
else
{
gHitMarker |= HITMARKER_OBEYS;
return MOVE_STEP_BREAK;
}
gHitMarker |= HITMARKER_OBEYS;
return MOVE_STEP_SUCCESS;
}
static void CancellerTruant(u32 *effect)
static enum MoveCanceller CancellerTruant(void)
{
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_TRUANT && gDisableStructs[gBattlerAttacker].truantCounter)
{
@ -2060,11 +2060,12 @@ static void CancellerTruant(u32 *effect)
gBattlerAbility = gBattlerAttacker;
gBattlescriptCurrInstr = BattleScript_TruantLoafingAround;
gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerFlinch(u32 *effect)
static enum MoveCanceller CancellerFlinch(void)
{
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_FLINCHED)
{
@ -2072,32 +2073,12 @@ static void CancellerFlinch(u32 *effect)
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedFlinched;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerInLove(u32 *effect)
{
if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION)
{
gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10);
if (!RandomPercentage(RNG_INFATUATION, 50))
{
BattleScriptCall(BattleScript_MoveUsedIsInLove);
}
else
{
BattleScriptPush(BattleScript_MoveUsedIsInLoveCantAttack);
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE;
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove;
}
*effect = 1;
}
}
static void CancellerDisabled(u32 *effect)
static enum MoveCanceller CancellerDisabled(void)
{
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].disabledMove == gCurrentMove && gDisableStructs[gBattlerAttacker].disabledMove != MOVE_NONE)
{
@ -2106,11 +2087,12 @@ static void CancellerDisabled(u32 *effect)
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsDisabled;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerHealBlocked(u32 *effect)
static enum MoveCanceller CancellerVolatileBlocked(void)
{
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gStatuses3[gBattlerAttacker] & STATUS3_HEAL_BLOCK && IsHealBlockPreventingMove(gBattlerAttacker, gCurrentMove))
{
@ -2119,36 +2101,29 @@ static void CancellerHealBlocked(u32 *effect)
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedHealBlockPrevents;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
}
static void CancellerGravity(u32 *effect)
{
if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(gCurrentMove))
else if (gFieldStatuses & STATUS_FIELD_GRAVITY && IsGravityPreventingMove(gCurrentMove))
{
gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE;
gBattleScripting.battler = gBattlerAttacker;
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedGravityPrevents;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
}
static void CancellerThroatChop(u32 *effect)
{
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].throatChopTimer > gBattleTurnCounter && IsSoundMove(gCurrentMove))
else if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].throatChopTimer > gBattleTurnCounter && IsSoundMove(gCurrentMove))
{
gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE;
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsThroatChopPrevented;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerTaunted(u32 *effect)
static enum MoveCanceller CancellerTaunted(void)
{
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && gDisableStructs[gBattlerAttacker].tauntTimer && IsBattleMoveStatus(gCurrentMove))
{
@ -2156,11 +2131,12 @@ static void CancellerTaunted(u32 *effect)
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsTaunted;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerImprisoned(u32 *effect)
static enum MoveCanceller CancellerImprisoned(void)
{
if (GetActiveGimmick(gBattlerAttacker) != GIMMICK_Z_MOVE && GetImprisonedMovesCount(gBattlerAttacker, gCurrentMove))
{
@ -2168,14 +2144,15 @@ static void CancellerImprisoned(u32 *effect)
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsImprisoned;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerConfused(u32 *effect)
static enum MoveCanceller CancellerConfused(void)
{
if (gBattleStruct->isAtkCancelerForCalledMove)
return;
return MOVE_STEP_SUCCESS;
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_CONFUSION)
{
@ -2211,11 +2188,12 @@ static void CancellerConfused(u32 *effect)
{
BattleScriptCall(BattleScript_MoveUsedIsConfusedNoMore);
}
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerParalysed(u32 *effect)
static enum MoveCanceller CancellerParalysed(void)
{
if (!gBattleStruct->isAtkCancelerForCalledMove
&& (gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS)
@ -2227,11 +2205,34 @@ static void CancellerParalysed(u32 *effect)
//CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerBide(u32 *effect)
static enum MoveCanceller CancellerInfatuation(void)
{
if (!gBattleStruct->isAtkCancelerForCalledMove && gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION)
{
gBattleScripting.battler = CountTrailingZeroBits((gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) >> 0x10);
if (!RandomPercentage(RNG_INFATUATION, 50))
{
BattleScriptCall(BattleScript_MoveUsedIsInLove);
}
else
{
BattleScriptPush(BattleScript_MoveUsedIsInLoveCantAttack);
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
gProtectStructs[gBattlerAttacker].unableToUseMove = TRUE;
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsInLove;
}
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static enum MoveCanceller CancellerBide(void)
{
if (gBattleMons[gBattlerAttacker].status2 & STATUS2_BIDE)
{
@ -2257,11 +2258,12 @@ static void CancellerBide(u32 *effect)
gBattlescriptCurrInstr = BattleScript_BideNoEnergyToAttack;
}
}
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerThaw(u32 *effect)
static enum MoveCanceller CancellerThaw(void)
{
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FREEZE)
{
@ -2271,7 +2273,7 @@ static void CancellerThaw(u32 *effect)
BattleScriptCall(BattleScript_MoveUsedUnfroze);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DEFROSTED_BY_MOVE;
}
*effect = 2;
return MOVE_STEP_REMOVES_STATUS;
}
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_FROSTBITE && MoveThawsUser(gCurrentMove))
{
@ -2281,32 +2283,35 @@ static void CancellerThaw(u32 *effect)
BattleScriptCall(BattleScript_MoveUsedUnfrostbite);
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FROSTBITE_HEALED_BY_MOVE;
}
*effect = 2;
return MOVE_STEP_REMOVES_STATUS;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerStanceChangeTwo(u32 *effect)
static enum MoveCanceller CancellerStanceChangeTwo(void)
{
if (B_STANCE_CHANGE_FAIL >= GEN_7 && !gBattleStruct->isAtkCancelerForCalledMove && TryFormChangeBeforeMove())
*effect = 1;
return MOVE_STEP_BREAK;
return MOVE_STEP_SUCCESS;
}
static void CancellerWeatherPrimal(u32 *effect)
static enum MoveCanceller CancellerWeatherPrimal(void)
{
enum MoveCanceller effect = MOVE_STEP_SUCCESS;
if (HasWeatherEffect() && GetMovePower(gCurrentMove) > 0)
{
u32 moveType = GetBattleMoveType(gCurrentMove);
if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL) && (B_POWDER_RAIN >= GEN_7 || !TryActivatePowderStatus(gCurrentMove)))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN;
*effect = 1;
effect = MOVE_STEP_BREAK;
}
else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL))
{
gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN;
*effect = 1;
effect = MOVE_STEP_BREAK;
}
if (*effect == 1)
if (effect == MOVE_STEP_BREAK)
{
gBattleScripting.moveEffect = MOVE_EFFECT_NONE;
gProtectStructs[gBattlerAttacker].chargingTurn = FALSE;
@ -2315,19 +2320,21 @@ static void CancellerWeatherPrimal(u32 *effect)
BattleScriptCall(BattleScript_PrimalWeatherBlocksMove);
}
}
return effect;
}
static void CancellerDynamaxBlocked(u32 *effect)
static enum MoveCanceller CancellerDynamaxBlocked(void)
{
if ((GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && IsMoveBlockedByDynamax(gCurrentMove))
{
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
BattleScriptCall(BattleScript_MoveBlockedByDynamax);
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerPowderStatus(u32 *effect)
static enum MoveCanceller CancellerPowderStatus(void)
{
if (TryActivatePowderStatus(gCurrentMove))
{
@ -2339,11 +2346,12 @@ static void CancellerPowderStatus(u32 *effect)
|| HasTrainerUsedGimmick(gBattlerAttacker, GIMMICK_Z_MOVE))
gBattlescriptCurrInstr = BattleScript_MoveUsedPowder;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerProtean(u32 *effect)
static enum MoveCanceller CancellerProtean(void)
{
u32 moveType = GetBattleMoveType(gCurrentMove);
if (ProteanTryChangeType(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker), gCurrentMove, moveType))
@ -2355,11 +2363,12 @@ static void CancellerProtean(u32 *effect)
PrepareStringBattle(STRINGID_EMPTYSTRING3, gBattlerAttacker);
gBattleCommunication[MSG_DISPLAY] = 1;
BattleScriptCall(BattleScript_ProteanActivates);
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerPsychicTerrain(u32 *effect)
static enum MoveCanceller CancellerPsychicTerrain(void)
{
if (gFieldStatuses & STATUS_FIELD_PSYCHIC_TERRAIN
&& IsBattlerGrounded(gBattlerTarget)
@ -2371,11 +2380,12 @@ static void CancellerPsychicTerrain(u32 *effect)
CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK);
gBattlescriptCurrInstr = BattleScript_MoveUsedPsychicTerrainPrevents;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerExplodingDamp(u32 *effect)
static enum MoveCanceller CancellerExplodingDamp(void)
{
u32 dampBattler = IsAbilityOnField(ABILITY_DAMP);
if (dampBattler && IsMoveDampBanned(gCurrentMove))
@ -2383,11 +2393,12 @@ static void CancellerExplodingDamp(u32 *effect)
gBattleScripting.battler = dampBattler - 1;
gBattlescriptCurrInstr = BattleScript_DampStopsExplosion;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
*effect = 1;
return MOVE_STEP_BREAK;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerMultihitMoves(u32 *effect)
static enum MoveCanceller CancellerMultihitMoves(void)
{
if (GetMoveEffect(gCurrentMove) == EFFECT_MULTI_HIT)
{
@ -2450,9 +2461,11 @@ static void CancellerMultihitMoves(u32 *effect)
{
gMultiHitCounter = 0;
}
return MOVE_STEP_SUCCESS;
}
static void CancellerZMoves(u32 *effect)
static enum MoveCanceller CancellerZMoves(void)
{
if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE)
{
@ -2479,11 +2492,12 @@ static void CancellerZMoves(u32 *effect)
if (!alreadyUsed)
BattleScriptCall(BattleScript_ZMoveActivateDamaging);
}
*effect = 1;
return MOVE_STEP_BREAK; // The original move is cancelled, not the z move
}
return MOVE_STEP_SUCCESS;
}
static void CancellerMultiTargetMoves(u32 *effect)
static enum MoveCanceller CancellerMultiTargetMoves(void)
{
u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove);
u32 abilityAtk = GetBattlerAbility(gBattlerAttacker);
@ -2526,24 +2540,22 @@ static void CancellerMultiTargetMoves(u32 *effect)
else
gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker);
}
return MOVE_STEP_SUCCESS;
}
static const MoveSuccessOrderCancellers sMoveSuccessOrderCancellers[] =
static enum MoveCanceller (*const sMoveSuccessOrderCancellers[])(void) =
{
[CANCELLER_FLAGS] = CancellerFlags,
[CANCELLER_STANCE_CHANGE_1] = CancellerStanceChangeOne,
[CANCELLER_SKY_DROP] = CancellerSkyDrop,
[CANCELLER_RECHARGE] = CancellerRecharge,
[CANCELLER_ASLEEP] = CancellerAsleep,
[CANCELLER_FROZEN] = CancellerFrozen,
[CANCELLER_ASLEEP_OR_FROZEN] = CancellerAsleepOrFrozen,
[CANCELLER_OBEDIENCE] = CancellerObedience,
[CANCELLER_TRUANT] = CancellerTruant,
[CANCELLER_FLINCH] = CancellerFlinch,
[CANCELLER_IN_LOVE] = CancellerInLove,
[CANCELLER_INFATUATION] = CancellerInfatuation,
[CANCELLER_DISABLED] = CancellerDisabled,
[CANCELLER_HEAL_BLOCKED] = CancellerHealBlocked,
[CANCELLER_GRAVITY] = CancellerGravity,
[CANCELLER_THROAT_CHOP] = CancellerThroatChop,
[CANCELLER_VOLATILE_BLOCKED] = CancellerVolatileBlocked,
[CANCELLER_TAUNTED] = CancellerTaunted,
[CANCELLER_IMPRISONED] = CancellerImprisoned,
[CANCELLER_CONFUSED] = CancellerConfused,
@ -2562,17 +2574,17 @@ static const MoveSuccessOrderCancellers sMoveSuccessOrderCancellers[] =
[CANCELLER_MULTI_TARGET_MOVES] = CancellerMultiTargetMoves,
};
u32 AtkCanceller_MoveSuccessOrder(void)
enum MoveCanceller AtkCanceller_MoveSuccessOrder(void)
{
u32 effect = 0;
enum MoveCanceller effect = MOVE_STEP_SUCCESS;
while (gBattleStruct->atkCancellerTracker < CANCELLER_END && effect == 0)
while (gBattleStruct->atkCancellerTracker < CANCELLER_END && effect == MOVE_STEP_SUCCESS)
{
sMoveSuccessOrderCancellers[gBattleStruct->atkCancellerTracker](&effect);
effect = sMoveSuccessOrderCancellers[gBattleStruct->atkCancellerTracker]();
gBattleStruct->atkCancellerTracker++;
}
if (effect == 2)
if (effect == MOVE_STEP_REMOVES_STATUS)
{
BtlController_EmitSetMonData(gBattlerAttacker, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, 4, &gBattleMons[gBattlerAttacker].status1);
MarkBattlerForControllerExec(gBattlerAttacker);