From 786859b6bb596d3d0d7951ec4798901fe0fe488d Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 19 Oct 2025 22:38:27 +0200 Subject: [PATCH] Fix Fling Mental Herb message (#7984) --- asm/macros/battle_script.inc | 11 +-- data/battle_scripts_1.s | 43 +----------- include/battle.h | 1 + include/battle_hold_effects.h | 4 +- include/battle_scripts.h | 1 + src/battle_hold_effects.c | 3 +- src/battle_script_commands.c | 115 +++++++++++++++++--------------- src/data/hold_effects.h | 2 + test/battle/move_effect/fling.c | 21 ++++++ 9 files changed, 95 insertions(+), 106 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9170ffc85d..39ecce81a6 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1790,11 +1790,8 @@ .4byte \jumpInstr .endm - .macro jumpiflastuseditemholdeffect holdEffect:req, secondaryId:req, jumpInstr:req - callnative BS_JumpIfLastUsedItemHoldEffect - .byte \holdEffect - .2byte \secondaryId - .4byte \jumpInstr + .macro tryflingholdeffect + callnative BS_TryFlingHoldEffect .endm .macro swapsidestatuses @@ -2391,10 +2388,6 @@ .4byte \failInstr .endm - .macro curecertainstatuses - callnative BS_CureCertainStatuses - .endm - .macro tryresetnegativestatstages callnative BS_TryResetNegativeStatStages .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 94ad23d029..2aaf0649b3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -697,15 +697,9 @@ BattleScript_EffectFling:: resultmessage waitmessage B_WAIT_TIME_MED jumpiflastuseditemberry BattleScript_EffectFlingConsumeBerry - jumpifability BS_TARGET, ABILITY_SHIELD_DUST, BattleScript_FlingBlockedByShieldDust - jumpiflastuseditemholdeffect HOLD_EFFECT_FLAME_ORB, 0, BattleScript_FlingFlameOrb - jumpiflastuseditemholdeffect HOLD_EFFECT_FLINCH, 0, BattleScript_FlingFlinch - jumpiflastuseditemholdeffect HOLD_EFFECT_LIGHT_BALL, 0, BattleScript_FlingLightBall - jumpiflastuseditemholdeffect HOLD_EFFECT_MENTAL_HERB, 0, BattleScript_FlingMentalHerb - jumpiflastuseditemholdeffect HOLD_EFFECT_TYPE_POWER, TYPE_POISON, BattleScript_FlingPoisonBarb - jumpiflastuseditemholdeffect HOLD_EFFECT_TOXIC_ORB, 0, BattleScript_FlingToxicOrb - jumpiflastuseditemholdeffect HOLD_EFFECT_WHITE_HERB, 0, BattleScript_FlingWhiteHerb + tryflingholdeffect goto BattleScript_FlingEnd + BattleScript_EffectFlingConsumeBerry: savebattleritem battleritemtolastuseditem @@ -729,39 +723,6 @@ BattleScript_FlingBlockedByShieldDust:: waitmessage B_WAIT_TIME_LONG goto BattleScript_FlingEnd -BattleScript_FlingFlameOrb: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_BURN - goto BattleScript_FlingEnd -BattleScript_FlingFlinch: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_FLINCH - goto BattleScript_FlingEnd -BattleScript_FlingLightBall: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_PARALYSIS - goto BattleScript_FlingEnd -BattleScript_FlingMentalHerb: - curecertainstatuses - saveattacker - copybyte gBattlerAttacker, gBattlerTarget - playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT, NULL - printfromtable gMentalHerbCureStringIds - waitmessage B_WAIT_TIME_LONG - updatestatusicon BS_ATTACKER - restoreattacker - goto BattleScript_FlingEnd -BattleScript_FlingPoisonBarb: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_POISON - goto BattleScript_FlingEnd -BattleScript_FlingToxicOrb: - seteffectsecondary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_TOXIC - goto BattleScript_FlingEnd -BattleScript_FlingWhiteHerb: - tryresetnegativestatstages - swapattackerwithtarget - printstring STRINGID_PKMNSTATUSNORMAL - waitmessage B_WAIT_TIME_MED - swapattackerwithtarget - goto BattleScript_FlingEnd - BattleScript_FlingMissed: removeitem BS_ATTACKER goto BattleScript_MoveMissedPause diff --git a/include/battle.h b/include/battle.h index 1888c249de..1ec919c229 100644 --- a/include/battle.h +++ b/include/battle.h @@ -781,6 +781,7 @@ struct BattleStruct u8 hazardsCounter:4; // Counter for applying hazard on switch in enum SubmoveState submoveAnnouncement:2; u8 padding2:2; + u16 flingItem; }; struct AiBattleData diff --git a/include/battle_hold_effects.h b/include/battle_hold_effects.h index 5ee1d4a494..7ddace7782 100644 --- a/include/battle_hold_effects.h +++ b/include/battle_hold_effects.h @@ -20,7 +20,8 @@ struct HoldEffectInfo u32 leftovers:1; u32 orbs:1; u32 onEffect:1; - u32 padding:15; + u32 onFling:1; + u32 padding:14; }; extern const struct HoldEffectInfo gHoldEffectsInfo[]; @@ -48,5 +49,6 @@ bool32 IsOrbsActivation(enum HoldEffect holdEffect); bool32 IsOnEffectActivation(enum HoldEffect holdEffect); bool32 IsActivationForceTriggerItem(enum HoldEffect holdEffect); bool32 IsActivationOnBerry(enum HoldEffect holdEffect); +bool32 IsOnFlingActivation(enum HoldEffect holdEffect); #endif // GUARD_BATTLE_HOLD_EFFECTS diff --git a/include/battle_scripts.h b/include/battle_scripts.h index a0d99d9de3..d64d9812aa 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -14,6 +14,7 @@ extern const u8 BattleScript_MoveMissedPause[]; extern const u8 BattleScript_MoveMissedPause[]; extern const u8 BattleScript_MoveMissed[]; extern const u8 BattleScript_FlingFailConsumeItem[]; +extern const u8 BattleScript_FlingBlockedByShieldDust[]; extern const u8 BattleScript_FailedFromAtkCanceler[]; extern const u8 BattleScript_ButItFailed[]; extern const u8 BattleScript_StatUp[]; diff --git a/src/battle_hold_effects.c b/src/battle_hold_effects.c index 907350cff5..b325956d9d 100644 --- a/src/battle_hold_effects.c +++ b/src/battle_hold_effects.c @@ -28,6 +28,7 @@ bool32 IsLeftoversActivation(enum HoldEffect holdEffect) { return gHol bool32 IsOrbsActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].orbs; } bool32 IsOnEffectActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onEffect; } bool32 IsActivationOnBerry(enum HoldEffect holdEffect) { return GetItemPocket(gLastUsedItem) == POCKET_BERRIES; } +bool32 IsOnFlingActivation(enum HoldEffect holdEffect) { return gHoldEffectsInfo[holdEffect].onFling; } bool32 IsActivationForceTriggerItem(enum HoldEffect holdEffect) { @@ -177,7 +178,7 @@ static enum ItemEffect RestoreWhiteHerbStats(u32 battler, ActivationTiming timin } if (effect != ITEM_NO_EFFECT) { - if (timing == IsWhiteHerbActivation) + if (timing == IsWhiteHerbActivation || timing == IsOnFlingActivation) BattleScriptCall(BattleScript_WhiteHerbRet); else BattleScriptExecute(BattleScript_WhiteHerbEnd2); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index e74265b649..33ca053ad7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -16332,14 +16332,68 @@ void BS_JumpIfCanGigantamax(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfLastUsedItemHoldEffect(void) +void BS_TryFlingHoldEffect(void) { - NATIVE_ARGS(u8 holdEffect, u16 secondaryId, const u8 *jumpInstr); - if (GetItemHoldEffect(gLastUsedItem) == cmd->holdEffect - && (cmd->secondaryId == 0 || GetItemSecondaryId(gLastUsedItem) == cmd->secondaryId)) - gBattlescriptCurrInstr = cmd->jumpInstr; - else + NATIVE_ARGS(); + enum HoldEffect holdEffect = GetItemHoldEffect(gBattleStruct->flingItem); + gBattleStruct->flingItem = ITEM_NONE; + + if (IsMoveEffectBlockedByTarget(GetBattlerAbility(gBattlerTarget))) + { + gBattlescriptCurrInstr = BattleScript_FlingBlockedByShieldDust; + return; + } + + switch (holdEffect) + { + case HOLD_EFFECT_FLAME_ORB: + gBattlescriptCurrInstr = cmd->nextInstr - 1; + gBattleScripting.moveEffect = MOVE_EFFECT_BURN; + SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE); + break; + case HOLD_EFFECT_TOXIC_ORB: + gBattlescriptCurrInstr = cmd->nextInstr - 1; + gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC; + SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE); + break; + case HOLD_EFFECT_LIGHT_BALL: + gBattlescriptCurrInstr = cmd->nextInstr - 1; + gBattleScripting.moveEffect = MOVE_EFFECT_PARALYSIS; + SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE); + break; + case HOLD_EFFECT_TYPE_POWER: + if (GetItemSecondaryId(gLastUsedItem) != TYPE_POISON) + { + gBattlescriptCurrInstr = cmd->nextInstr; + } + else + { + gBattlescriptCurrInstr = cmd->nextInstr - 1; + gBattleScripting.moveEffect = MOVE_EFFECT_POISON; + SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE); + } + break; + case HOLD_EFFECT_FLINCH: + gBattlescriptCurrInstr = cmd->nextInstr - 1; + gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; + SetMoveEffect(gBattlerAttacker, gBattlerTarget, FALSE, FALSE); + break; + case HOLD_EFFECT_MENTAL_HERB: + if (ItemBattleEffects(gBattlerTarget, 0, holdEffect, IsOnFlingActivation)) + return; + else + gBattlescriptCurrInstr = cmd->nextInstr; + break; + case HOLD_EFFECT_WHITE_HERB: + if (ItemBattleEffects(gBattlerTarget, 0, holdEffect, IsOnFlingActivation)) + return; + else + gBattlescriptCurrInstr = cmd->nextInstr; + break; + default: gBattlescriptCurrInstr = cmd->nextInstr; + break; + } } void BS_JumpIfNoWhiteOut(void) @@ -16507,6 +16561,7 @@ void BS_SetLastUsedItem(void) { NATIVE_ARGS(u8 battler); gLastUsedItem = gBattleMons[GetBattlerForBattleScript(cmd->battler)].item; + gBattleStruct->flingItem = gLastUsedItem; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -17924,54 +17979,6 @@ void BS_SetPoltergeistMessage(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_CureCertainStatuses(void) -{ - NATIVE_ARGS(); - // Check infatuation - if (gBattleMons[gBattlerTarget].volatiles.infatuation) - { - gBattleMons[gBattlerTarget].volatiles.infatuation = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_INFATUATION; // STRINGID_TARGETGOTOVERINFATUATION - StringCopy(gBattleTextBuff1, gStatusConditionString_LoveJpn); - } - // Check taunt - if (gDisableStructs[gBattlerTarget].tauntTimer != 0) - { - gDisableStructs[gBattlerTarget].tauntTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TAUNT; - PREPARE_MOVE_BUFFER(gBattleTextBuff1, MOVE_TAUNT); - } - // Check encore - if (gDisableStructs[gBattlerTarget].encoreTimer != 0) - { - gDisableStructs[gBattlerTarget].encoredMove = 0; - gDisableStructs[gBattlerTarget].encoreTimer = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_ENCORE; // STRINGID_PKMNENCOREENDED - } - // Check torment - if (gBattleMons[gBattlerTarget].volatiles.torment == TRUE) - { - gBattleMons[gBattlerTarget].volatiles.torment = FALSE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_TORMENT; - } - // Check heal block - if (gBattleMons[gBattlerTarget].volatiles.healBlock) - { - gBattleMons[gBattlerTarget].volatiles.healBlock = FALSE; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_HEALBLOCK; - } - // Check disable - if (gDisableStructs[gBattlerTarget].disableTimer != 0) - { - gDisableStructs[gBattlerTarget].disableTimer = 0; - gDisableStructs[gBattlerTarget].disabledMove = 0; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_MENTALHERBCURE_DISABLE; - } - - gBattleScripting.battler = gBattlerTarget; - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_TryResetNegativeStatStages(void) { NATIVE_ARGS(); diff --git a/src/data/hold_effects.h b/src/data/hold_effects.h index f56b6811f9..221c9e166f 100644 --- a/src/data/hold_effects.h +++ b/src/data/hold_effects.h @@ -163,6 +163,7 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] = .whiteHerb = TRUE, .whiteHerbFirstTurn = TRUE, .whiteHerbEndTurn = TRUE, + .onFling = TRUE, }, [HOLD_EFFECT_MACHO_BRACE] = @@ -185,6 +186,7 @@ const struct HoldEffectInfo gHoldEffectsInfo[HOLD_EFFECT_COUNT] = { .onTargetAfterHit = TRUE, .onAttackerAfterHit = TRUE, + .onFling = TRUE, }, [HOLD_EFFECT_CHOICE_BAND] = diff --git a/test/battle/move_effect/fling.c b/test/battle/move_effect/fling.c index 1efbd3fce7..4a3ca4597c 100644 --- a/test/battle/move_effect/fling.c +++ b/test/battle/move_effect/fling.c @@ -461,4 +461,25 @@ SINGLE_BATTLE_TEST("Fling deals damage based on items fling power") } } +SINGLE_BATTLE_TEST("Flinging a Mental Herb does not trigger the item if the target doesn't have anything that's cured by Mental Herb") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_MENTAL_HERB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FLING); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FLING, player); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + MESSAGE("The opposing Wobbuffet got over its infatuation!"); + MESSAGE("The opposing Wobbuffet's Taunt wore off!"); + MESSAGE("The opposing Wobbuffet ended its encore!"); + MESSAGE("The opposing Wobbuffet is no longer tormented!"); + MESSAGE("The opposing Wobbuffet's move is no longer disabled!"); + MESSAGE("The opposing Wobbuffet is cured of its heal block!"); + } + } +} + TO_DO_BATTLE_TEST("Fling deals damage based on a TM's move power")