From e0b76e98ff319901d1316ad9305620dbd57d56ed Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 22 Feb 2023 14:55:34 +0100 Subject: [PATCH] Add MOVE_SHELL_TRAP Effect (#2716) * implemented Shell Trap Co-authored-by: AgustinGDLV --- asm/macros/battle_script.inc | 5 + data/battle_anim_scripts.s | 144 +++++++++--------- data/battle_scripts_1.s | 18 +++ include/battle.h | 1 + include/battle_scripts.h | 1 + include/constants/battle_move_effects.h | 3 +- include/constants/battle_script_commands.h | 1 + include/constants/battle_string_ids.h | 4 +- src/battle_main.c | 3 + src/battle_message.c | 4 + src/battle_script_commands.c | 87 ++++++++--- src/battle_util.c | 3 +- src/data/battle_moves.h | 2 +- test/move_effect_shell_trap.c | 168 +++++++++++++++++++++ 14 files changed, 344 insertions(+), 100 deletions(-) create mode 100644 test/move_effect_shell_trap.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 5c71cef70..66c60a7cf 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2249,6 +2249,11 @@ .4byte \jumpInstr .endm + .macro jumpifshelltrap battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_SHELL_TRAP + .4byte \ptr + .endm + .macro hitswitchtargetfailed various 0, VARIOUS_HIT_SWITCH_TARGET_FAILED .endm diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 71bd93d70..75a831a33 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -12036,168 +12036,168 @@ ShellTrapUnleash: monbg ANIM_TARGET waitplaysewithpan SE_M_REFLECT, SOUND_PAN_ATTACKER, 0x10 delay 0x6 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapYellowImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapYellowImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x0 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x38, 0x0 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x2 - launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x4 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x38, 0x4 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x2 - launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x8 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x38, 0x8 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x2 - launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0xc - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x38, 0xc + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x2 - launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x10 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x38, 0x10 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x2 - launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x14 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x38, 0x14 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x2 - launchtemplate gFireSpiralOutwardSpriteTemplate 0x3 0x4 0x0 0x0 0x38 0x18 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gFireSpiralOutwardSpriteTemplate, ANIM_ATTACKER, 3, 0x0, 0x0, 0x38, 0x18 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 - launchtemplate gShellTrapRedImpactTemplate 0x2 0x4 0x0 0x0 0x0 0x2 + createsprite gShellTrapRedImpactTemplate, ANIM_ATTACKER, 2, 0x0, 0x0, 0x0, 0x2 delay 0x5 waitforvisualfinish call ShellTrapFireLaunch1 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0x0 0x0 0x0 0x38 0x4 0x4 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0x0, 0x0, 0x0, 0x38, 0x4, 0x4, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xfff6 0x0 0xfff6 0x38 0x4 0x4 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xfff6, 0x0, 0xfff6, 0x38, 0x4, 0x4, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xa 0x0 0xa 0x38 0xfffc 0x3 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xa, 0x0, 0xa, 0x38, 0xfffc, 0x3, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xffec 0x0 0xffec 0x38 0xfffc 0x5 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xffec, 0x0, 0xffec, 0x38, 0xfffc, 0x5, 0x1 delay 0x3 call ShellTrapFireLaunch2 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 delay 0x3 waitforvisualfinish clearmonbg ANIM_TARGET end ShellTrapFireLaunch1: - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0x0 0x0 0x0 0x38 0x4 0x4 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0x0, 0x0, 0x0, 0x38, 0x4, 0x4, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xfff6 0x0 0xfff6 0x38 0x4 0x4 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xfff6, 0x0, 0xfff6, 0x38, 0x4, 0x4, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xa 0x0 0xa 0x38 0xfffc 0x3 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xa, 0x0, 0xa, 0x38, 0xfffc, 0x3, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xffec 0x0 0xffec 0x38 0xfffc 0x5 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xffec, 0x0, 0xffec, 0x38, 0xfffc, 0x5, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xf 0x0 0xf 0x38 0x4 0x4 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xf, 0x0, 0xf, 0x38, 0x4, 0x4, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xffec 0x0 0xffec 0x38 0x4 0x4 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xffec, 0x0, 0xffec, 0x38, 0x4, 0x4, 0x1 delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0x14 0x0 0x14 0x38 0x4 0x4 0x1 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0x14, 0x0, 0x14, 0x38, 0x4, 0x4, 0x1 delay 0x3 return ShellTrapFireLaunch2: - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0x0 0x0 0x0 0x38 0x4 0x4 0x1 - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0x0, 0x0, 0x0, 0x38, 0x4, 0x4, 0x1 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xfff6 0x0 0xfff6 0x38 0x4 0x4 0x1 - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xfff6, 0x0, 0xfff6, 0x38, 0x4, 0x4, 0x1 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xa 0x0 0xa 0x38 0xfffc 0x3 0x1 - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xa, 0x0, 0xa, 0x38, 0xfffc, 0x3, 0x1 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xffec 0x0 0xffec 0x38 0xfffc 0x5 0x1 - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xffec, 0x0, 0xffec, 0x38, 0xfffc, 0x5, 0x1 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xf 0x0 0xf 0x38 0x4 0x4 0x1 - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xf, 0x0, 0xf, 0x38, 0x4, 0x4, 0x1 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0xffec 0x0 0xffec 0x38 0x4 0x4 0x1 - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0xffec, 0x0, 0xffec, 0x38, 0x4, 0x4, 0x1 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x3 - launchtemplate gShellTrapFireHitsTemplate 0x28 0x8 0x0 0x14 0x0 0x14 0x38 0x4 0x4 0x1 - launchtask AnimTask_ShakeMon 0x2 0x5 ANIM_TARGET 0x0003 0x0000 0x0006 0x0001 + createsprite gShellTrapFireHitsTemplate, ANIM_ATTACKER, 40, 0x0, 0x14, 0x0, 0x14, 0x38, 0x4, 0x4, 0x1 + createvisualtaskontargets AnimTask_ShakeMon, 0x2, 0, ANIM_TARGET, 0x0003, 0x0000, 0x0006, 0x0001 playsewithpan SE_M_FLAME_WHEEL, SOUND_PAN_ATTACKER delay 0x3 return diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 8ed23a922..5bf5f52b0 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -417,6 +417,7 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectVictoryDance @ EFFECT_VICTORY_DANCE .4byte BattleScript_EffectTeatime @ EFFECT_TEATIME .4byte BattleScript_EffectAttackUpUserAlly @ EFFECT_ATTACK_UP_USER_ALLY + .4byte BattleScript_EffectShellTrap @ EFFECT_SHELL_TRAP BattleScript_EffectAttackUpUserAlly: jumpifnoally BS_ATTACKER, BattleScript_EffectAttackUp @@ -557,6 +558,23 @@ BattleScript_AffectionBasedStatusHeal_Continue: waitstate end2 +BattleScript_ShellTrapSetUp:: + printstring STRINGID_EMPTYSTRING3 + waitmessage 0x1 + playanimation BS_ATTACKER, B_ANIM_SHELL_TRAP_SETUP, NULL + printstring STRINGID_PREPARESHELLTRAP + waitmessage B_WAIT_TIME_LONG + end2 + +BattleScript_EffectShellTrap:: + attackcanceler + jumpifshelltrap BS_ATTACKER, BattleScript_HitFromAccCheck + jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING | HITMARKER_NO_PPDEDUCT, BattleScript_MoveEnd + ppreduce + printstring STRINGID_SHELLTRAPDIDNTWORK + waitmessage B_WAIT_TIME_LONG + goto BattleScript_MoveEnd + BattleScript_EffectSteelBeam:: attackcanceler attackstring diff --git a/include/battle.h b/include/battle.h index e17733823..48c283ab4 100644 --- a/include/battle.h +++ b/include/battle.h @@ -143,6 +143,7 @@ struct ProtectStruct u16 quickDraw:1; u16 beakBlastCharge:1; u16 quash:1; + u16 shellTrap:1; u16 silkTrapped:1; u32 physicalDmg; u32 specialDmg; diff --git a/include/battle_scripts.h b/include/battle_scripts.h index d4e4d4b3c..7904f5dc1 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -453,6 +453,7 @@ extern const u8 BattleScript_BattlerFormChangeWithStringEnd3[]; extern const u8 BattleScript_DampPreventsAftermath[]; extern const u8 BattleScript_HealingWishActivates[]; extern const u8 BattleScript_LunarDanceActivates[]; +extern const u8 BattleScript_ShellTrapSetUp[]; // zmoves extern const u8 BattleScript_ZMoveActivateDamaging[]; diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index beab88151..061271dd5 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -398,7 +398,8 @@ #define EFFECT_VICTORY_DANCE 392 #define EFFECT_TEATIME 393 #define EFFECT_ATTACK_UP_USER_ALLY 394 // Howl 8th Gen +#define EFFECT_SHELL_TRAP 395 -#define NUM_BATTLE_MOVE_EFFECTS 395 +#define NUM_BATTLE_MOVE_EFFECTS 396 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 9699a2921..26064bcfb 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -258,6 +258,7 @@ #define VARIOUS_JUMP_IF_EMERGENCY_EXITED 166 #define VARIOUS_STORE_HEALING_WISH 167 #define VARIOUS_HIT_SWITCH_TARGET_FAILED 168 +#define VARIOUS_JUMP_IF_SHELL_TRAP 169 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 3f8853024..e561a9cb9 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -639,8 +639,10 @@ #define STRINGID_ABILITYWEAKENEDFSURROUNDINGMONSSTAT 637 #define STRINGID_ATTACKERGAINEDSTRENGTHFROMTHEFALLEN 638 #define STRINGID_PKMNSABILITYPREVENTSABILITY 639 +#define STRINGID_PREPARESHELLTRAP 640 +#define STRINGID_SHELLTRAPDIDNTWORK 641 -#define BATTLESTRINGS_COUNT 640 +#define BATTLESTRINGS_COUNT 642 // This is the string id that gBattleStringsTable starts with. // String ids before this (e.g. STRINGID_INTROMSG) are not in the table, diff --git a/src/battle_main.c b/src/battle_main.c index b23d8af55..6588d3c5e 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4954,6 +4954,9 @@ static void CheckChosenMoveForEffectsBeforeTurnStarts(void) case MOVE_BEAK_BLAST: BattleScriptExecute(BattleScript_BeakBlastSetUp); return; + case MOVE_SHELL_TRAP: + BattleScriptExecute(BattleScript_ShellTrapSetUp); + return; } } } diff --git a/src/battle_message.c b/src/battle_message.c index 2b8005f64..ec2527d84 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -774,6 +774,8 @@ static const u8 sText_StatWasHeightened[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s static const u8 sText_ElectricTerrainActivatedAbility[] = _("The Electric Terrain activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!"); static const u8 sText_AbilityWeakenedSurroundingMonsStat[] = _("{B_ATK_NAME_WITH_PREFIX}'s {B_ATK_ABILITY}\nweakened the {B_BUFF1} of\lall surrounding Pokémon!\p"); static const u8 sText_AttackerGainedStrengthFromTheFallen[] = _("{B_ATK_NAME_WITH_PREFIX} gained strength\nfrom the fallen!"); +static const u8 sText_PrepareShellTrap[] = _("{B_ATK_NAME_WITH_PREFIX} set a shell trap!"); +static const u8 sText_ShellTrapDidntWork[] = _("{B_ATK_NAME_WITH_PREFIX}'s shell trap didn't work!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { @@ -800,6 +802,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = [STRINGID_ZMOVEHPTRAP - BATTLESTRINGS_TABLE_START] = sText_ZMoveHpSwitchInTrap, [STRINGID_PLAYERLOSTTOENEMYTRAINER - BATTLESTRINGS_TABLE_START] = sText_PlayerLostToEnemyTrainer, [STRINGID_PLAYERPAIDPRIZEMONEY - BATTLESTRINGS_TABLE_START] = sText_PlayerPaidPrizeMoney, + [STRINGID_SHELLTRAPDIDNTWORK - BATTLESTRINGS_TABLE_START] = sText_ShellTrapDidntWork, + [STRINGID_PREPARESHELLTRAP - BATTLESTRINGS_TABLE_START] = sText_PrepareShellTrap, [STRINGID_COURTCHANGE - BATTLESTRINGS_TABLE_START] = sText_CourtChange, [STRINGID_HEATUPBEAK - BATTLESTRINGS_TABLE_START] = sText_HeatingUpBeak, [STRINGID_METEORBEAMCHARGING - BATTLESTRINGS_TABLE_START] = sText_MeteorBeamCharging, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1d6ab5fae..3826a4751 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -350,6 +350,7 @@ static bool32 CriticalCapture(u32 odds); static void BestowItem(u32 battlerAtk, u32 battlerDef); static bool8 IsFinalStrikeEffect(u16 move); static void TryUpdateRoundTurnOrder(void); +static bool32 ChangeOrderTargetAfterAttacker(void); static void Cmd_attackcanceler(void); static void Cmd_accuracycheck(void); @@ -5732,6 +5733,22 @@ static void Cmd_moveend(void) else gBattleStruct->lastMoveFailed &= ~(gBitTable[gBattlerAttacker]); + // Set ShellTrap to activate after the attacker's turn if target was hit by a physical move. + if (gBattleMoves[gChosenMoveByBattler[gBattlerTarget]].effect == EFFECT_SHELL_TRAP + && gBattlerTarget != gBattlerAttacker + && GetBattlerSide(gBattlerTarget) != GetBattlerSide(gBattlerAttacker) + && gProtectStructs[gBattlerTarget].physicalDmg + && gProtectStructs[gBattlerTarget].physicalBattlerId == gBattlerAttacker + && !TestSheerForceFlag(gBattlerAttacker, gCurrentMove)) + { + gProtectStructs[gBattlerTarget].shellTrap = TRUE; + // Change move order in double battles, so the hit mon with shell trap moves immediately after being hit. + if (IsDoubleBattle()) + { + ChangeOrderTargetAfterAttacker(); + } + } + if (gHitMarker & HITMARKER_SWAP_ATTACKER_TARGET) { gActiveBattler = gBattlerAttacker; @@ -6196,6 +6213,7 @@ static void Cmd_moveend(void) gBattleStruct->targetsDone[gBattlerAttacker] = 0; gProtectStructs[gBattlerAttacker].usesBouncedMove = FALSE; gProtectStructs[gBattlerAttacker].targetAffected = FALSE; + gProtectStructs[gBattlerAttacker].shellTrap = FALSE; gBattleStruct->ateBoost[gBattlerAttacker] = 0; gStatuses3[gBattlerAttacker] &= ~STATUS3_ME_FIRST; gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE; @@ -8643,6 +8661,38 @@ static bool32 CanTeleport(u8 battlerId) return TRUE; } +// Return True if the order was changed, and false if the order was not changed(for example because the target would move after the attacker anyway). +static bool32 ChangeOrderTargetAfterAttacker(void) +{ + u32 i; + u8 data[MAX_BATTLERS_COUNT]; + + if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget) + || GetBattlerTurnOrderNum(gBattlerAttacker) + 1 == GetBattlerTurnOrderNum(gBattlerTarget)) + return FALSE; + + for (i = 0; i < gBattlersCount; i++) + data[i] = gBattlerByTurnOrder[i]; + if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 2) + { + gBattlerByTurnOrder[1] = gBattlerTarget; + gBattlerByTurnOrder[2] = data[1]; + gBattlerByTurnOrder[3] = data[3]; + } + else if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 3) + { + gBattlerByTurnOrder[1] = gBattlerTarget; + gBattlerByTurnOrder[2] = data[1]; + gBattlerByTurnOrder[3] = data[2]; + } + else // Attacker == 1, Target == 3 + { + gBattlerByTurnOrder[2] = gBattlerTarget; + gBattlerByTurnOrder[3] = data[2]; + } + return TRUE; +} + static void Cmd_various(void) { CMD_ARGS(u8 battler, u8 id); @@ -10010,34 +10060,14 @@ static void Cmd_various(void) case VARIOUS_AFTER_YOU: { VARIOUS_ARGS(const u8 *failInstr); - if (GetBattlerTurnOrderNum(gBattlerAttacker) > GetBattlerTurnOrderNum(gBattlerTarget) - || GetBattlerTurnOrderNum(gBattlerAttacker) + 1 == GetBattlerTurnOrderNum(gBattlerTarget)) + if (ChangeOrderTargetAfterAttacker()) { - gBattlescriptCurrInstr = cmd->failInstr; + gSpecialStatuses[gBattlerTarget].afterYou = 1; + gBattlescriptCurrInstr = cmd->nextInstr; } else { - for (i = 0; i < gBattlersCount; i++) - data[i] = gBattlerByTurnOrder[i]; - if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 2) - { - gBattlerByTurnOrder[1] = gBattlerTarget; - gBattlerByTurnOrder[2] = data[1]; - gBattlerByTurnOrder[3] = data[3]; - } - else if (GetBattlerTurnOrderNum(gBattlerAttacker) == 0 && GetBattlerTurnOrderNum(gBattlerTarget) == 3) - { - gBattlerByTurnOrder[1] = gBattlerTarget; - gBattlerByTurnOrder[2] = data[1]; - gBattlerByTurnOrder[3] = data[2]; - } - else - { - gBattlerByTurnOrder[2] = gBattlerTarget; - gBattlerByTurnOrder[3] = data[2]; - } - gSpecialStatuses[gBattlerTarget].afterYou = 1; - gBattlescriptCurrInstr = cmd->nextInstr; + gBattlescriptCurrInstr = cmd->failInstr; } return; } @@ -11068,6 +11098,15 @@ static void Cmd_various(void) AbilityBattleEffects(ABILITYEFFECT_ON_WEATHER, gActiveBattler, 0, 0, 0); return; } + case VARIOUS_JUMP_IF_SHELL_TRAP: + { + VARIOUS_ARGS(const u8 *jumpInstr); + if (gProtectStructs[gActiveBattler].shellTrap) + gBattlescriptCurrInstr = cmd->jumpInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; + return; + } case VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES: { VARIOUS_ARGS(); diff --git a/src/battle_util.c b/src/battle_util.c index 185575411..ccc7445b5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -948,7 +948,8 @@ void HandleAction_ActionFinished(void) u8 battler1 = gBattlerByTurnOrder[i]; u8 battler2 = gBattlerByTurnOrder[j]; - if (gProtectStructs[battler1].quash || gProtectStructs[battler2].quash) + if (gProtectStructs[battler1].quash || gProtectStructs[battler2].quash + || gProtectStructs[battler1].shellTrap || gProtectStructs[battler2].shellTrap) continue; // We recalculate order only for action of the same priority. If any action other than switch/move has been taken, they should diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index bf5414276..82883fb8c 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -11613,7 +11613,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_SHELL_TRAP] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_SHELL_TRAP, + .effect = EFFECT_SHELL_TRAP, .power = 150, .type = TYPE_FIRE, .accuracy = 100, diff --git a/test/move_effect_shell_trap.c b/test/move_effect_shell_trap.c new file mode 100644 index 000000000..27dc4b7f6 --- /dev/null +++ b/test/move_effect_shell_trap.c @@ -0,0 +1,168 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_SHELL_TRAP].effect == EFFECT_SHELL_TRAP); + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + ASSUME(gBattleMoves[MOVE_WATER_GUN].split == SPLIT_SPECIAL); + ASSUME(gBattleMoves[MOVE_LEER].split == SPLIT_STATUS); +} + +SINGLE_BATTLE_TEST("Shell Trap activates only if hit by a physical move") +{ + u32 move; + bool32 activate; + PARAMETRIZE { move = MOVE_TACKLE; activate = TRUE; } + PARAMETRIZE { move = MOVE_WATER_GUN; activate = FALSE; } + PARAMETRIZE { move = MOVE_LEER; activate = FALSE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SHELL_TRAP); MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, player); + MESSAGE("Wobbuffet set a shell trap!"); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + + if (activate) { + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + HP_BAR(opponent); + } else { + MESSAGE("Wobbuffet's shell trap didn't work!"); + NONE_OF { + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + HP_BAR(opponent); + } + } + } +} + +SINGLE_BATTLE_TEST("Shell Trap does not activate if attacker's Sheer Force applied") +{ + u32 move; + bool32 activate; + PARAMETRIZE { move = MOVE_TACKLE; activate = TRUE; } + PARAMETRIZE { move = MOVE_STOMP; activate = FALSE; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_TAUROS) { Ability(ABILITY_SHEER_FORCE); } + } WHEN { + TURN { MOVE(player, MOVE_SHELL_TRAP); MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, player); + MESSAGE("Wobbuffet set a shell trap!"); + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + if (activate) { + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + HP_BAR(opponent); + } else { + MESSAGE("Wobbuffet's shell trap didn't work!"); + NONE_OF { + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + HP_BAR(opponent); + } + } + } +} + +SINGLE_BATTLE_TEST("Shell Trap does not activate if battler faints before being able to activate it") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SHELL_TRAP); MOVE(opponent, MOVE_TACKLE); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, player); + MESSAGE("Wobbuffet set a shell trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + MESSAGE("Wobbuffet fainted!"); + MESSAGE("Go! Wobbuffet!"); + NONE_OF { + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, player); + HP_BAR(opponent); + } + } +} + +DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 1 and attacks both opponents") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SHELL_TRAP].target == MOVE_TARGET_BOTH); + PLAYER(SPECIES_WOBBUFFET) { Speed(1); } + PLAYER(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WYNAUT) { Speed(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SHELL_TRAP); MOVE(opponentLeft, MOVE_TACKLE, target:playerLeft); MOVE(playerRight, MOVE_CELEBRATE); MOVE(opponentRight, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, playerLeft); + MESSAGE("Wobbuffet set a shell trap!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft); + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, playerLeft); + HP_BAR(opponentLeft); + HP_BAR(opponentRight); + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wynaut used Celebrate!"); + } +} + +DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 2 and attacks both opponents") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SHELL_TRAP].target == MOVE_TARGET_BOTH); + PLAYER(SPECIES_WOBBUFFET) { Speed(1); } + PLAYER(SPECIES_WOBBUFFET) { Speed(2); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WYNAUT) { Speed(6); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SHELL_TRAP); MOVE(opponentLeft, MOVE_TACKLE, target:playerLeft); MOVE(playerRight, MOVE_CELEBRATE); MOVE(opponentRight, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, playerLeft); + MESSAGE("Wobbuffet set a shell trap!"); + MESSAGE("Foe Wynaut used Celebrate!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft); + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, playerLeft); + HP_BAR(opponentLeft); + HP_BAR(opponentRight); + MESSAGE("Wobbuffet used Celebrate!"); + } +} + +DOUBLE_BATTLE_TEST("Shell Trap activates immediately after being hit on turn 3 and attacks both opponents") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SHELL_TRAP].target == MOVE_TARGET_BOTH); + PLAYER(SPECIES_WOBBUFFET) { Speed(1); } + PLAYER(SPECIES_WOBBUFFET) { Speed(7); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(5); } + OPPONENT(SPECIES_WYNAUT) { Speed(6); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_SHELL_TRAP); MOVE(opponentLeft, MOVE_TACKLE, target:playerLeft); MOVE(playerRight, MOVE_CELEBRATE); MOVE(opponentRight, MOVE_CELEBRATE); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_SHELL_TRAP_SETUP, playerLeft); + MESSAGE("Wobbuffet set a shell trap!"); + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Foe Wynaut used Celebrate!"); + MESSAGE("Foe Wobbuffet used Tackle!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponentLeft); + MESSAGE("Wobbuffet used Shell Trap!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHELL_TRAP, playerLeft); + HP_BAR(opponentLeft); + HP_BAR(opponentRight); + } +}