From 142a5ef08c06025929875e7bd877ee2ededb269a Mon Sep 17 00:00:00 2001 From: FosterProgramming Date: Thu, 4 Dec 2025 00:35:38 +0100 Subject: [PATCH] Fix illusion not breaking properly when behind substitute (#8423) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- data/battle_anim_scripts.s | 10 ++++++++++ data/battle_scripts_1.s | 20 ++++++++++++++++++++ include/battle_anim_scripts.h | 2 ++ include/constants/battle_anim.h | 5 +++-- src/battle_anim.c | 2 ++ src/battle_gfx_sfx_util.c | 3 +++ test/battle/ability/illusion.c | 17 +++++++++++++++++ 7 files changed, 57 insertions(+), 2 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 2118d14c4b..5623654048 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -32134,6 +32134,16 @@ gBattleAnimGeneral_Swamp:: blendoff end +gBattleAnimGeneral_SwapToSubstitute:: + createvisualtask AnimTask_SwapMonSpriteToFromSubstitute, 2, FALSE + waitforvisualfinish + end + +gBattleAnimGeneral_SwapFromSubstitute:: + createvisualtask AnimTask_SwapMonSpriteToFromSubstitute, 2, TRUE + waitforvisualfinish + end + SnatchMoveTrySwapFromSubstitute: createvisualtask AnimTask_IsAttackerBehindSubstitute, 2 jumprettrue SnatchMoveSwapSubstituteForMon diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 3e5c79041a..85cd9cbef4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5951,8 +5951,10 @@ BattleScript_IllusionOffEnd3:: BattleScript_IllusionOff:: setspriteignore0hp TRUE + call BattleScript_SwapFromSubstitute playanimation BS_SCRIPTING, B_ANIM_ILLUSION_OFF waitanimation + call BattleScript_SwapToSubstitute updatenick waitstate setspriteignore0hp FALSE @@ -8857,3 +8859,21 @@ BattleScript_NaturePowerAttackstring:: printstring STRINGID_NATUREPOWERTURNEDINTO waitmessage B_WAIT_TIME_LONG return + +BattleScript_SwapFromSubstitute:: + jumpifvolatile BS_SCRIPTING, VOLATILE_SUBSTITUTE, BattleScript_SwapFromSubstituteContinue + goto BattleScript_SwapFromSubstituteReturn +BattleScript_SwapFromSubstituteContinue: + playanimation BS_SCRIPTING, B_ANIM_SWAP_FROM_SUBSTITUTE + waitanimation +BattleScript_SwapFromSubstituteReturn: + return + +BattleScript_SwapToSubstitute:: + jumpifvolatile BS_SCRIPTING, VOLATILE_SUBSTITUTE, BattleScript_SwapToSubstituteContinue + goto BattleScript_SwapToSubstituteReturn +BattleScript_SwapToSubstituteContinue: + playanimation BS_SCRIPTING, B_ANIM_SWAP_TO_SUBSTITUTE + waitanimation +BattleScript_SwapToSubstituteReturn: + return diff --git a/include/battle_anim_scripts.h b/include/battle_anim_scripts.h index 193696375d..febbfe9a2c 100644 --- a/include/battle_anim_scripts.h +++ b/include/battle_anim_scripts.h @@ -1005,6 +1005,8 @@ extern const u8 gBattleAnimGeneral_TeraCharge[]; extern const u8 gBattleAnimGeneral_TeraActivate[]; extern const u8 gBattleAnimGeneral_SimpleHeal[]; extern const u8 gBattleAnimGeneral_PowerConstruct[]; +extern const u8 gBattleAnimGeneral_SwapToSubstitute[]; +extern const u8 gBattleAnimGeneral_SwapFromSubstitute[]; // special animations extern const u8 gBattleAnimSpecial_LevelUp[]; diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 2ac2bc30f2..6ac604798f 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -592,8 +592,9 @@ #define B_ANIM_TERA_ACTIVATE 51 #define B_ANIM_SIMPLE_HEAL 52 #define B_ANIM_POWER_CONSTRUCT 53 - -#define NUM_B_ANIMS_GENERAL 54 +#define B_ANIM_SWAP_TO_SUBSTITUTE 54 +#define B_ANIM_SWAP_FROM_SUBSTITUTE 55 +#define NUM_B_ANIMS_GENERAL 56 // special animations table (sBattleAnims_Special) #define B_ANIM_LVL_UP 0 diff --git a/src/battle_anim.c b/src/battle_anim.c index f08c1eaa8d..cf1f32ed85 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -255,6 +255,8 @@ static const u8* const sBattleAnims_General[NUM_B_ANIMS_GENERAL] = [B_ANIM_TERA_ACTIVATE] = gBattleAnimGeneral_TeraActivate, [B_ANIM_SIMPLE_HEAL] = gBattleAnimGeneral_SimpleHeal, [B_ANIM_POWER_CONSTRUCT] = gBattleAnimGeneral_PowerConstruct, + [B_ANIM_SWAP_TO_SUBSTITUTE] = gBattleAnimGeneral_SwapToSubstitute, + [B_ANIM_SWAP_FROM_SUBSTITUTE] = gBattleAnimGeneral_SwapFromSubstitute, }; static const u8* const sBattleAnims_Special[NUM_B_ANIMS_SPECIAL] = diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 0e80a3e5f0..5a30edcdef 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -546,6 +546,9 @@ static bool8 ShouldAnimBeDoneRegardlessOfSubstitute(u8 animId) { switch (animId) { + case B_ANIM_ILLUSION_OFF: + case B_ANIM_SWAP_TO_SUBSTITUTE: + case B_ANIM_SWAP_FROM_SUBSTITUTE: case B_ANIM_SUBSTITUTE_FADE: case B_ANIM_RAIN_CONTINUES: case B_ANIM_SUN_CONTINUES: diff --git a/test/battle/ability/illusion.c b/test/battle/ability/illusion.c index 26c8daabc7..efa80cdafe 100644 --- a/test/battle/ability/illusion.c +++ b/test/battle/ability/illusion.c @@ -113,3 +113,20 @@ SINGLE_BATTLE_TEST("Illusion breaks if user loses Illusion due to Worry Seed") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ILLUSION_OFF, player); } } + +SINGLE_BATTLE_TEST("Illusion breaks when attacked behind a substitute") +{ + GIVEN { + PLAYER(SPECIES_DRAGAPULT) {Ability(ABILITY_INFILTRATOR); Speed(1);}; + OPPONENT(SPECIES_WOBBUFFET) {Speed(2);}; + OPPONENT(SPECIES_ZOROARK) {Speed(2);}; + OPPONENT(SPECIES_WYNAUT) {Speed(2);}; + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_SHED_TAIL); SEND_OUT(opponent, 1);} + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SWAP_FROM_SUBSTITUTE, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_ILLUSION_OFF, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SWAP_TO_SUBSTITUTE, opponent); + MESSAGE("The opposing Zoroark's illusion wore off!"); + } +}