From 09aa452659a73dd7b356f37f232500ce6ac59389 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 29 Sep 2025 19:32:11 +0200 Subject: [PATCH] Fix Throat Spray activating multiply times (#7818) --- include/battle_util.h | 1 + include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 20 ++++++++++++++++++++ src/battle_util.c | 18 +----------------- 4 files changed, 23 insertions(+), 17 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 0c486f4a3a..fd0fbbac46 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -388,6 +388,7 @@ bool32 IsPursuitTargetSet(void); void ClearPursuitValuesIfSet(u32 battler); void ClearPursuitValues(void); bool32 HasWeatherEffect(void); +bool32 IsAnyTargetAffected(u32 battlerAtk); u32 RestoreWhiteHerbStats(u32 battler); bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move); bool32 HadMoreThanHalfHpNowDoesnt(u32 battler); diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 2b4d590286..94d2a2bd48 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -153,6 +153,7 @@ enum MoveEndEffects MOVEEND_MULTIHIT_MOVE, MOVEEND_MOVE_BLOCK, MOVEEND_ITEM_EFFECTS_ATTACKER, + MOVEEND_ITEM_THROAT_SPRAY, MOVEEND_ABILITY_BLOCK, MOVEEND_SHEER_FORCE, // If move is Sheer Force affected, skip until Opportunist MOVEEND_RED_CARD, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f2b03a382e..9e1d6cc358 100755 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6494,10 +6494,30 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_ITEM_EFFECTS_ATTACKER: + // ITEMEFFECT_MOVE_END loops over all battlers, not just attacker. + // It will executre only the first mon with an applicable item. + // So presumably it is a bug if (ItemBattleEffects(ITEMEFFECT_MOVE_END, gBattlerAttacker)) effect = TRUE; gBattleScripting.moveendState++; break; + case MOVEEND_ITEM_THROAT_SPRAY: + if (IsSoundMove(gCurrentMove) + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_THROAT_SPRAY + && IsBattlerAlive(gBattlerAttacker) + && IsAnyTargetAffected(gBattlerAttacker) + && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN) + && !NoAliveMonsForEitherParty()) // Don't activate if battle will end + { + gLastUsedItem = gBattleMons[gBattlerAttacker].item; + gBattleScripting.battler = gBattlerAttacker; + SET_STATCHANGER(STAT_SPATK, 1, FALSE); + effect = TRUE; + BattleScriptCall(BattleScript_AttackerItemStatRaise); + } + gBattleScripting.moveendState++; + break; case MOVEEND_ABILITY_BLOCK: effect = HandleMoveEndAbilityBlock(gBattlerAttacker, gBattlerTarget, gCurrentMove); gBattleScripting.moveendState++; diff --git a/src/battle_util.c b/src/battle_util.c index 10d04161b0..c2fcdc08e9 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -65,7 +65,6 @@ static u32 GetFlingPowerFromItemId(u32 itemId); static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item); static bool32 CanBeInfinitelyConfused(u32 battler); -static bool32 IsAnyTargetAffected(u32 battlerAtk); static bool32 IsNonVolatileStatusBlocked(u32 battlerDef, u32 abilityDef, u32 abilityAffected, const u8 *battleScript, enum FunctionCallOption option); static bool32 CanSleepDueToSleepClause(u32 battlerAtk, u32 battlerDef, enum FunctionCallOption option); @@ -6501,21 +6500,6 @@ static u8 ItemEffectMoveEnd(u32 battler, enum ItemHoldEffect holdEffect) case HOLD_EFFECT_MIRROR_HERB: effect = TryConsumeMirrorHerb(battler, ITEMEFFECT_NONE); break; - case HOLD_EFFECT_THROAT_SPRAY: - if (IsSoundMove(gCurrentMove) - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && IsBattlerAlive(gBattlerAttacker) - && IsAnyTargetAffected(gBattlerAttacker) - && CompareStat(gBattlerAttacker, STAT_SPATK, MAX_STAT_STAGE, CMP_LESS_THAN) - && !NoAliveMonsForEitherParty()) // Don't activate if battle will end - { - gLastUsedItem = gBattleMons[gBattlerAttacker].item; - gBattleScripting.battler = gBattlerAttacker; - SET_STATCHANGER(STAT_SPATK, 1, FALSE); - effect = ITEM_STATS_CHANGE; - BattleScriptCall(BattleScript_AttackerItemStatRaise); - } - break; default: break; } @@ -11412,7 +11396,7 @@ bool32 HasWeatherEffect(void) return TRUE; } -static bool32 IsAnyTargetAffected(u32 battlerAtk) +bool32 IsAnyTargetAffected(u32 battlerAtk) { for (u32 battlerDef = 0; battlerDef < gBattlersCount; battlerDef++) {