From 97d8bd2646f8cde956a05872ee048d6a7f3ba873 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 31 Jan 2025 22:02:26 +0100 Subject: [PATCH] Fixes Dragon Tail missing timing against Rocky Helmet / Iron Barbs (#6154) --- asm/macros/battle_script.inc | 5 -- data/battle_scripts_1.s | 29 ++++++----- include/battle_scripts.h | 5 +- include/constants/battle_script_commands.h | 1 + src/battle_script_commands.c | 57 +++++++++++++-------- src/data/battle_move_effects.h | 2 +- test/battle/move_effect/hit_switch_target.c | 49 ++++++++++++++++++ 7 files changed, 109 insertions(+), 39 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index a5e21af674..67d97fda02 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1721,11 +1721,6 @@ .4byte \failInstr .endm - .macro tryhitswitchtarget failInstr:req - callnative BS_TryHitSwitchTarget - .4byte \failInstr - .endm - .macro setmagiccoattarget callnative BS_SetMagicCoatTarget .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bb4e4ea2bd..88cd06d596 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1798,25 +1798,17 @@ BattleScript_EffectFinalGambit:: jumpifmovehadnoeffect BattleScript_MoveEnd goto BattleScript_MoveEnd -BattleScript_EffectHitSwitchTarget:: - call BattleScript_EffectHit_Ret - tryfaintmon BS_TARGET - jumpiffainted BS_TARGET, TRUE, BattleScript_MoveEnd - jumpifability BS_TARGET, ABILITY_SUCTION_CUPS, BattleScript_AbilityPreventsPhasingOut - jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_MoveEnd - jumpifstatus3 BS_TARGET, STATUS3_ROOTED, BattleScript_PrintMonIsRooted - jumpiftargetdynamaxed BattleScript_HitSwitchTargetDynamaxed - tryhitswitchtarget BattleScript_MoveEnd +BattleScript_TryHitSwitchTarget:: forcerandomswitch BattleScript_HitSwitchTargetForceRandomSwitchFailed - goto BattleScript_MoveEnd + return -BattleScript_HitSwitchTargetDynamaxed: +BattleScript_HitSwitchTargetDynamaxed:: printstring STRINGID_MOVEBLOCKEDBYDYNAMAX waitmessage B_WAIT_TIME_LONG BattleScript_HitSwitchTargetForceRandomSwitchFailed: hitswitchtargetfailed setbyte sSWITCH_CASE, B_SWITCH_NORMAL - goto BattleScript_MoveEnd + return BattleScript_EffectToxicThread:: setstatchanger STAT_SPEED, 1, TRUE @@ -6774,6 +6766,12 @@ BattleScript_PrintMonIsRooted:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +BattleScript_PrintMonIsRootedRet:: + pause B_WAIT_TIME_SHORT + printstring STRINGID_PKMNANCHOREDITSELF + waitmessage B_WAIT_TIME_LONG + return + BattleScript_AtkDefDown:: setbyte sSTAT_ANIM_PLAYED, FALSE playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_ATK, STAT_CHANGE_CANT_PREVENT | STAT_CHANGE_NEGATIVE | STAT_CHANGE_MULTIPLE_STATS @@ -8261,6 +8259,13 @@ BattleScript_AbilityPreventsPhasingOut:: waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd +BattleScript_AbilityPreventsPhasingOutRet:: + pause B_WAIT_TIME_SHORT + call BattleScript_AbilityPopUp + printstring STRINGID_PKMNANCHORSITSELFWITH + waitmessage B_WAIT_TIME_LONG + return + BattleScript_AbilityNoStatLoss:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 1404a40718..fb830c275b 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -770,7 +770,10 @@ extern const u8 BattleScript_EffectDefenseUp3[]; extern const u8 BattleScript_EffectNobleRoar[]; extern const u8 BattleScript_EffectVenomDrench[]; extern const u8 BattleScript_EffectToxicThread[]; -extern const u8 BattleScript_EffectHitSwitchTarget[]; +extern const u8 BattleScript_TryHitSwitchTarget[]; +extern const u8 BattleScript_HitSwitchTargetDynamaxed[]; +extern const u8 BattleScript_AbilityPreventsPhasingOutRet[]; +extern const u8 BattleScript_PrintMonIsRootedRet[]; extern const u8 BattleScript_EffectFinalGambit[]; extern const u8 BattleScript_EffectAutotomize[]; extern const u8 BattleScript_EffectCopycat[]; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 20858c2365..c8f6b7cd5b 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -276,6 +276,7 @@ enum MoveEndEffects MOVEEND_ITEM_EFFECTS_TARGET, MOVEEND_MOVE_EFFECTS2, MOVEEND_ITEM_EFFECTS_ALL, + MOVEEND_HIT_SWITCH_TARGET, MOVEEND_KINGSROCK, // These item effects will occur each strike of a multi-hit move MOVEEND_NUM_HITS, MOVEEND_SUBSTITUTE, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 61082d33cd..7a7fddac98 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6077,6 +6077,43 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_HIT_SWITCH_TARGET: + if (gMovesInfo[gCurrentMove].effect == EFFECT_HIT_SWITCH_TARGET + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && TARGET_TURN_DAMAGED + && IsBattlerAlive(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT) + { + u32 targetAbility = GetBattlerAbility(gBattlerTarget); + if (targetAbility == ABILITY_GUARD_DOG) + { + gBattleScripting.moveendState++; + break; + } + + effect = TRUE; + BattleScriptPushCursor(); + if (targetAbility == ABILITY_SUCTION_CUPS) + { + gBattlescriptCurrInstr = BattleScript_AbilityPreventsPhasingOutRet; + } + else if (gStatuses3[gBattlerTarget] & STATUS3_ROOTED) + { + gBattlescriptCurrInstr = BattleScript_PrintMonIsRootedRet; + } + else if (GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) + { + gBattlescriptCurrInstr = BattleScript_HitSwitchTargetDynamaxed; + } + else + { + gBattleScripting.switchCase = B_SWITCH_HIT; + gBattlescriptCurrInstr = BattleScript_TryHitSwitchTarget; + } + } + gBattleScripting.moveendState++; + break; case MOVEEND_KINGSROCK: // King's rock // These effects will occur at each hit in a multi-strike move if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) @@ -17381,26 +17418,6 @@ void BS_JumpIfBlockedBySoundproof(void) } } -void BS_TryHitSwitchTarget(void) -{ - NATIVE_ARGS(const u8 *failInstr); - - if (IsBattlerAlive(gBattlerAttacker) - && IsBattlerAlive(gBattlerTarget) - && !(gMoveResultFlags & MOVE_RESULT_NO_EFFECT) - && TARGET_TURN_DAMAGED - && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT - && GetBattlerAbility(gBattlerTarget) != ABILITY_GUARD_DOG) - { - gBattleScripting.switchCase = B_SWITCH_HIT; - gBattlescriptCurrInstr = cmd->nextInstr; - } - else - { - gBattlescriptCurrInstr = cmd->failInstr; - } -} - void BS_SetMagicCoatTarget(void) { NATIVE_ARGS(); diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index ee281d6fe2..0b6a1dd72f 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -1571,7 +1571,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = [EFFECT_HIT_SWITCH_TARGET] = { - .battleScript = BattleScript_EffectHitSwitchTarget, + .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, diff --git a/test/battle/move_effect/hit_switch_target.c b/test/battle/move_effect/hit_switch_target.c index a899ae0b33..bc026110ee 100644 --- a/test/battle/move_effect/hit_switch_target.c +++ b/test/battle/move_effect/hit_switch_target.c @@ -69,3 +69,52 @@ SINGLE_BATTLE_TEST("Dragon Tail does not fail if replacements fainted") NOT MESSAGE("But it failed!"); } } + +SINGLE_BATTLE_TEST("Dragon Tail switches the target after Rocky Helmet and Iron Barbs") +{ + PASSES_RANDOMLY(1, 2, RNG_FORCE_RANDOM_SWITCH); + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_TOGEDEMARU) { Ability(ABILITY_IRON_BARBS); Item(ITEM_ROCKY_HELMET); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CHARMANDER); + } WHEN { + TURN { MOVE(player, MOVE_DRAGON_TAIL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, player); + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the opposing Togedemaru's Iron Barbs!"); + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the opposing Togedemaru's Rocky Helmet!"); + MESSAGE("The opposing Charmander was dragged out!"); + } +} + +SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Guard Dog ability") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_OKIDOGI) { Ability(ABILITY_GUARD_DOG); } + OPPONENT(SPECIES_CHARMANDER); + } WHEN { + TURN { MOVE(player, MOVE_DRAGON_TAIL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, player); + NOT MESSAGE("The opposing Charmander was dragged out!"); + } +} + +SINGLE_BATTLE_TEST("Dragon Tail effect will fails against Suction Cups ability") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_OCTILLERY) { Ability(ABILITY_SUCTION_CUPS); } + OPPONENT(SPECIES_CHARMANDER); + } WHEN { + TURN { MOVE(player, MOVE_DRAGON_TAIL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_TAIL, player); + MESSAGE("The opposing Octillery anchors itself with Suction Cups!"); + NOT MESSAGE("The opposing Charmander was dragged out!"); + } +}