From 11d2b3a812d230b05e676f443a45fdb07d851bf2 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 4 Sep 2026 20:59:48 +0200 Subject: [PATCH] Combine UpdateLastMoves and MirrorMove states (#10740) --- include/constants/battle_move_resolution.h | 7 +- src/battle_move_resolution.c | 184 ++++++++++----------- 2 files changed, 91 insertions(+), 100 deletions(-) diff --git a/include/constants/battle_move_resolution.h b/include/constants/battle_move_resolution.h index bf9f550b4c..7ac2865259 100644 --- a/include/constants/battle_move_resolution.h +++ b/include/constants/battle_move_resolution.h @@ -192,8 +192,6 @@ enum MoveEndState MOVEEND_SYMBIOSIS_ALLIED_SIDE, MOVEEND_FAINT_BLOCK_ALLIED_SIDE, MOVEEND_FAINT_ATTACKER_ALLIED_SIDE, - MOVEEND_UPDATE_LAST_MOVES_ALLIED_SIDE, - MOVEEND_MIRROR_MOVE_ALLIED_SIDE, // Switch to opposing side MOVEEND_SET_VALUES_FOR_OPPOSING_SIDE, MOVEEND_SUBSTITUTE_BLOCK_OPPOSING_SIDE, @@ -212,10 +210,9 @@ enum MoveEndState MOVEEND_SYMBIOSIS_OPPOSING_SIDE, MOVEEND_FAINT_BLOCK_OPPOSING_SIDE, MOVEEND_FAINT_ATTACKER_OPPOSING_SIDE, - MOVEEND_UPDATE_LAST_MOVES_OPPOSING_SIDE, - MOVEEND_MIRROR_MOVE_OPPOSING_SIDE, MOVEEND_NEXT_TARGET, // Everything up until here is handled for each strike of a spread move - // Check all battlers + MOVEEND_UPDATE_LAST_MOVES, + MOVEEND_MIRROR_MOVE, MOVEEND_BOUNCED_MOVE, MOVEEND_MULTIHIT_MOVE_BLOCK, // HP threshold items, effectiveness message, end move MOVEEND_DEFROST, diff --git a/src/battle_move_resolution.c b/src/battle_move_resolution.c index a4841074aa..34347e5b41 100644 --- a/src/battle_move_resolution.c +++ b/src/battle_move_resolution.c @@ -50,6 +50,7 @@ static bool32 ShouldPrintProtectMessage(enum BattlerId battler); static bool32 ShouldPrintEffectivenessMessage(struct BattleCalcValues *cv); // Stat change moves +bool32 IsStatChangeMove(enum Move move); static bool32 TryBellyDrum(enum BattlerId battler); static bool32 TryHalfHp(enum BattlerId battler); static bool32 CutThirdOfHp(enum BattlerId battler); @@ -2309,7 +2310,6 @@ static enum CancelerResult CancelerTargetFailure(struct BattleCalcValues *cv) if (ctx.abilityBlocked) { - gSpecialStatuses[cv->battlerDef].resultMessagePrinted = TRUE; gSpecialStatuses[cv->battlerDef].updateStallMons = TRUE; gBattleStruct->moveResultFlags[cv->battlerDef] = MOVE_RESULT_FAILED; gBattlerAbility = cv->battlerDef; @@ -2319,7 +2319,6 @@ static enum CancelerResult CancelerTargetFailure(struct BattleCalcValues *cv) } else if (ctx.airBalloonBlocked) { - gSpecialStatuses[cv->battlerDef].resultMessagePrinted = TRUE; gSpecialStatuses[cv->battlerDef].updateStallMons = TRUE; gBattleStruct->moveResultFlags[cv->battlerDef] = MOVE_RESULT_FAILED; BattleScriptCall(BattleScript_DoesntAffectScripting); @@ -2327,7 +2326,6 @@ static enum CancelerResult CancelerTargetFailure(struct BattleCalcValues *cv) } else if (ctx.typeEffectivenessModifier == UQ_4_12(0.0)) { - gSpecialStatuses[cv->battlerDef].resultMessagePrinted = TRUE; TryInitializeTrainerSlideMonUnaffected(cv->battlerDef, cv->battlerAtk); gSpecialStatuses[cv->battlerDef].updateStallMons = TRUE; gBattleStruct->moveResultFlags[cv->battlerDef] = MOVE_RESULT_FAILED; @@ -2336,7 +2334,6 @@ static enum CancelerResult CancelerTargetFailure(struct BattleCalcValues *cv) } else if (IsTargetUnaffectedByMoveEffect(cv)) { - gSpecialStatuses[cv->battlerDef].resultMessagePrinted = TRUE; TryInitializeTrainerSlideMonUnaffected(cv->battlerDef, cv->battlerAtk); gSpecialStatuses[cv->battlerDef].updateStallMons = TRUE; return TargetAvoidedAttack(cv->battlerAtk, cv->battlerDef); @@ -4431,6 +4428,74 @@ static enum MoveEndResult MoveEndFaintAttacker(struct BattleCalcValues *cv) return MOVEEND_RESULT_CONTINUE; } +static enum MoveEndResult MoveEndSetValuesForOpposingSide(struct BattleCalcValues *cv) +{ + if (!IsBattleMoveStatus(cv->move)) + { + cv->battlerDef = GetBattlerLeftFoe(cv->battlerAtk); + gBattleScripting.moveendState++; + } + else + { + gBattleScripting.moveendState = MOVEEND_NEXT_TARGET; + } + + return MOVEEND_RESULT_CONTINUE; +} + +static enum MoveEndResult MoveEndNextTarget(struct BattleCalcValues *cv) +{ + enum MoveTarget moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); + + if (gBattleStruct->unableToUseMove || gProtectStructs[gBattlerAttacker].chargingTurn || !IsBattleMoveStatus(cv->move)) + { + // go to next state + } + else if (moveTarget == TARGET_USER_AND_ALLY) + { + enum BattlerId partner = GetPartnerBattler(gBattlerAttacker); + gBattleStruct->battlerState[gBattlerAttacker].targetsDone[gBattlerTarget] = TRUE; + + if (partner != gBattlerTarget && IsBattlerAlive(partner)) + { + gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = partner; + gBattleScripting.moveendState = 0; + + if (IsStatChangeMove(cv->move)) + return MOVEEND_RESULT_CONTINUE; + else + BattleScriptPush(GetMoveBattleScript(cv->move)); + + gBattlescriptCurrInstr = BattleScript_FlushMessageBox; + return MOVEEND_RESULT_BREAK; + } + } + else if (IsSpreadMove(moveTarget)) + { + gBattleStruct->battlerState[gBattlerAttacker].targetsDone[gBattlerTarget] = TRUE; + u32 nextTarget = GetNextTarget(moveTarget, FALSE); + + if (nextTarget != MAX_BATTLERS_COUNT) + { + // no point in writting + gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = nextTarget; // Fix for moxie spread moves + gBattleScripting.moveendState = 0; + + if (IsStatChangeMove(cv->move)) + return MOVEEND_RESULT_CONTINUE; + else + BattleScriptPush(GetMoveBattleScript(cv->move)); + + gBattlescriptCurrInstr = BattleScript_FlushMessageBox; + return MOVEEND_RESULT_BREAK; + } + } + + RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove); + gBattleScripting.moveendState++; + return MOVEEND_RESULT_CONTINUE; +} + static enum MoveEndResult MoveEndUpdateLastMoves(struct BattleCalcValues *cv) { if (!IsOnPlayerSide(cv->battlerAtk)) @@ -4540,93 +4605,6 @@ static enum MoveEndResult MoveEndMirrorMove(struct BattleCalcValues *cv) return MOVEEND_RESULT_CONTINUE; } -// Used for non damaging (status) stat change moves -bool32 IsStatChangeMove(enum Move move) -{ - u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); - for (u32 i = 0; i < additionalEffectCount; i++) - { - const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); - switch (additionalEffect->moveEffect) - { - case STAT_CHANGE_EFFECT_MINUS: - case STAT_CHANGE_EFFECT_PLUS: - return TRUE; - default: - return FALSE; - } - } - return FALSE; -} - -static enum MoveEndResult MoveEndSetValuesForOpposingSide(struct BattleCalcValues *cv) -{ - if (!IsBattleMoveStatus(cv->move)) - { - cv->battlerDef = GetBattlerLeftFoe(cv->battlerAtk); - gBattleScripting.moveendState++; - } - else - { - gBattleScripting.moveendState = MOVEEND_NEXT_TARGET; - } - - return MOVEEND_RESULT_CONTINUE; -} - -static enum MoveEndResult MoveEndNextTarget(struct BattleCalcValues *cv) -{ - enum MoveTarget moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - - if (gBattleStruct->unableToUseMove || gProtectStructs[gBattlerAttacker].chargingTurn || !IsBattleMoveStatus(cv->move)) - { - // go to next state - } - else if (moveTarget == TARGET_USER_AND_ALLY) - { - enum BattlerId partner = GetPartnerBattler(gBattlerAttacker); - gBattleStruct->battlerState[gBattlerAttacker].targetsDone[gBattlerTarget] = TRUE; - - if (partner != gBattlerTarget && IsBattlerAlive(partner)) - { - gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = partner; - gBattleScripting.moveendState = 0; - - if (IsStatChangeMove(cv->move)) - return MOVEEND_RESULT_CONTINUE; - else - BattleScriptPush(GetMoveBattleScript(cv->move)); - - gBattlescriptCurrInstr = BattleScript_FlushMessageBox; - return MOVEEND_RESULT_BREAK; - } - } - else if (IsSpreadMove(moveTarget)) - { - gBattleStruct->battlerState[gBattlerAttacker].targetsDone[gBattlerTarget] = TRUE; - u32 nextTarget = GetNextTarget(moveTarget, FALSE); - - if (nextTarget != MAX_BATTLERS_COUNT) - { - // no point in writting - gBattleStruct->moveTarget[gBattlerAttacker] = gBattlerTarget = nextTarget; // Fix for moxie spread moves - gBattleScripting.moveendState = 0; - - if (IsStatChangeMove(cv->move)) - return MOVEEND_RESULT_CONTINUE; - else - BattleScriptPush(GetMoveBattleScript(cv->move)); - - gBattlescriptCurrInstr = BattleScript_FlushMessageBox; - return MOVEEND_RESULT_BREAK; - } - } - - RecordLastUsedMoveBy(gBattlerAttacker, gCurrentMove); - gBattleScripting.moveendState++; - return MOVEEND_RESULT_CONTINUE; -} - static enum MoveEndResult MoveEndBouncedMove(struct BattleCalcValues *cv) { if (gBattleStruct->bouncedMoveIsUsed) @@ -6069,8 +6047,6 @@ static enum MoveEndResult (*const sMoveEndHandlers[])(struct BattleCalcValues *c [MOVEEND_SYMBIOSIS_ALLIED_SIDE] = MoveEndSymbiosis, [MOVEEND_FAINT_BLOCK_ALLIED_SIDE] = MoveEndFaintBlock, [MOVEEND_FAINT_ATTACKER_ALLIED_SIDE] = MoveEndFaintAttacker, - [MOVEEND_UPDATE_LAST_MOVES_ALLIED_SIDE] = MoveEndUpdateLastMoves, - [MOVEEND_MIRROR_MOVE_ALLIED_SIDE] = MoveEndMirrorMove, [MOVEEND_SET_VALUES_FOR_OPPOSING_SIDE] = MoveEndSetValuesForOpposingSide, [MOVEEND_SUBSTITUTE_BLOCK_OPPOSING_SIDE] = MoveEndSubstituteBlock, [MOVEEND_EFFECTIVENESS_MESSAGE_OPPOSING_SIDE] = MoveEndEffectivenessMessage, @@ -6088,9 +6064,9 @@ static enum MoveEndResult (*const sMoveEndHandlers[])(struct BattleCalcValues *c [MOVEEND_SYMBIOSIS_OPPOSING_SIDE] = MoveEndSymbiosis, [MOVEEND_FAINT_BLOCK_OPPOSING_SIDE] = MoveEndFaintBlock, [MOVEEND_FAINT_ATTACKER_OPPOSING_SIDE] = MoveEndFaintAttacker, - [MOVEEND_UPDATE_LAST_MOVES_OPPOSING_SIDE] = MoveEndUpdateLastMoves, - [MOVEEND_MIRROR_MOVE_OPPOSING_SIDE] = MoveEndMirrorMove, [MOVEEND_NEXT_TARGET] = MoveEndNextTarget, + [MOVEEND_UPDATE_LAST_MOVES] = MoveEndUpdateLastMoves, + [MOVEEND_MIRROR_MOVE] = MoveEndMirrorMove, [MOVEEND_BOUNCED_MOVE] = MoveEndBouncedMove, [MOVEEND_MULTIHIT_MOVE_BLOCK] = MoveEndMultihitMoveBlock, [MOVEEND_DEFROST] = MoveEndDefrost, @@ -6983,6 +6959,24 @@ static void UpdateStallMons(struct BattleCalcValues *cv) // Move Stat Change Functions +bool32 IsStatChangeMove(enum Move move) +{ + u32 additionalEffectCount = GetMoveAdditionalEffectCount(move); + for (u32 i = 0; i < additionalEffectCount; i++) + { + const struct AdditionalEffect *additionalEffect = GetMoveAdditionalEffectById(move, i); + switch (additionalEffect->moveEffect) + { + case STAT_CHANGE_EFFECT_MINUS: + case STAT_CHANGE_EFFECT_PLUS: + return TRUE; + default: + return FALSE; + } + } + return FALSE; +} + static bool32 TryBellyDrum(enum BattlerId battler) { if (CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_EQUAL, ABILITY_NONE))