From c5c0e91215e05dcc8d517f9780f4d54afa1a7d52 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 2 Feb 2023 21:39:01 -0500 Subject: [PATCH 01/34] fix BattleScript_TargetAbilityStatRaiseRet overwriting gBattlerAttacker --- data/battle_scripts_1.s | 2 ++ 1 file changed, 2 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 9ff5838b1..e526f6e96 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -10200,6 +10200,7 @@ BattleScript_SymbiosisActivates:: return BattleScript_TargetAbilityStatRaiseRet:: + copybyte sSAVED_BATTLER, gBattlerAttacker copybyte gBattlerAbility, gEffectBattler copybyte gBattlerAttacker, gBattlerTarget call BattleScript_AbilityPopUp @@ -10207,6 +10208,7 @@ BattleScript_TargetAbilityStatRaiseRet:: setgraphicalstatchangevalues call BattleScript_StatUp BattleScript_TargetAbilityStatRaiseRet_End: + copybyte gBattlerAttacker, sSAVED_BATTLER return BattleScript_PokemonCantUseTheMove:: From f060d0185f2da05378f51c577baadbf3fb131cef Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 2 Feb 2023 21:59:40 -0500 Subject: [PATCH 02/34] fix wind power, electromorphosis stomping on gbattlerattacker --- data/battle_scripts_1.s | 33 +++------------------------------ src/battle_script_commands.c | 9 +++++---- 2 files changed, 8 insertions(+), 34 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e526f6e96..0dada5566 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2951,12 +2951,9 @@ BattleScript_TryTailwindAbilitiesLoop_WindRider: BattleScript_TryTailwindAbilitiesLoop_WindPower: call BattleScript_AbilityPopUp - copybyte sSAVED_BATTLER, gBattlerAttacker - copybyte gBattlerAttacker, gBattlerTarget - setcharge + setcharge BS_TARGET printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER waitmessage B_WAIT_TIME_LONG - copybyte gBattlerAttacker, sSAVED_BATTLER goto BattleScript_TryTailwindAbilitiesLoop_Increment BattleScript_EffectMircleEye: @@ -5675,7 +5672,7 @@ BattleScript_EffectCharge:: attackcanceler attackstring ppreduce - setcharge + setcharge BS_ATTACKER attackanimation waitanimation .if B_CHARGE_SPDEF_RAISE >= GEN_5 @@ -6738,27 +6735,6 @@ BattleScript_TailwindEnds:: waitmessage B_WAIT_TIME_LONG end2 -BattleScript_WindPowerActivatesEnd2:: - setbyte gBattlerAttacker, 0 -BattleScript_WindPowerLoop: - printstring STRINGID_EMPTYSTRING3 - jumpifability BS_ATTACKER, ABILITY_WIND_POWER, BattleScript_WindPowerLoop_Cont - goto BattleScript_WindPowerIncrement -BattleScript_WindPowerLoop_Cont: - jumpifstatus3 BS_ATTACKER, STATUS3_CHARGED_UP, BattleScript_WindPowerIncrement - goto BattleScript_WindPower_Activate -BattleScript_WindPower_Activate: - call BattleScript_AbilityPopUp - setcharge - printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER - waitmessage B_WAIT_TIME_LONG -BattleScript_WindPowerIncrement: - addbyte gBattlerAttacker, 1 - jumpifbytenotequal gBattlerAttacker, gBattlersCount, BattleScript_WindPowerLoop -BattleScript_WindPowerEnd: - destroyabilitypopup - end2 - BattleScript_TrickRoomEnds:: printstring STRINGID_TRICKROOMENDS waitmessage B_WAIT_TIME_LONG @@ -7233,11 +7209,8 @@ BattleScript_AngerShellRet: return BattleScript_WindPowerActivates:: -.if B_CHECK_IF_CHARGED_UP == TRUE - jumpifstatus3 BS_ATTACKER, STATUS3_CHARGED_UP, BattleScript_WindPowerActivates_Ret -.endif call BattleScript_AbilityPopUp - setcharge + setcharge BS_TARGET printstring STRINGID_BEINGHITCHARGEDPKMNWITHPOWER waitmessage B_WAIT_TIME_LONG BattleScript_WindPowerActivates_Ret: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ccec3f6a6..87cb185b4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -13198,10 +13198,11 @@ static void Cmd_setforcedtarget(void) static void Cmd_setcharge(void) { - gStatuses3[gBattlerAttacker] |= STATUS3_CHARGED_UP; - gDisableStructs[gBattlerAttacker].chargeTimer = 2; - gDisableStructs[gBattlerAttacker].chargeTimerStartValue = 2; - gBattlescriptCurrInstr++; + u8 battler = GetBattlerForBattleScript(gBattlescriptCurrInstr[1]); + gStatuses3[battler] |= STATUS3_CHARGED_UP; + gDisableStructs[battler].chargeTimer = 2; + gDisableStructs[battler].chargeTimerStartValue = 2; + gBattlescriptCurrInstr += 2; } // Nature Power From 843096d32ac6073c733763b96649872f45727c06 Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Thu, 2 Feb 2023 22:46:24 -0500 Subject: [PATCH 03/34] update setcharge macro --- asm/macros/battle_script.inc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 4d0b9a614..591702850 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1053,8 +1053,9 @@ .byte 0xca .endm - .macro setcharge + .macro setcharge battler:req .byte 0xcb + .byte \battler .endm .macro callterrainattack From 39b8c8e9e7ec4b6a6489f9c5d328d6579f80ef8e Mon Sep 17 00:00:00 2001 From: ghoulslash Date: Mon, 13 Feb 2023 08:39:04 -0500 Subject: [PATCH 04/34] fix sText_BeingHitChargedPkmnWithPower battler --- src/battle_message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_message.c b/src/battle_message.c index 7ec079e72..ad830de28 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -768,7 +768,7 @@ static const u8 sText_AttackerMeltedTheIce[] = _("{B_ATK_NAME_WITH_PREFIX} melte static const u8 sText_TargetToughedItOut[] = _("{B_DEF_NAME_WITH_PREFIX} toughed it out\nto show you its best side!"); static const u8 sText_AttackerLostElectricType[] = _("{B_ATK_NAME_WITH_PREFIX} used up all\nof its electricity!"); static const u8 sText_AttackerSwitchedStatWithTarget[] = _("{B_ATK_NAME_WITH_PREFIX} switched {B_BUFF1}\nwith its target!"); -static const u8 sText_BeingHitChargedPkmnWithPower[] = _("Being hit by {B_CURRENT_MOVE}\ncharged {B_ATK_NAME_WITH_PREFIX} with power!"); +static const u8 sText_BeingHitChargedPkmnWithPower[] = _("Being hit by {B_CURRENT_MOVE}\ncharged {B_DEF_NAME_WITH_PREFIX} with power!"); static const u8 sText_SunlightActivatedAbility[] = _("The harsh sunlight activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!"); static const u8 sText_StatWasHeightened[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_BUFF1} was heightened!"); static const u8 sText_ElectricTerrainActivatedAbility[] = _("The Electric Terrain activated\n{B_SCR_ACTIVE_NAME_WITH_PREFIX}'s {B_LAST_ABILITY}!"); From 010ce6bc634ed9cd0dd2133fbc1dc4f25af3fe90 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 6 Jul 2023 11:56:04 -0400 Subject: [PATCH 05/34] Revert "Install libpng using pacman instead of manual build for msys2" This reverts commit dc2e210ade38bc5789764d0c3836c3d995a1d4ef. --- INSTALL.md | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 01fbd5cee..9aca02a15 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -125,12 +125,12 @@ Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or conti Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert. -1. Open msys2 at C:\devkitPro\msys2\mingw64.exe or run `C:\devkitPro\msys2\msys2_shell.bat -mingw64`. +1. Open msys2 at C:\devkitPro\msys2\msys2_shell.bat. 2. Certain packages are required to build pokeemerald. Install these by running the following command: ```bash - pacman -S make zlib-devel git mingw-w64-x86_64-gcc mingw-w64-x86_64-libpng + pacman -S make gcc zlib-devel git ```
Note... @@ -138,6 +138,39 @@ Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert. > This command will ask for confirmation, just enter the yes action when prompted.
+3. Download [libpng](https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz/download). + +4. Change directory to where libpng was downloaded. By default, msys2 will start in the current user's profile folder, located at **C:\Users\\⁠_\_**, where *\* is your Windows username. In most cases, libpng should be saved within a subfolder of the profile folder. For example, if libpng was saved to **C:\Users\\_\_\Downloads** (the Downloads location for most users), enter this command: + + ```bash + cd Downloads + ``` + +
+ Notes... + + > Note 1: While not shown, msys uses forward slashes `/` instead of backwards slashes `\` as the directory separator. + > Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Downloads/My Downloads"`. + > Note 3: Windows path names are case-insensitive so adhering to capitalization isn’t needed. + > Note 4: If libpng was saved elsewhere, you will need to specify the full path to where libpng was downloaded, e.g. `cd c:/devkitpro/msys2` if it was saved there. +
+ +5. Run the following commands to uncompress and install libpng. + + ```bash + tar xf libpng-1.6.37.tar.xz + cd libpng-1.6.37 + ./configure --prefix=/usr + make check + make install + ``` + +6. Then finally, run the following command to change back to the user profile folder. + + ```bash + cd + ``` + ### Choosing where to store pokeemerald (msys2) At this point, you can choose a folder to store pokeemerald into. If you're okay with storing pokeemerald in the user profile folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald is stored when changing directory to the pokeemerald folder. From f4111d8082cce24b94969d5b49e977a165abbcb4 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sun, 9 Jul 2023 14:57:51 -0400 Subject: [PATCH 06/34] Sync castform folder organization --- .../anim_front.png} | Bin .../{back_normal_form.png => normal/back.png} | Bin .../front.png} | Bin .../normal.pal} | 0 .../shiny.pal} | 0 .../anim_front.png} | Bin .../{back_rainy_form.png => rainy/back.png} | Bin .../{front_rainy_form.png => rainy/front.png} | Bin .../normal.pal} | 0 .../{shiny_rainy_form.pal => rainy/shiny.pal} | 0 .../anim_front.png} | Bin .../{back_snowy_form.png => snowy/back.png} | Bin .../{front_snowy_form.png => snowy/front.png} | Bin .../normal.pal} | 0 .../{shiny_snowy_form.pal => snowy/shiny.pal} | 0 .../anim_front.png} | Bin .../{back_sunny_form.png => sunny/back.png} | Bin .../{front_sunny_form.png => sunny/front.png} | Bin .../normal.pal} | 0 .../{shiny_sunny_form.pal => sunny/shiny.pal} | 0 graphics_file_rules.mk | 40 +++++++++--------- 21 files changed, 20 insertions(+), 20 deletions(-) rename graphics/pokemon/castform/{anim_front_normal_form.png => normal/anim_front.png} (100%) rename graphics/pokemon/castform/{back_normal_form.png => normal/back.png} (100%) rename graphics/pokemon/castform/{front_normal_form.png => normal/front.png} (100%) rename graphics/pokemon/castform/{normal_normal_form.pal => normal/normal.pal} (100%) rename graphics/pokemon/castform/{shiny_normal_form.pal => normal/shiny.pal} (100%) rename graphics/pokemon/castform/{anim_front_rainy_form.png => rainy/anim_front.png} (100%) rename graphics/pokemon/castform/{back_rainy_form.png => rainy/back.png} (100%) rename graphics/pokemon/castform/{front_rainy_form.png => rainy/front.png} (100%) rename graphics/pokemon/castform/{normal_rainy_form.pal => rainy/normal.pal} (100%) rename graphics/pokemon/castform/{shiny_rainy_form.pal => rainy/shiny.pal} (100%) rename graphics/pokemon/castform/{anim_front_snowy_form.png => snowy/anim_front.png} (100%) rename graphics/pokemon/castform/{back_snowy_form.png => snowy/back.png} (100%) rename graphics/pokemon/castform/{front_snowy_form.png => snowy/front.png} (100%) rename graphics/pokemon/castform/{normal_snowy_form.pal => snowy/normal.pal} (100%) rename graphics/pokemon/castform/{shiny_snowy_form.pal => snowy/shiny.pal} (100%) rename graphics/pokemon/castform/{anim_front_sunny_form.png => sunny/anim_front.png} (100%) rename graphics/pokemon/castform/{back_sunny_form.png => sunny/back.png} (100%) rename graphics/pokemon/castform/{front_sunny_form.png => sunny/front.png} (100%) rename graphics/pokemon/castform/{normal_sunny_form.pal => sunny/normal.pal} (100%) rename graphics/pokemon/castform/{shiny_sunny_form.pal => sunny/shiny.pal} (100%) diff --git a/graphics/pokemon/castform/anim_front_normal_form.png b/graphics/pokemon/castform/normal/anim_front.png similarity index 100% rename from graphics/pokemon/castform/anim_front_normal_form.png rename to graphics/pokemon/castform/normal/anim_front.png diff --git a/graphics/pokemon/castform/back_normal_form.png b/graphics/pokemon/castform/normal/back.png similarity index 100% rename from graphics/pokemon/castform/back_normal_form.png rename to graphics/pokemon/castform/normal/back.png diff --git a/graphics/pokemon/castform/front_normal_form.png b/graphics/pokemon/castform/normal/front.png similarity index 100% rename from graphics/pokemon/castform/front_normal_form.png rename to graphics/pokemon/castform/normal/front.png diff --git a/graphics/pokemon/castform/normal_normal_form.pal b/graphics/pokemon/castform/normal/normal.pal similarity index 100% rename from graphics/pokemon/castform/normal_normal_form.pal rename to graphics/pokemon/castform/normal/normal.pal diff --git a/graphics/pokemon/castform/shiny_normal_form.pal b/graphics/pokemon/castform/normal/shiny.pal similarity index 100% rename from graphics/pokemon/castform/shiny_normal_form.pal rename to graphics/pokemon/castform/normal/shiny.pal diff --git a/graphics/pokemon/castform/anim_front_rainy_form.png b/graphics/pokemon/castform/rainy/anim_front.png similarity index 100% rename from graphics/pokemon/castform/anim_front_rainy_form.png rename to graphics/pokemon/castform/rainy/anim_front.png diff --git a/graphics/pokemon/castform/back_rainy_form.png b/graphics/pokemon/castform/rainy/back.png similarity index 100% rename from graphics/pokemon/castform/back_rainy_form.png rename to graphics/pokemon/castform/rainy/back.png diff --git a/graphics/pokemon/castform/front_rainy_form.png b/graphics/pokemon/castform/rainy/front.png similarity index 100% rename from graphics/pokemon/castform/front_rainy_form.png rename to graphics/pokemon/castform/rainy/front.png diff --git a/graphics/pokemon/castform/normal_rainy_form.pal b/graphics/pokemon/castform/rainy/normal.pal similarity index 100% rename from graphics/pokemon/castform/normal_rainy_form.pal rename to graphics/pokemon/castform/rainy/normal.pal diff --git a/graphics/pokemon/castform/shiny_rainy_form.pal b/graphics/pokemon/castform/rainy/shiny.pal similarity index 100% rename from graphics/pokemon/castform/shiny_rainy_form.pal rename to graphics/pokemon/castform/rainy/shiny.pal diff --git a/graphics/pokemon/castform/anim_front_snowy_form.png b/graphics/pokemon/castform/snowy/anim_front.png similarity index 100% rename from graphics/pokemon/castform/anim_front_snowy_form.png rename to graphics/pokemon/castform/snowy/anim_front.png diff --git a/graphics/pokemon/castform/back_snowy_form.png b/graphics/pokemon/castform/snowy/back.png similarity index 100% rename from graphics/pokemon/castform/back_snowy_form.png rename to graphics/pokemon/castform/snowy/back.png diff --git a/graphics/pokemon/castform/front_snowy_form.png b/graphics/pokemon/castform/snowy/front.png similarity index 100% rename from graphics/pokemon/castform/front_snowy_form.png rename to graphics/pokemon/castform/snowy/front.png diff --git a/graphics/pokemon/castform/normal_snowy_form.pal b/graphics/pokemon/castform/snowy/normal.pal similarity index 100% rename from graphics/pokemon/castform/normal_snowy_form.pal rename to graphics/pokemon/castform/snowy/normal.pal diff --git a/graphics/pokemon/castform/shiny_snowy_form.pal b/graphics/pokemon/castform/snowy/shiny.pal similarity index 100% rename from graphics/pokemon/castform/shiny_snowy_form.pal rename to graphics/pokemon/castform/snowy/shiny.pal diff --git a/graphics/pokemon/castform/anim_front_sunny_form.png b/graphics/pokemon/castform/sunny/anim_front.png similarity index 100% rename from graphics/pokemon/castform/anim_front_sunny_form.png rename to graphics/pokemon/castform/sunny/anim_front.png diff --git a/graphics/pokemon/castform/back_sunny_form.png b/graphics/pokemon/castform/sunny/back.png similarity index 100% rename from graphics/pokemon/castform/back_sunny_form.png rename to graphics/pokemon/castform/sunny/back.png diff --git a/graphics/pokemon/castform/front_sunny_form.png b/graphics/pokemon/castform/sunny/front.png similarity index 100% rename from graphics/pokemon/castform/front_sunny_form.png rename to graphics/pokemon/castform/sunny/front.png diff --git a/graphics/pokemon/castform/normal_sunny_form.pal b/graphics/pokemon/castform/sunny/normal.pal similarity index 100% rename from graphics/pokemon/castform/normal_sunny_form.pal rename to graphics/pokemon/castform/sunny/normal.pal diff --git a/graphics/pokemon/castform/shiny_sunny_form.pal b/graphics/pokemon/castform/sunny/shiny.pal similarity index 100% rename from graphics/pokemon/castform/shiny_sunny_form.pal rename to graphics/pokemon/castform/sunny/shiny.pal diff --git a/graphics_file_rules.mk b/graphics_file_rules.mk index 97a7794b3..090620ebe 100644 --- a/graphics_file_rules.mk +++ b/graphics_file_rules.mk @@ -30,34 +30,34 @@ contest_types := cool beauty cute smart tough ### Castform ### -$(CASTFORMGFXDIR)/front.4bpp: $(CASTFORMGFXDIR)/front_normal_form.4bpp \ - $(CASTFORMGFXDIR)/front_sunny_form.4bpp \ - $(CASTFORMGFXDIR)/front_rainy_form.4bpp \ - $(CASTFORMGFXDIR)/front_snowy_form.4bpp +$(CASTFORMGFXDIR)/front.4bpp: $(CASTFORMGFXDIR)/normal/front.4bpp \ + $(CASTFORMGFXDIR)/sunny/front.4bpp \ + $(CASTFORMGFXDIR)/rainy/front.4bpp \ + $(CASTFORMGFXDIR)/snowy/front.4bpp @cat $^ >$@ -$(CASTFORMGFXDIR)/back.4bpp: $(CASTFORMGFXDIR)/back_normal_form.4bpp \ - $(CASTFORMGFXDIR)/back_sunny_form.4bpp \ - $(CASTFORMGFXDIR)/back_rainy_form.4bpp \ - $(CASTFORMGFXDIR)/back_snowy_form.4bpp +$(CASTFORMGFXDIR)/back.4bpp: $(CASTFORMGFXDIR)/normal/back.4bpp \ + $(CASTFORMGFXDIR)/sunny/back.4bpp \ + $(CASTFORMGFXDIR)/rainy/back.4bpp \ + $(CASTFORMGFXDIR)/snowy/back.4bpp @cat $^ >$@ -$(CASTFORMGFXDIR)/anim_front.4bpp: $(CASTFORMGFXDIR)/anim_front_normal_form.4bpp \ - $(CASTFORMGFXDIR)/anim_front_sunny_form.4bpp \ - $(CASTFORMGFXDIR)/anim_front_rainy_form.4bpp \ - $(CASTFORMGFXDIR)/anim_front_snowy_form.4bpp +$(CASTFORMGFXDIR)/anim_front.4bpp: $(CASTFORMGFXDIR)/normal/anim_front.4bpp \ + $(CASTFORMGFXDIR)/sunny/anim_front.4bpp \ + $(CASTFORMGFXDIR)/rainy/anim_front.4bpp \ + $(CASTFORMGFXDIR)/snowy/anim_front.4bpp @cat $^ >$@ -$(CASTFORMGFXDIR)/normal.gbapal: $(CASTFORMGFXDIR)/normal_normal_form.gbapal \ - $(CASTFORMGFXDIR)/normal_sunny_form.gbapal \ - $(CASTFORMGFXDIR)/normal_rainy_form.gbapal \ - $(CASTFORMGFXDIR)/normal_snowy_form.gbapal +$(CASTFORMGFXDIR)/normal.gbapal: $(CASTFORMGFXDIR)/normal/normal.gbapal \ + $(CASTFORMGFXDIR)/sunny/normal.gbapal \ + $(CASTFORMGFXDIR)/rainy/normal.gbapal \ + $(CASTFORMGFXDIR)/snowy/normal.gbapal @cat $^ >$@ -$(CASTFORMGFXDIR)/shiny.gbapal: $(CASTFORMGFXDIR)/shiny_normal_form.gbapal \ - $(CASTFORMGFXDIR)/shiny_sunny_form.gbapal \ - $(CASTFORMGFXDIR)/shiny_rainy_form.gbapal \ - $(CASTFORMGFXDIR)/shiny_snowy_form.gbapal +$(CASTFORMGFXDIR)/shiny.gbapal: $(CASTFORMGFXDIR)/normal/shiny.gbapal \ + $(CASTFORMGFXDIR)/sunny/shiny.gbapal \ + $(CASTFORMGFXDIR)/rainy/shiny.gbapal \ + $(CASTFORMGFXDIR)/snowy/shiny.gbapal @cat $^ >$@ From 5fd881a1b68b62679452591a6299fad0668db2e9 Mon Sep 17 00:00:00 2001 From: gruxor Date: Wed, 12 Jul 2023 14:44:23 -0400 Subject: [PATCH 07/34] Remove unused macro to fix syntax highlights --- include/global.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/global.h b/include/global.h index 184abdbe4..0ca226c03 100644 --- a/include/global.h +++ b/include/global.h @@ -20,7 +20,6 @@ #define BLOCK_CROSS_JUMP asm(""); // to help in decompiling -#define asm_comment(x) asm volatile("@ -- " x " -- ") #define asm_unified(x) asm(".syntax unified\n" x "\n.syntax divided") #define NAKED __attribute__((naked)) From 1b6f582600f334e9bb023e4b1bab274e10923516 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 17 Jul 2023 15:33:44 +0200 Subject: [PATCH 08/34] tests for stamina/wind power --- test/ability_stamina.c | 89 +++++++++++++++++++++++ test/ability_wind_power.c | 145 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 test/ability_stamina.c create mode 100644 test/ability_wind_power.c diff --git a/test/ability_stamina.c b/test/ability_stamina.c new file mode 100644 index 000000000..70cf3cdc0 --- /dev/null +++ b/test/ability_stamina.c @@ -0,0 +1,89 @@ +#include "global.h" +#include "test_battle.h" + +#define STAMINA_STAT_RAISE(target, msg) \ +{ \ + ABILITY_POPUP(target, ABILITY_STAMINA); \ + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, target); \ + MESSAGE(msg); \ +} + +#define STAMINA_HIT(attacker, target, move, msg, dmgVar) \ +{ \ + ANIMATION(ANIM_TYPE_MOVE, move, attacker); \ + HP_BAR(target, captureDamage: &dmgVar); \ + STAMINA_STAT_RAISE(target, msg); \ +} + +SINGLE_BATTLE_TEST("Stamina raises Defense by 1 when hit by a move") +{ + s16 turnOneHit, turnTwoHit; + u16 move; + + PARAMETRIZE {move = MOVE_TACKLE; } + PARAMETRIZE {move = MOVE_GUST; } + + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].power != 0); + ASSUME(gBattleMoves[MOVE_GUST].power != 0); + ASSUME(gBattleMoves[MOVE_GUST].split == SPLIT_SPECIAL); + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_STAMINA); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, move); } + TURN { MOVE(opponent, move); } + } SCENE { + STAMINA_HIT(opponent, player, move, "Wobbuffet's Defense rose!", turnOneHit); + STAMINA_HIT(opponent, player, move, "Wobbuffet's Defense rose!", turnTwoHit); + } + THEN { + if (move == MOVE_TACKLE) { + EXPECT_MUL_EQ(turnTwoHit, Q_4_12(1.5), turnOneHit); + } + else { + EXPECT_EQ(turnTwoHit, turnOneHit); + } + } +} + +DOUBLE_BATTLE_TEST("Stamina activates correctly for every battler with the ability when hit by a multi target move") +{ + u16 abilityLeft, abilityRight; + + PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_STAMINA; } + PARAMETRIZE {abilityLeft = ABILITY_STAMINA, abilityRight = ABILITY_NONE; } + PARAMETRIZE {abilityLeft = ABILITY_STAMINA, abilityRight = ABILITY_STAMINA; } + + GIVEN { + ASSUME(gBattleMoves[MOVE_EARTHQUAKE].target == MOVE_TARGET_FOES_AND_ALLY); + PLAYER(SPECIES_WOBBUFFET) { Ability(abilityLeft); Speed(10); } + PLAYER(SPECIES_WOBBUFFET) { Ability(abilityRight); Speed(5); } + OPPONENT(SPECIES_WOBBUFFET) {Speed(20); } + OPPONENT(SPECIES_WOBBUFFET) {Speed(15); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_EARTHQUAKE);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponentLeft); + + HP_BAR(playerLeft); + if (abilityLeft == ABILITY_STAMINA) { + STAMINA_STAT_RAISE(playerLeft, "Wobbuffet's Defense rose!"); + } + NOT HP_BAR(opponentLeft); // We need to check the attacker itself does NOT get damaged. There was an issue when the targets would get overwritten by the Stamina's stat raise. + + HP_BAR(playerRight); + if (abilityRight == ABILITY_STAMINA) { + STAMINA_STAT_RAISE(playerRight, "Wobbuffet's Defense rose!"); + } + NOT HP_BAR(opponentLeft); // We need to check the attacker itself does NOT get damaged. There was an issue when the targets would get overwritten by the Stamina's stat raise. + + HP_BAR(opponentRight); + } + THEN { + EXPECT_NE(playerLeft->hp, playerLeft->maxHP); + EXPECT_NE(playerRight->hp, playerRight->maxHP); + EXPECT_NE(opponentRight->hp, opponentRight->maxHP); + EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP); + } +} diff --git a/test/ability_wind_power.c b/test/ability_wind_power.c new file mode 100644 index 000000000..83ec47103 --- /dev/null +++ b/test/ability_wind_power.c @@ -0,0 +1,145 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_THUNDERBOLT].power != 0); + ASSUME(gBattleMoves[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); + ASSUME(gBattleMoves[MOVE_TACKLE].power != 0); + ASSUME(gBattleMoves[MOVE_AIR_CUTTER].power != 0); + ASSUME(gBattleMoves[MOVE_AIR_CUTTER].target == MOVE_TARGET_BOTH); + ASSUME(gBattleMoves[MOVE_AIR_CUTTER].flags & FLAG_WIND_MOVE); + ASSUME(!(gBattleMoves[MOVE_TACKLE].flags & FLAG_WIND_MOVE)); +} + +SINGLE_BATTLE_TEST("Wind Power sets up Charge for player when hit by a wind move") +{ + s16 dmgBefore, dmgAfter; + u16 move; + + PARAMETRIZE {move = MOVE_TACKLE; } + PARAMETRIZE {move = MOVE_AIR_CUTTER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(10); } + OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed. + } WHEN { + TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); } + TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); + HP_BAR(opponent, captureDamage: &dmgBefore); + + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player); + if (move == MOVE_AIR_CUTTER) { + ABILITY_POPUP(player, ABILITY_WIND_POWER); + MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!"); + } + + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); + HP_BAR(opponent, captureDamage: &dmgAfter); + + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player); + if (move == MOVE_AIR_CUTTER) { + ABILITY_POPUP(player, ABILITY_WIND_POWER); + MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!"); + } + } + THEN { + if (move == MOVE_AIR_CUTTER) { + EXPECT_MUL_EQ(dmgBefore, Q_4_12(2.0), dmgAfter); + } + else { + EXPECT_EQ(dmgAfter, dmgBefore); + } + } +} + +SINGLE_BATTLE_TEST("Wind Power sets up Charge for opponent when hit by a wind move") +{ + s16 dmgBefore, dmgAfter; + u16 move; + + PARAMETRIZE {move = MOVE_TACKLE; } + PARAMETRIZE {move = MOVE_AIR_CUTTER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed. + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(10); } + } WHEN { + TURN { MOVE(opponent, MOVE_THUNDERBOLT), MOVE(player, move); } + TURN { MOVE(opponent, MOVE_THUNDERBOLT), MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, opponent); + HP_BAR(player, captureDamage: &dmgBefore); + + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + if (move == MOVE_AIR_CUTTER) { + ABILITY_POPUP(opponent, ABILITY_WIND_POWER); + MESSAGE("Being hit by Air Cutter charged Foe Wobbuffet with power!"); + } + + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, opponent); + HP_BAR(player, captureDamage: &dmgAfter); + + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + if (move == MOVE_AIR_CUTTER) { + ABILITY_POPUP(opponent, ABILITY_WIND_POWER); + MESSAGE("Being hit by Air Cutter charged Foe Wobbuffet with power!"); + } + } + THEN { + if (move == MOVE_AIR_CUTTER) { + EXPECT_MUL_EQ(dmgBefore, Q_4_12(2.0), dmgAfter); + } + else { + EXPECT_EQ(dmgAfter, dmgBefore); + } + } +} + +DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a multi target move") +{ + u16 abilityLeft, abilityRight; + + PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER; } + PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; } + PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_WIND_POWER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(abilityLeft); Speed(10); } + PLAYER(SPECIES_WOBBUFFET) { Ability(abilityRight); Speed(5); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(20); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(15); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_AIR_CUTTER);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AIR_CUTTER, opponentLeft); + + HP_BAR(playerLeft); + if (abilityLeft == ABILITY_WIND_POWER) { + ABILITY_POPUP(playerLeft, ABILITY_WIND_POWER); + MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!"); + } + NOT HP_BAR(opponentLeft); + NOT HP_BAR(opponentRight); + + HP_BAR(playerRight); + if (abilityRight == ABILITY_WIND_POWER) { + ABILITY_POPUP(playerRight, ABILITY_WIND_POWER); + MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!"); + } + NOT HP_BAR(opponentLeft); + NOT HP_BAR(opponentRight); + } + THEN { + EXPECT_NE(playerLeft->hp, playerLeft->maxHP); + EXPECT_NE(playerRight->hp, playerRight->maxHP); + EXPECT_EQ(opponentRight->hp, opponentRight->maxHP); + EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP); + } +} From 04feba83147c24fed0f533acab9b60baa054054f Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 17 Jul 2023 16:30:59 +0200 Subject: [PATCH 09/34] test for electromorphosis, small fix for wind power --- src/battle_util.c | 1 - test/ability_electromorphosis.c | 56 ++++++++++++++++++++ test/ability_wind_power.c | 90 ++++++++++++++++++++++++++++++--- 3 files changed, 139 insertions(+), 8 deletions(-) create mode 100644 test/ability_electromorphosis.c diff --git a/src/battle_util.c b/src/battle_util.c index 105b29cac..f1048664b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5691,7 +5691,6 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move && TARGET_TURN_DAMAGED && IsBattlerAlive(gBattlerTarget)) { - gBattlerAttacker = gBattlerTarget; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_WindPowerActivates; effect++; diff --git a/test/ability_electromorphosis.c b/test/ability_electromorphosis.c new file mode 100644 index 000000000..25d33aac0 --- /dev/null +++ b/test/ability_electromorphosis.c @@ -0,0 +1,56 @@ +#include "global.h" +#include "test_battle.h" + +SINGLE_BATTLE_TEST("Electromorphosis sets up Charge when hit by any move") +{ + s16 dmgBefore, dmgAfter; + u16 move; + + PARAMETRIZE {move = MOVE_TACKLE; } + PARAMETRIZE {move = MOVE_GUST; } + + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].power != 0); + ASSUME(gBattleMoves[MOVE_GUST].power != 0); + ASSUME(gBattleMoves[MOVE_GUST].split == SPLIT_SPECIAL); + ASSUME(gBattleMoves[MOVE_TACKLE].split == SPLIT_PHYSICAL); + ASSUME(gBattleMoves[MOVE_THUNDERBOLT].power != 0); + ASSUME(gBattleMoves[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); + + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_ELECTROMORPHOSIS); Speed(10); } + OPPONENT(SPECIES_WOBBUFFET) {Ability(ABILITY_LIMBER); Speed(5) ;} // Limber, so it doesn't get paralyzed. + } + WHEN { + TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); } + TURN { MOVE(player, MOVE_THUNDERBOLT), MOVE(opponent, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); + HP_BAR(opponent, captureDamage: &dmgBefore); + + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ELECTROMORPHOSIS); + if (move == MOVE_TACKLE) { + MESSAGE("Being hit by Tackle charged Wobbuffet with power!"); + } + else { + MESSAGE("Being hit by Gust charged Wobbuffet with power!"); + } + + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDERBOLT, player); + HP_BAR(opponent, captureDamage: &dmgAfter); + + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_ELECTROMORPHOSIS); + if (move == MOVE_TACKLE) { + MESSAGE("Being hit by Tackle charged Wobbuffet with power!"); + } + else { + MESSAGE("Being hit by Gust charged Wobbuffet with power!"); + } + } + THEN { + EXPECT_MUL_EQ(dmgBefore, Q_4_12(2.0), dmgAfter); + } +} diff --git a/test/ability_wind_power.c b/test/ability_wind_power.c index 83ec47103..8488db269 100644 --- a/test/ability_wind_power.c +++ b/test/ability_wind_power.c @@ -9,6 +9,9 @@ ASSUMPTIONS ASSUME(gBattleMoves[MOVE_AIR_CUTTER].power != 0); ASSUME(gBattleMoves[MOVE_AIR_CUTTER].target == MOVE_TARGET_BOTH); ASSUME(gBattleMoves[MOVE_AIR_CUTTER].flags & FLAG_WIND_MOVE); + ASSUME(gBattleMoves[MOVE_PETAL_BLIZZARD].power != 0); + ASSUME(gBattleMoves[MOVE_PETAL_BLIZZARD].target == MOVE_TARGET_FOES_AND_ALLY); + ASSUME(gBattleMoves[MOVE_PETAL_BLIZZARD].flags & FLAG_WIND_MOVE); ASSUME(!(gBattleMoves[MOVE_TACKLE].flags & FLAG_WIND_MOVE)); } @@ -102,11 +105,11 @@ SINGLE_BATTLE_TEST("Wind Power sets up Charge for opponent when hit by a wind mo } } -DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a multi target move") +DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a 2/3 target move") { - u16 abilityLeft, abilityRight; + u16 move, abilityLeft, abilityRight; - PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER; } + PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER;} PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; } PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_WIND_POWER; } @@ -116,7 +119,7 @@ DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ab OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(20); } OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(15); } } WHEN { - TURN { MOVE(opponentLeft, MOVE_AIR_CUTTER);} + TURN { MOVE(opponentLeft, MOVE_AIR_CUTTER); MOVE(opponentRight, MOVE_AIR_CUTTER);} } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_AIR_CUTTER, opponentLeft); @@ -125,9 +128,6 @@ DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ab ABILITY_POPUP(playerLeft, ABILITY_WIND_POWER); MESSAGE("Being hit by Air Cutter charged Wobbuffet with power!"); } - NOT HP_BAR(opponentLeft); - NOT HP_BAR(opponentRight); - HP_BAR(playerRight); if (abilityRight == ABILITY_WIND_POWER) { ABILITY_POPUP(playerRight, ABILITY_WIND_POWER); @@ -143,3 +143,79 @@ DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ab EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP); } } + +DOUBLE_BATTLE_TEST("Wind Power activates correctly for every battler with the ability when hit by a 3 target move") +{ + u16 abilityLeft, abilityRight; + + PARAMETRIZE {abilityLeft = ABILITY_NONE, abilityRight = ABILITY_WIND_POWER; } + PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_NONE; } + PARAMETRIZE {abilityLeft = ABILITY_WIND_POWER, abilityRight = ABILITY_WIND_POWER; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Ability(abilityLeft); Speed(10); } + PLAYER(SPECIES_WOBBUFFET) { Ability(abilityRight); Speed(5); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(20); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_LIMBER); Speed(15); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_PETAL_BLIZZARD);} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PETAL_BLIZZARD, opponentLeft); + + HP_BAR(playerLeft); + if (abilityLeft == ABILITY_WIND_POWER) { + ABILITY_POPUP(playerLeft, ABILITY_WIND_POWER); + MESSAGE("Being hit by PetalBlizzrd charged Wobbuffet with power!"); + } + HP_BAR(playerRight); + if (abilityRight == ABILITY_WIND_POWER) { + ABILITY_POPUP(playerRight, ABILITY_WIND_POWER); + MESSAGE("Being hit by PetalBlizzrd charged Wobbuffet with power!"); + } + HP_BAR(opponentRight); + NOT HP_BAR(opponentLeft); + } + THEN { + EXPECT_NE(playerLeft->hp, playerLeft->maxHP); + EXPECT_NE(playerRight->hp, playerRight->maxHP); + EXPECT_NE(opponentRight->hp, opponentRight->maxHP); + EXPECT_EQ(opponentLeft->hp, opponentLeft->maxHP); + } +} + +DOUBLE_BATTLE_TEST("Wind Power activates correctly when Tailwind is used") +{ + bool8 opponentSide; + + PARAMETRIZE {opponentSide = TRUE;} + PARAMETRIZE {opponentSide = FALSE;} + + GIVEN { + ASSUME(gBattleMoves[MOVE_TAILWIND].effect == EFFECT_TAILWIND); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(10); } + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(5); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(20); } + OPPONENT(SPECIES_WOBBUFFET) { Ability(ABILITY_WIND_POWER); Speed(15); } + } WHEN { + TURN { MOVE((opponentSide == TRUE) ? opponentLeft : playerLeft, MOVE_TAILWIND);} + } SCENE { + if (opponentSide) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, opponentLeft); + + ABILITY_POPUP(opponentLeft, ABILITY_WIND_POWER); + MESSAGE("Being hit by Tailwind charged Foe Wobbuffet with power!"); + + ABILITY_POPUP(opponentRight, ABILITY_WIND_POWER); + MESSAGE("Being hit by Tailwind charged Foe Wobbuffet with power!"); + } + else { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TAILWIND, playerLeft); + + ABILITY_POPUP(playerLeft, ABILITY_WIND_POWER); + MESSAGE("Being hit by Tailwind charged Wobbuffet with power!"); + + ABILITY_POPUP(playerRight, ABILITY_WIND_POWER); + MESSAGE("Being hit by Tailwind charged Wobbuffet with power!"); + } + } +} From 8ec0bff0342413ac4996b63382c8d03a3b532899 Mon Sep 17 00:00:00 2001 From: luckytyphlosion <10688458+luckytyphlosion@users.noreply.github.com> Date: Tue, 18 Jul 2023 19:28:41 -0400 Subject: [PATCH 10/34] Update msys2 instructions Add pacman -Sy msys2-keyring --- INSTALL.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/INSTALL.md b/INSTALL.md index 9aca02a15..a76d0acc7 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -127,15 +127,16 @@ Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert. 1. Open msys2 at C:\devkitPro\msys2\msys2_shell.bat. -2. Certain packages are required to build pokeemerald. Install these by running the following command: +2. Certain packages are required to build pokeemerald. Install these by running the following two commands: ```bash + pacman -Sy msys2-keyring pacman -S make gcc zlib-devel git ```
Note... - > This command will ask for confirmation, just enter the yes action when prompted. + > The commands will ask for confirmation, just enter the yes action when prompted.
3. Download [libpng](https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz/download). From 34beb3d662252ab309a094a224f4414e7771cabf Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 19 Jul 2023 10:59:36 +0200 Subject: [PATCH 11/34] add tests for rattled --- test/ability_rattled.c | 93 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 test/ability_rattled.c diff --git a/test/ability_rattled.c b/test/ability_rattled.c new file mode 100644 index 000000000..bddc88751 --- /dev/null +++ b/test/ability_rattled.c @@ -0,0 +1,93 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_FURY_CUTTER].type == TYPE_BUG); + ASSUME(gBattleMoves[MOVE_FURY_CUTTER].power != 0); + ASSUME(gBattleMoves[MOVE_FEINT_ATTACK].type == TYPE_DARK); + ASSUME(gBattleMoves[MOVE_FEINT_ATTACK].power != 0); + ASSUME(gBattleMoves[MOVE_SHADOW_PUNCH].type == TYPE_GHOST); + ASSUME(gBattleMoves[MOVE_SHADOW_PUNCH].power != 0); + ASSUME(gBattleMoves[MOVE_TACKLE].type == TYPE_NORMAL); + ASSUME(gBattleMoves[MOVE_TACKLE].power != 0); +} + +SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when hit by Bug, Dark or Ghost type move") +{ + u16 move; + PARAMETRIZE { move = MOVE_FURY_CUTTER; } + PARAMETRIZE { move = MOVE_FEINT_ATTACK; } + PARAMETRIZE { move = MOVE_SHADOW_PUNCH; } + PARAMETRIZE { move = MOVE_TACKLE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) {Speed(42) ;} + OPPONENT(SPECIES_SUDOWOODO) {Speed(40); Ability(ABILITY_RATTLED);} + } WHEN { + TURN { MOVE(player, move); } + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + if (move != MOVE_TACKLE) { + ABILITY_POPUP(opponent, ABILITY_RATTLED); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Sudowoodo's Speed rose!"); + } + MESSAGE("Foe Sudowoodo used Celebrate!"); + // Sudowoodo is now faster + if (move != MOVE_TACKLE){ + MESSAGE("Foe Sudowoodo used Celebrate!"); + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + ABILITY_POPUP(opponent, ABILITY_RATTLED); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Sudowoodo's Speed rose!"); + } + else { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent); + MESSAGE("Foe Sudowoodo used Celebrate!"); + } + } +} + +SINGLE_BATTLE_TEST("Rattled boosts speed by 1 when affected by Intimidate") +{ + GIVEN { + ASSUME(B_UPDATED_INTIMIDATE >= GEN_8); + PLAYER(SPECIES_GYARADOS) {Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); } + } WHEN { + TURN {} + } SCENE { + ABILITY_POPUP(player, ABILITY_INTIMIDATE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Gyarados's Intimidate cuts Foe Sudowoodo's attack!"); + ABILITY_POPUP(opponent, ABILITY_RATTLED); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Sudowoodo's Speed rose!"); + } +} + +SINGLE_BATTLE_TEST("Rattled triggers correctly when hit by U-Turn") // Specific test here, because of #3124 +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE); + ASSUME(gBattleMoves[MOVE_U_TURN].type == TYPE_BUG); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_SUDOWOODO) {Ability(ABILITY_RATTLED); } + OPPONENT(SPECIES_SUDOWOODO); + } WHEN { + TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, 1); } + } SCENE { + MESSAGE("Wobbuffet used U-Turn!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player); + HP_BAR(opponent); + ABILITY_POPUP(opponent, ABILITY_RATTLED); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Sudowoodo's Speed rose!"); + MESSAGE("Go! Wynaut!"); + } +} From 7fa6ed8b05d794b1e2656849d1631230cc8084fa Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Wed, 19 Jul 2023 17:33:28 +0200 Subject: [PATCH 12/34] Fix priortiy typos --- include/pokeball.h | 2 +- src/pokeball.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/pokeball.h b/include/pokeball.h index 1149791b8..2f003c407 100644 --- a/include/pokeball.h +++ b/include/pokeball.h @@ -34,7 +34,7 @@ extern const struct SpriteTemplate gBallSpriteTemplates[]; #define POKEBALL_OPPONENT_SENDOUT 0xFE u8 DoPokeballSendOutAnimation(s16 pan, u8 kindOfThrow); -void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 delay, u32 fadePalettes, u16 species); +void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriority, u8 delay, u32 fadePalettes, u16 species); u8 CreateTradePokeballSprite(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subPriority, u8 delay, u32 fadePalettes); void StartHealthboxSlideIn(u8 battler); void DoHitAnimHealthboxEffect(u8 battler); diff --git a/src/pokeball.c b/src/pokeball.c index 2633fd574..22d973381 100644 --- a/src/pokeball.c +++ b/src/pokeball.c @@ -1028,13 +1028,13 @@ static u8 LaunchBallFadeMonTaskForPokeball(bool8 unFadeLater, u8 spritePalNum, u #define sTrigIdx data[7] // Pokeball in Birch intro, and when receiving via trade -void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriortiy, u8 delay, u32 fadePalettes, u16 species) +void CreatePokeballSpriteToReleaseMon(u8 monSpriteId, u8 monPalNum, u8 x, u8 y, u8 oamPriority, u8 subpriority, u8 delay, u32 fadePalettes, u16 species) { u8 spriteId; LoadCompressedSpriteSheetUsingHeap(&gBallSpriteSheets[BALL_POKE]); LoadCompressedSpritePaletteUsingHeap(&gBallSpritePalettes[BALL_POKE]); - spriteId = CreateSprite(&gBallSpriteTemplates[BALL_POKE], x, y, subpriortiy); + spriteId = CreateSprite(&gBallSpriteTemplates[BALL_POKE], x, y, subpriority); gSprites[spriteId].sMonSpriteId = monSpriteId; gSprites[spriteId].sFinalMonX = gSprites[monSpriteId].x; From b53cca1a064d3a565900c9a096f9f6a7779b1dd5 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 24 Jul 2023 14:57:37 +0100 Subject: [PATCH 13/34] Declarations for 2- and 3-argument GetMonData (#1756) * Type-safe GetMonData/GetBoxMonData * Comments --- include/global.h | 7 +++++++ include/pokemon.h | 17 +++++++++++------ src/daycare.c | 2 +- src/pokemon.c | 16 ++++++++++++++-- 4 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/global.h b/include/global.h index 0ca226c03..00b08f48f 100644 --- a/include/global.h +++ b/include/global.h @@ -134,6 +134,13 @@ #define NUM_FLAG_BYTES ROUND_BITS_TO_BYTES(FLAGS_COUNT) #define NUM_TRENDY_SAYING_BYTES ROUND_BITS_TO_BYTES(NUM_TRENDY_SAYINGS) +// This returns the number of arguments passed to it (up to 8). +#define NARG_8(...) NARG_8_(_, ##__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0) +#define NARG_8_(_, a, b, c, d, e, f, g, h, N, ...) N + +#define CAT(a, b) CAT_(a, b) +#define CAT_(a, b) a ## b + // This produces an error at compile-time if expr is zero. // It looks like file.c:line: size of array `id' is negative #define STATIC_ASSERT(expr, id) typedef char id[(expr) ? 1 : -1]; diff --git a/include/pokemon.h b/include/pokemon.h index 54b4841f7..f4f6d6989 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -436,12 +436,17 @@ void SetMultiuseSpriteTemplateToPokemon(u16 speciesTag, u8 battlerPosition); void SetMultiuseSpriteTemplateToTrainerBack(u16 trainerSpriteId, u8 battlerPosition); void SetMultiuseSpriteTemplateToTrainerFront(u16 trainerPicId, u8 battlerPosition); -// These are full type signatures for GetMonData() and GetBoxMonData(), -// but they are not used since some code erroneously omits the third arg. -// u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data); -// u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data); -u32 GetMonData(); -u32 GetBoxMonData(); +/* GameFreak called Get(Box)MonData with either 2 or 3 arguments, for + * type safety we have a Get(Box)MonData macro which dispatches to + * either Get(Box)MonData2 or Get(Box)MonData3 based on the number of + * arguments. The two functions are aliases of each other, but they + * differ for matching purposes in the caller's codegen. */ +#define GetMonData(...) CAT(GetMonData, NARG_8(__VA_ARGS__))(__VA_ARGS__) +#define GetBoxMonData(...) CAT(GetBoxMonData, NARG_8(__VA_ARGS__))(__VA_ARGS__) +u32 GetMonData3(struct Pokemon *mon, s32 field, u8 *data); +u32 GetMonData2(struct Pokemon *mon, s32 field); +u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data); +u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field); void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg); void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg); diff --git a/src/daycare.c b/src/daycare.c index c3f4dd990..9d199f0f3 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -341,7 +341,7 @@ static void Debug_AddDaycareSteps(u16 numSteps) u8 GetNumLevelsGainedFromDaycare(void) { - if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004], MON_DATA_SPECIES) != 0) + if (GetBoxMonData(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004].mon, MON_DATA_SPECIES) != 0) return GetNumLevelsGainedForDaycareMon(&gSaveBlock1Ptr->daycare.mons[gSpecialVar_0x8004]); return 0; diff --git a/src/pokemon.c b/src/pokemon.c index fa2eee42c..b8f7ae48b 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3622,7 +3622,11 @@ static union PokemonSubstruct *GetSubstruct(struct BoxPokemon *boxMon, u32 perso return substruct; } -u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data) +/* GameFreak called GetMonData with either 2 or 3 arguments, for type + * safety we have a GetMonData macro (in include/pokemon.h) which + * dispatches to either GetMonData2 or GetMonData3 based on the number + * of arguments. */ +u32 GetMonData3(struct Pokemon *mon, s32 field, u8 *data) { u32 ret; @@ -3690,7 +3694,13 @@ u32 GetMonData(struct Pokemon *mon, s32 field, u8 *data) return ret; } -u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) +u32 GetMonData2(struct Pokemon *mon, s32 field) __attribute__((alias("GetMonData3"))); + +/* GameFreak called GetBoxMonData with either 2 or 3 arguments, for type + * safety we have a GetBoxMonData macro (in include/pokemon.h) which + * dispatches to either GetBoxMonData2 or GetBoxMonData3 based on the + * number of arguments. */ +u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) { s32 i; u32 retVal = 0; @@ -4046,6 +4056,8 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data) return retVal; } +u32 GetBoxMonData2(struct BoxPokemon *boxMon, s32 field) __attribute__((alias("GetBoxMonData3"))); + #define SET8(lhs) (lhs) = *data #define SET16(lhs) (lhs) = data[0] + (data[1] << 8) #define SET32(lhs) (lhs) = data[0] + (data[1] << 8) + (data[2] << 16) + (data[3] << 24) From 31a3ada7de629aa28c828762352b1d307113a1bd Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Mon, 24 Jul 2023 19:04:23 +0100 Subject: [PATCH 14/34] Detect potential misalignment in modern --- include/decompress.h | 2 +- include/gba/m4a_internal.h | 2 +- include/gba/macro.h | 83 ++++++++++++++++++++++++++++++++--- include/gba/syscall.h | 22 ++++++++++ include/global.h | 2 +- include/graphics.h | 6 +-- include/item_menu.h | 2 +- include/librfu.h | 2 +- include/link.h | 2 +- include/mon_markings.h | 2 +- include/palette.h | 6 +-- include/scanline_effect.h | 2 +- src/battle_factory_screen.c | 2 +- src/berry_fix_program.c | 2 +- src/contest.c | 4 +- src/decoration.c | 2 +- src/field_weather.c | 6 +-- src/fieldmap.c | 2 +- src/graphics.c | 4 +- src/item_menu.c | 6 +-- src/link.c | 2 +- src/mirage_tower.c | 2 +- src/palette.c | 2 +- src/pokedex_area_region_map.c | 2 +- src/pokemon_storage_system.c | 4 +- src/pokenav_conditions_gfx.c | 4 +- src/pokenav_region_map.c | 2 +- src/rayquaza_scene.c | 4 +- src/scanline_effect.c | 2 +- src/util.c | 2 +- 30 files changed, 142 insertions(+), 45 deletions(-) diff --git a/include/decompress.h b/include/decompress.h index 5e33665b7..18340d54b 100644 --- a/include/decompress.h +++ b/include/decompress.h @@ -3,7 +3,7 @@ #include "sprite.h" -extern u8 gDecompressionBuffer[0x4000]; +extern u8 ALIGNED(4) gDecompressionBuffer[0x4000]; void LZDecompressWram(const u32 *src, void *dest); void LZDecompressVram(const u32 *src, void *dest); diff --git a/include/gba/m4a_internal.h b/include/gba/m4a_internal.h index 40a25ba05..fc8205efd 100644 --- a/include/gba/m4a_internal.h +++ b/include/gba/m4a_internal.h @@ -213,7 +213,7 @@ struct SoundInfo ExtVolPitFunc ExtVolPit; u8 gap2[16]; struct SoundChannel chans[MAX_DIRECTSOUND_CHANNELS]; - s8 pcmBuffer[PCM_DMA_BUF_SIZE * 2]; + s8 ALIGNED(4) pcmBuffer[PCM_DMA_BUF_SIZE * 2]; }; struct SongHeader diff --git a/include/gba/macro.h b/include/gba/macro.h index 3b35a1946..5239cd4c8 100644 --- a/include/gba/macro.h +++ b/include/gba/macro.h @@ -1,7 +1,7 @@ #ifndef GUARD_GBA_MACRO_H #define GUARD_GBA_MACRO_H -#define CPU_FILL(value, dest, size, bit) \ +#define CPU_FILL_UNCHECKED(value, dest, size, bit) \ { \ vu##bit tmp = (vu##bit)(value); \ CpuSet((void *)&tmp, \ @@ -9,10 +9,33 @@ CPU_SET_##bit##BIT | CPU_SET_SRC_FIXED | ((size)/(bit/8) & 0x1FFFFF)); \ } +#if MODERN +#define CPU_FILL(value, dest, size, bit) \ + do \ + { \ + _Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \ + CPU_FILL_UNCHECKED(value, dest, size, bit); \ + } while (0) +#else +#define CPU_FILL(value, dest, size, bit) CPU_FILL_UNCHECKED(value, dest, size, bit) +#endif + #define CpuFill16(value, dest, size) CPU_FILL(value, dest, size, 16) #define CpuFill32(value, dest, size) CPU_FILL(value, dest, size, 32) -#define CPU_COPY(src, dest, size, bit) CpuSet(src, dest, CPU_SET_##bit##BIT | ((size)/(bit/8) & 0x1FFFFF)) +#define CPU_COPY_UNCHECKED(src, dest, size, bit) CpuSet(src, dest, CPU_SET_##bit##BIT | ((size)/(bit/8) & 0x1FFFFF)) + +#if MODERN +#define CPU_COPY(src, dest, size, bit) \ + do \ + { \ + _Static_assert(_Alignof(src) >= (bit / 8), "source potentially unaligned"); \ + _Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \ + CPU_COPY_UNCHECKED(src, dest, size, bit); \ + } while (0) +#else +#define CPU_COPY(src, dest, size, bit) CPU_COPY_UNCHECKED(src, dest, size, bit) +#endif #define CpuCopy16(src, dest, size) CPU_COPY(src, dest, size, 16) #define CpuCopy32(src, dest, size) CPU_COPY(src, dest, size, 32) @@ -31,7 +54,7 @@ #define CpuFastCopy(src, dest, size) CpuFastSet(src, dest, ((size)/(32/8) & 0x1FFFFF)) -#define DmaSet(dmaNum, src, dest, control) \ +#define DmaSetUnchecked(dmaNum, src, dest, control) \ { \ vu32 *dmaRegs = (vu32 *)REG_ADDR_DMA##dmaNum; \ dmaRegs[0] = (vu32)(src); \ @@ -40,7 +63,21 @@ dmaRegs[2]; \ } -#define DMA_FILL(dmaNum, value, dest, size, bit) \ +#if MODERN +// NOTE: Assumes 16-bit DMAs. +#define DmaSet(dmaNum, src, dest, control) \ + do \ + { \ + _Static_assert(_Alignof(src) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & (DMA_32BIT << 16)) ? 4 : 2, 2), "source potentially unaligned"); \ + _Static_assert(_Alignof(dest) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & (DMA_32BIT << 16)) ? 4 : 2, 2), "destination potentially unaligned"); \ + DmaSetUnchecked(dmaNum, src, dest, control); \ + } while (0) +#else +#define DmaSet(dmaNum, src, dest, control) \ + DmaSetUnchecked(dmaNum, src, dest, control) +#endif + +#define DMA_FILL_UNCHECKED(dmaNum, value, dest, size, bit) \ { \ vu##bit tmp = (vu##bit)(value); \ DmaSet(dmaNum, \ @@ -50,6 +87,17 @@ | ((size)/(bit/8))); \ } +#if MODERN +#define DMA_FILL(dmaNum, value, dest, size, bit) \ + do \ + { \ + _Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \ + DMA_FILL_UNCHECKED(dmaNum, value, dest, size, bit); \ + } while (0) +#else +#define DMA_FILL(dmaNum, value, dest, size, bit) DMA_FILL_UNCHECKED(dmaNum, value, dest, size, bit) +#endif + #define DmaFill16(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 16) #define DmaFill32(dmaNum, value, dest, size) DMA_FILL(dmaNum, value, dest, size, 32) @@ -58,23 +106,46 @@ // unit size (2 or 4 bytes) and then combined with the DMA control flags using a // bitwise OR operation. -#define DMA_CLEAR(dmaNum, dest, size, bit) \ +#define DMA_CLEAR_UNCHECKED(dmaNum, dest, size, bit) \ { \ vu##bit *_dest = (vu##bit *)(dest); \ u32 _size = size; \ DmaFill##bit(dmaNum, 0, _dest, _size); \ } +#if MODERN +#define DMA_CLEAR(dmaNum, dest, size, bit) \ + do \ + { \ + _Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \ + DMA_CLEAR_UNCHECKED(dmaNum, dest, size, bit); \ + } while (0) +#else +#define DMA_CLEAR(dmaNum, dest, size, bit) DMA_CLEAR_UNCHECKED(dmaNum, dest, size, bit) +#endif + #define DmaClear16(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 16) #define DmaClear32(dmaNum, dest, size) DMA_CLEAR(dmaNum, dest, size, 32) -#define DMA_COPY(dmaNum, src, dest, size, bit) \ +#define DMA_COPY_UNCHECKED(dmaNum, src, dest, size, bit) \ DmaSet(dmaNum, \ src, \ dest, \ (DMA_ENABLE | DMA_START_NOW | DMA_##bit##BIT | DMA_SRC_INC | DMA_DEST_INC) << 16 \ | ((size)/(bit/8))) +#if MODERN +#define DMA_COPY(dmaNum, src, dest, size, bit) \ + do \ + { \ + _Static_assert(_Alignof(src) >= (bit / 8), "source potentially unaligned"); \ + _Static_assert(_Alignof(dest) >= (bit / 8), "destination potentially unaligned"); \ + DMA_COPY_UNCHECKED(dmaNum, src, dest, size, bit); \ + } while (0) +#else +#define DMA_COPY(dmaNum, src, dest, size, bit) DMA_COPY_UNCHECKED(dmaNum, src, dest, size, bit) +#endif + #define DmaCopy16(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 16) #define DmaCopy32(dmaNum, src, dest, size) DMA_COPY(dmaNum, src, dest, size, 32) diff --git a/include/gba/syscall.h b/include/gba/syscall.h index 56cd4ba58..c922084d5 100644 --- a/include/gba/syscall.h +++ b/include/gba/syscall.h @@ -27,10 +27,32 @@ u16 ArcTan2(s16 x, s16 y); void CpuSet(const void *src, void *dest, u32 control); +#if MODERN +// NOTE: Assumes 16-bit CpuSets unless control is a constant and has +// CPU_SET_32BIT set. +#define CpuSet(src, dest, control) \ + do \ + { \ + _Static_assert(_Alignof(src) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & CPU_SET_32BIT) ? 4 : 2, 2), "source potentially unaligned"); \ + _Static_assert(_Alignof(dest) >= __builtin_choose_expr(__builtin_constant_p(control), ((control) & CPU_SET_32BIT) ? 4 : 2, 2), "destination potentially unaligned"); \ + CpuSet(src, dest, control); \ + } while (0) +#endif + #define CPU_FAST_SET_SRC_FIXED 0x01000000 void CpuFastSet(const void *src, void *dest, u32 control); +#if MODERN +#define CpuFastSet(src, dest, control) \ + do \ + { \ + _Static_assert(_Alignof(src) >= 4, "source potentially unaligned"); \ + _Static_assert(_Alignof(dest) >= 4, "destination potentially unaligned"); \ + CpuFastSet(src, dest, control); \ + } while (0) +#endif + void BgAffineSet(struct BgAffineSrcData *src, struct BgAffineDstData *dest, s32 count); void ObjAffineSet(struct ObjAffineSrcData *src, void *dest, s32 count, s32 offset); diff --git a/include/global.h b/include/global.h index 00b08f48f..e0cecafd0 100644 --- a/include/global.h +++ b/include/global.h @@ -845,7 +845,7 @@ struct WaldaPhrase struct TrainerNameRecord { u32 trainerId; - u8 trainerName[PLAYER_NAME_LENGTH + 1]; + u8 ALIGNED(2) trainerName[PLAYER_NAME_LENGTH + 1]; }; struct TrainerHillSave diff --git a/include/graphics.h b/include/graphics.h index 135eaa95e..04ad64606 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -3893,7 +3893,7 @@ extern const u32 gIntroGroudon_Gfx[]; extern const u32 gIntroGroudon_Tilemap[]; extern const u32 gIntroLegendBg_Gfx[]; extern const u32 gIntroGroudonBg_Tilemap[]; -extern const u8 gIntro3Bg_Pal[0x200]; +extern const u8 ALIGNED(2) gIntro3Bg_Pal[0x200]; extern const u32 gIntroKyogre_Gfx[]; extern const u32 gIntroKyogre_Tilemap[]; extern const u32 gIntroKyogreBg_Tilemap[]; @@ -5018,8 +5018,8 @@ extern const u32 gPokenavOptions_Gfx[]; extern const u16 gPokenavOptions_Pal[]; // Battle Factory Screen -extern const u8 gFrontierFactorySelectMenu_Gfx[]; -extern const u8 gFrontierFactorySelectMenu_Tilemap[]; +extern const u16 gFrontierFactorySelectMenu_Gfx[]; +extern const u16 gFrontierFactorySelectMenu_Tilemap[]; extern const u16 gFrontierFactorySelectMenu_Pal[]; // Object event pals diff --git a/include/item_menu.h b/include/item_menu.h index ce03cdacb..09ddd729c 100644 --- a/include/item_menu.h +++ b/include/item_menu.h @@ -78,7 +78,7 @@ struct BagMenu u8 numShownItems[POCKETS_COUNT]; s16 graphicsLoadState; u8 unused2[14]; - u8 pocketNameBuffer[32][32]; + u8 ALIGNED(4) pocketNameBuffer[32][32]; u8 unused3[4]; }; diff --git a/include/librfu.h b/include/librfu.h index 0026adece..6b0bd97c7 100644 --- a/include/librfu.h +++ b/include/librfu.h @@ -329,7 +329,7 @@ struct RfuIntrStruct { union RfuPacket rxPacketAlloc; union RfuPacket txPacketAlloc; - u8 block1[0x960]; // size of librfu_intr.s binary + u8 ALIGNED(2) block1[0x960]; // size of librfu_intr.s binary struct STWIStatus block2; }; diff --git a/include/link.h b/include/link.h index f27cddc62..66dd5fecd 100644 --- a/include/link.h +++ b/include/link.h @@ -238,7 +238,7 @@ struct BlockRequest }; extern struct Link gLink; -extern u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; +extern u16 ALIGNED(4) gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; extern u8 gBlockSendBuffer[BLOCK_BUFFER_SIZE]; extern u16 gLinkType; extern u32 gLinkStatus; diff --git a/include/mon_markings.h b/include/mon_markings.h index fda7ad563..dbb53f8e8 100644 --- a/include/mon_markings.h +++ b/include/mon_markings.h @@ -18,7 +18,7 @@ struct MonMarkingsMenu struct Sprite *textSprite; const u8 *frameTiles; const u16 *framePalette; - u8 windowSpriteTiles[0x1000]; + u8 ALIGNED(2) windowSpriteTiles[0x1000]; u8 unused[0x80]; u8 tileLoadState; }; diff --git a/include/palette.h b/include/palette.h index d23a658b4..15c92cc2a 100644 --- a/include/palette.h +++ b/include/palette.h @@ -54,9 +54,9 @@ struct PaletteFadeControl extern struct PaletteFadeControl gPaletteFade; extern u32 gPlttBufferTransferPending; -extern u8 gPaletteDecompressionBuffer[]; -extern u16 gPlttBufferUnfaded[PLTT_BUFFER_SIZE]; -extern u16 gPlttBufferFaded[PLTT_BUFFER_SIZE]; +extern u8 ALIGNED(4) gPaletteDecompressionBuffer[]; +extern u16 ALIGNED(4) gPlttBufferUnfaded[PLTT_BUFFER_SIZE]; +extern u16 ALIGNED(4) gPlttBufferFaded[PLTT_BUFFER_SIZE]; void LoadCompressedPalette(const u32 *src, u16 offset, u16 size); void LoadPalette(const void *src, u16 offset, u16 size); diff --git a/include/scanline_effect.h b/include/scanline_effect.h index ae534d969..80d9df764 100644 --- a/include/scanline_effect.h +++ b/include/scanline_effect.h @@ -37,7 +37,7 @@ struct ScanlineEffect extern struct ScanlineEffect gScanlineEffect; -extern u16 gScanlineEffectRegBuffers[2][0x3C0]; +extern u16 ALIGNED(4) gScanlineEffectRegBuffers[2][0x3C0]; void ScanlineEffect_Stop(void); void ScanlineEffect_Clear(void); diff --git a/src/battle_factory_screen.c b/src/battle_factory_screen.c index 081295323..c5633ce28 100644 --- a/src/battle_factory_screen.c +++ b/src/battle_factory_screen.c @@ -268,7 +268,7 @@ static const u8 sActionHighlightMiddle_Gfx[] = INCBIN_U8( "graphics/battle_front static const u8 sActionHighlightRight_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/action_highlight_right.4bpp"); static const u8 sMonPicBgAnim_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg_anim.4bpp"); static const u8 sMonPicBg_Tilemap[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg.bin"); -static const u8 sMonPicBg_Gfx[] = INCBIN_U8( "graphics/battle_frontier/factory_screen/mon_pic_bg.4bpp"); +static const u16 sMonPicBg_Gfx[] = INCBIN_U16("graphics/battle_frontier/factory_screen/mon_pic_bg.4bpp"); static const u16 sMonPicBg_Pal[] = INCBIN_U16("graphics/battle_frontier/factory_screen/mon_pic_bg.gbapal"); static const struct SpriteSheet sSelect_SpriteSheets[] = diff --git a/src/berry_fix_program.c b/src/berry_fix_program.c index af21bb929..26af445a0 100644 --- a/src/berry_fix_program.c +++ b/src/berry_fix_program.c @@ -117,7 +117,7 @@ static const struct WindowTemplate sBerryFixWindowTemplates[] = { DUMMY_WIN_TEMPLATE }; -static const u16 sBerryFixPalColors[] = { +static const u16 ALIGNED(4) sBerryFixPalColors[] = { RGB_WHITE, RGB_WHITE, RGB(12, 12, 12), RGB(26, 26, 25), RGB(28, 1, 1), RGB(31, 23, 14), RGB(4, 19, 1), RGB(18, 30, 18), RGB(6, 10, 25), RGB(20, 24, 30), RGB_WHITE, RGB(12, 12, 12), diff --git a/src/contest.c b/src/contest.c index 84d295f13..741a0e12d 100644 --- a/src/contest.c +++ b/src/contest.c @@ -1301,8 +1301,8 @@ static void Task_ReadyStartLinkContest(u8 taskId) static bool8 SetupContestGraphics(u8 *stateVar) { - u16 tempPalette1[16]; - u16 tempPalette2[16]; + u16 ALIGNED(4) tempPalette1[16]; + u16 ALIGNED(4) tempPalette2[16]; switch (*stateVar) { diff --git a/src/decoration.c b/src/decoration.c index 27ef85de9..b33580d2d 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -1916,7 +1916,7 @@ static void CopyPalette(u16 *dest, u16 pal) static void CopyTile(u8 *dest, u16 tile) { - u8 buffer[TILE_SIZE_4BPP]; + u8 ALIGNED(4) buffer[TILE_SIZE_4BPP]; u16 mode; u16 i; diff --git a/src/field_weather.c b/src/field_weather.c index 73aef3746..bcc6a1c44 100644 --- a/src/field_weather.c +++ b/src/field_weather.c @@ -61,7 +61,7 @@ static void None_Main(void); static u8 None_Finish(void); EWRAM_DATA struct Weather gWeather = {0}; -EWRAM_DATA static u8 sFieldEffectPaletteColorMapTypes[32] = {0}; +EWRAM_DATA static u8 ALIGNED(2) sFieldEffectPaletteColorMapTypes[32] = {0}; static const u8 *sPaletteColorMapTypes; @@ -111,7 +111,7 @@ void (*const gWeatherPalStateFuncs[])(void) = // This table specifies which of the color maps should be // applied to each of the background and sprite palettes. -static const u8 sBasePaletteColorMapTypes[32] = +static const u8 ALIGNED(2) sBasePaletteColorMapTypes[32] = { // background palettes COLOR_MAP_DARK_CONTRAST, @@ -149,7 +149,7 @@ static const u8 sBasePaletteColorMapTypes[32] = COLOR_MAP_DARK_CONTRAST, }; -const u16 gFogPalette[] = INCBIN_U16("graphics/weather/fog.gbapal"); +const u16 ALIGNED(4) gFogPalette[] = INCBIN_U16("graphics/weather/fog.gbapal"); void StartWeather(void) { diff --git a/src/fieldmap.c b/src/fieldmap.c index bdacf7ab2..9534255c7 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -25,7 +25,7 @@ struct ConnectionFlags u8 east:1; }; -EWRAM_DATA static u16 sBackupMapData[MAX_MAP_DATA_SIZE] = {0}; +EWRAM_DATA static u16 ALIGNED(4) sBackupMapData[MAX_MAP_DATA_SIZE] = {0}; EWRAM_DATA struct MapHeader gMapHeader = {0}; EWRAM_DATA struct Camera gCamera = {0}; EWRAM_DATA static struct ConnectionFlags sMapConnectionFlags = {0}; diff --git a/src/graphics.c b/src/graphics.c index e8f891d8b..3cfd47ea7 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1219,8 +1219,8 @@ const u32 gRouletteMultiplier_Gfx[] = INCBIN_U32("graphics/roulette/multiplier.4 const u16 gFrontierFactorySelectMenu_Pal[] = INCBIN_U16("graphics/battle_frontier/factory_menu1.gbapal"); const u16 gFrontierFactorySelectMenu_Pal2[] = INCBIN_U16("graphics/battle_frontier/factory_menu2.gbapal"); -const u8 gFrontierFactorySelectMenu_Gfx[] = INCBIN_U8("graphics/battle_frontier/factory_menu1.4bpp"); -const u8 gFrontierFactorySelectMenu_Gfx2[] = INCBIN_U8("graphics/battle_frontier/factory_menu2.4bpp"); +const u16 gFrontierFactorySelectMenu_Gfx[] = INCBIN_U16("graphics/battle_frontier/factory_menu1.4bpp"); +const u16 gFrontierFactorySelectMenu_Gfx2[] = INCBIN_U16("graphics/battle_frontier/factory_menu2.4bpp"); const u16 gFrontierFactorySelectMenu_Tilemap[] = INCBIN_U16("graphics/battle_frontier/factory_menu.bin"); diff --git a/src/item_menu.c b/src/item_menu.c index 00449c6ec..223f028d0 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -2429,16 +2429,16 @@ static void PrintPocketNames(const u8 *pocketName1, const u8 *pocketName2) static void CopyPocketNameToWindow(u32 a) { - u8 (* tileDataBuffer)[32][32]; + u8 (*tileDataBuffer)[32][32]; u8 *windowTileData; int b; if (a > 8) a = 8; tileDataBuffer = &gBagMenu->pocketNameBuffer; windowTileData = (u8 *)GetWindowAttribute(2, WINDOW_TILE_DATA); - CpuCopy32(tileDataBuffer[0][a], windowTileData, 0x100); // Top half of pocket name + CpuCopy32(&tileDataBuffer[0][a], windowTileData, 0x100); // Top half of pocket name b = a + 16; - CpuCopy32(tileDataBuffer[0][b], windowTileData + 0x100, 0x100); // Bottom half of pocket name + CpuCopy32(&tileDataBuffer[0][b], windowTileData + 0x100, 0x100); // Bottom half of pocket name CopyWindowToVram(WIN_POCKET_NAME, COPYWIN_GFX); } diff --git a/src/link.c b/src/link.c index 0894021b5..c51abc952 100644 --- a/src/link.c +++ b/src/link.c @@ -78,7 +78,7 @@ bool8 gRemoteLinkPlayersNotReceived[MAX_LINK_PLAYERS]; u8 gBlockReceivedStatus[MAX_LINK_PLAYERS]; u32 gLinkFiller2; u16 gLinkHeldKeys; -u16 gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; +u16 ALIGNED(4) gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH]; u32 gLinkStatus; bool8 gLinkDummy1; // Never read bool8 gLinkDummy2; // Never read diff --git a/src/mirage_tower.c b/src/mirage_tower.c index f9806e776..9b48ee24b 100644 --- a/src/mirage_tower.c +++ b/src/mirage_tower.c @@ -75,7 +75,7 @@ static void Task_FossilFallAndSink(u8); static void SpriteCB_FallingFossil(struct Sprite *); static void UpdateDisintegrationEffect(u8 *, u16, u8, u8, u8); -static const u8 sBlankTile_Gfx[32] = {0}; +static const u8 ALIGNED(2) sBlankTile_Gfx[32] = {0}; static const u8 sMirageTower_Gfx[] = INCBIN_U8("graphics/misc/mirage_tower.4bpp"); static const u16 sMirageTowerTilemap[] = INCBIN_U16("graphics/misc/mirage_tower.bin"); static const u16 sFossil_Pal[] = INCBIN_U16("graphics/object_events/pics/misc/fossil.gbapal"); // Unused diff --git a/src/palette.c b/src/palette.c index 6ce47a493..43a4c213c 100644 --- a/src/palette.c +++ b/src/palette.c @@ -64,7 +64,7 @@ static EWRAM_DATA struct PaletteStruct sPaletteStructs[NUM_PALETTE_STRUCTS] = {0 EWRAM_DATA struct PaletteFadeControl gPaletteFade = {0}; static EWRAM_DATA u32 sFiller = 0; static EWRAM_DATA u32 sPlttBufferTransferPending = 0; -EWRAM_DATA u8 gPaletteDecompressionBuffer[PLTT_SIZE] = {0}; +EWRAM_DATA u8 ALIGNED(2) gPaletteDecompressionBuffer[PLTT_SIZE] = {0}; static const struct PaletteStructTemplate sDummyPaletteStructTemplate = { .id = 0xFFFF, diff --git a/src/pokedex_area_region_map.c b/src/pokedex_area_region_map.c index da50f8c68..cd2975473 100644 --- a/src/pokedex_area_region_map.c +++ b/src/pokedex_area_region_map.c @@ -8,7 +8,7 @@ static EWRAM_DATA u8 *sPokedexAreaMapBgNum = NULL; -static const u16 sPokedexAreaMap_Pal[] = INCBIN_U16("graphics/pokedex/region_map.gbapal"); +static const u16 ALIGNED(4) sPokedexAreaMap_Pal[] = INCBIN_U16("graphics/pokedex/region_map.gbapal"); static const u32 sPokedexAreaMap_Gfx[] = INCBIN_U32("graphics/pokedex/region_map.8bpp.lz"); static const u32 sPokedexAreaMap_Tilemap[] = INCBIN_U32("graphics/pokedex/region_map.bin.lz"); static const u32 sPokedexAreaMapAffine_Gfx[] = INCBIN_U32("graphics/pokedex/region_map_affine.8bpp.lz"); diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 99b0dae0e..9db0d77c6 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -550,8 +550,8 @@ struct PokemonStorageSystemData u16 *displayMonTilePtr; struct Sprite *displayMonSprite; u16 displayMonPalBuffer[0x40]; - u8 tileBuffer[MON_PIC_SIZE * MAX_MON_PIC_FRAMES]; - u8 itemIconBuffer[0x800]; + u8 ALIGNED(4) tileBuffer[MON_PIC_SIZE * MAX_MON_PIC_FRAMES]; + u8 ALIGNED(4) itemIconBuffer[0x800]; u8 wallpaperBgTilemapBuffer[0x1000]; u8 displayMenuTilemapBuffer[0x800]; }; diff --git a/src/pokenav_conditions_gfx.c b/src/pokenav_conditions_gfx.c index e382cbf69..9f4b2db61 100644 --- a/src/pokenav_conditions_gfx.c +++ b/src/pokenav_conditions_gfx.c @@ -116,10 +116,12 @@ static const LoopedTask sLoopedTaskFuncs[] = [CONDITION_FUNC_CLOSE_MARKINGS] = LoopedTask_CloseMonMarkingsWindow }; +typedef u8 ALIGNED(4) TilemapBuffer[BG_SCREEN_SIZE]; + struct Pokenav_ConditionMenuGfx { u32 loopedTaskId; - u8 tilemapBuffers[3][BG_SCREEN_SIZE]; + TilemapBuffer tilemapBuffers[3]; u8 filler[2]; u8 partyPokeballSpriteIds[PARTY_SIZE + 1]; u32 (*callback)(void); diff --git a/src/pokenav_region_map.c b/src/pokenav_region_map.c index e589e2818..f81ff4296 100755 --- a/src/pokenav_region_map.c +++ b/src/pokenav_region_map.c @@ -35,7 +35,7 @@ struct Pokenav_RegionMapGfx u32 loopTaskId; u16 infoWindowId; struct Sprite *cityZoomTextSprites[3]; - u8 tilemapBuffer[BG_SCREEN_SIZE]; + u8 ALIGNED(2) tilemapBuffer[BG_SCREEN_SIZE]; u8 cityZoomPics[NUM_CITY_MAPS][200]; }; diff --git a/src/rayquaza_scene.c b/src/rayquaza_scene.c index c984dfec8..cacadf528 100644 --- a/src/rayquaza_scene.c +++ b/src/rayquaza_scene.c @@ -60,10 +60,12 @@ enum #define MAX_SMOKE 10 +typedef u8 ALIGNED(4) TilemapBuffer[BG_SCREEN_SIZE]; + struct RayquazaScene { MainCallback exitCallback; - u8 tilemapBuffers[4][BG_SCREEN_SIZE]; + TilemapBuffer tilemapBuffers[4]; u16 unk; // never read u8 animId; bool8 endEarly; diff --git a/src/scanline_effect.c b/src/scanline_effect.c index dc3ca03f4..684c89546 100644 --- a/src/scanline_effect.c +++ b/src/scanline_effect.c @@ -13,7 +13,7 @@ static void CopyValue32Bit(void); // Per-scanline register values. // This is double buffered so that it can be safely written to at any time // without overwriting the buffer that the DMA is currently reading -EWRAM_DATA u16 gScanlineEffectRegBuffers[2][0x3C0] = {0}; +EWRAM_DATA u16 ALIGNED(4) gScanlineEffectRegBuffers[2][0x3C0] = {0}; EWRAM_DATA struct ScanlineEffect gScanlineEffect = {0}; EWRAM_DATA static bool8 sShouldStopWaveTask = FALSE; diff --git a/src/util.c b/src/util.c index 32f31a26d..ab5603b86 100644 --- a/src/util.c +++ b/src/util.c @@ -158,7 +158,7 @@ void CopySpriteTiles(u8 shape, u8 size, u8 *tiles, u16 *tilemap, u8 *output) { u8 x, y; s8 i, j; - u8 xflip[32]; + u8 ALIGNED(4) xflip[32]; u8 h = sSpriteDimensions[shape][size][1]; u8 w = sSpriteDimensions[shape][size][0]; From 6f31314c4aed40eb27c7dc2dd58c5fb34964cebd Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 26 Jul 2023 09:42:29 +0200 Subject: [PATCH 15/34] Fix uturn typo in test --- test/ability_rattled.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/ability_rattled.c b/test/ability_rattled.c index bddc88751..493e3cfca 100644 --- a/test/ability_rattled.c +++ b/test/ability_rattled.c @@ -82,7 +82,7 @@ SINGLE_BATTLE_TEST("Rattled triggers correctly when hit by U-Turn") // Specific } WHEN { TURN { MOVE(player, MOVE_U_TURN); SEND_OUT(player, 1); } } SCENE { - MESSAGE("Wobbuffet used U-Turn!"); + MESSAGE("Wobbuffet used U-turn!"); ANIMATION(ANIM_TYPE_MOVE, MOVE_U_TURN, player); HP_BAR(opponent); ABILITY_POPUP(opponent, ABILITY_RATTLED); From 1baa57418ed087df597ebb4d5d8ab36fbc840fb0 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 27 Jul 2023 03:33:01 +0200 Subject: [PATCH 16/34] Fixed copyright screen not showing up on certain emulators (#2664) * Fix old intro not showing up on VBA * Update intro.c * Update intro.c * Update intro.c --- src/intro.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/intro.c b/src/intro.c index bfc23a74b..28b4120b1 100644 --- a/src/intro.c +++ b/src/intro.c @@ -1096,6 +1096,10 @@ static u8 SetUpCopyrightScreen(void) REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON; SetSerialCallback(SerialCB_CopyrightScreen); GameCubeMultiBoot_Init(&gMultibootProgramStruct); + // REG_DISPCNT needs to be overwritten the second time, because otherwise the intro won't show up on VBA 1.7.2 and John GBA Lite emulators. + // The REG_DISPCNT overwrite is NOT needed in m-GBA, No$GBA, VBA 1.8.0, My Boy and Pizza Boy GBA emulators. + case 1: + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON; default: UpdatePaletteFade(); gMain.state++; From 4a657c7eaff8ef277e00e6ddbbcfdc651befab52 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Tue, 25 Jul 2023 20:47:35 -0300 Subject: [PATCH 17/34] Revamped GetTotalAccuracy --- src/battle_script_commands.c | 74 +++++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 18 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ccd4a404f..69d6eb1a4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1852,6 +1852,8 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u s8 buff, accStage, evasionStage; u8 atkParam = GetBattlerHoldEffectParam(battlerAtk); u8 defParam = GetBattlerHoldEffectParam(battlerDef); + u8 atkAlly = BATTLE_PARTNER(battlerAtk); + u16 atkAllyAbility = GetBattlerAbility(atkAlly); gPotentialItemEffectBattler = battlerDef; accStage = gBattleMons[battlerAtk].statStages[STAT_ACC]; @@ -1885,30 +1887,66 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u calc = gAccuracyStageRatios[buff].dividend * moveAcc; calc /= gAccuracyStageRatios[buff].divisor; - if (atkAbility == ABILITY_COMPOUND_EYES) + // Attacker's ability + switch (atkAbility) + { + case ABILITY_COMPOUND_EYES: calc = (calc * 130) / 100; // 1.3 compound eyes boost - else if (atkAbility == ABILITY_VICTORY_STAR) + break; + case ABILITY_VICTORY_STAR: calc = (calc * 110) / 100; // 1.1 victory star boost - if (IsBattlerAlive(BATTLE_PARTNER(battlerAtk)) && GetBattlerAbility(BATTLE_PARTNER(battlerAtk)) == ABILITY_VICTORY_STAR) - calc = (calc * 110) / 100; // 1.1 ally's victory star boost + break; + case ABILITY_HUSTLE: + if (IS_MOVE_PHYSICAL(move)) + calc = (calc * 80) / 100; // 1.2 hustle loss + break; + } - if (defAbility == ABILITY_SAND_VEIL && WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SANDSTORM) - calc = (calc * 80) / 100; // 1.2 sand veil loss - else if (defAbility == ABILITY_SNOW_CLOAK && WEATHER_HAS_EFFECT && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) - calc = (calc * 80) / 100; // 1.2 snow cloak loss - else if (defAbility == ABILITY_TANGLED_FEET && gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) - calc = (calc * 50) / 100; // 1.5 tangled feet loss + // Target's ability + switch (defAbility) + { + case ABILITY_SAND_VEIL: + if (WEATHER_HAS_EFFECT && gBattleWeather & B_WEATHER_SANDSTORM) + calc = (calc * 80) / 100; // 1.2 sand veil loss + break; + case ABILITY_SNOW_CLOAK: + if (WEATHER_HAS_EFFECT && (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW))) + calc = (calc * 80) / 100; // 1.2 snow cloak loss + break; + case ABILITY_TANGLED_FEET: + if (gBattleMons[battlerDef].status2 & STATUS2_CONFUSION) + calc = (calc * 50) / 100; // 1.5 tangled feet loss + break; + } - if (atkAbility == ABILITY_HUSTLE && IS_MOVE_PHYSICAL(move)) - calc = (calc * 80) / 100; // 1.2 hustle loss + // Attacker's ally's ability + switch (atkAllyAbility) + { + case ABILITY_VICTORY_STAR: + if (IsBattlerAlive(atkAlly)) + calc = (calc * 110) / 100; // 1.1 ally's victory star boost + break; + } - if (defHoldEffect == HOLD_EFFECT_EVASION_UP) + // Attacker's hold effect + switch (atkHoldEffect) + { + case HOLD_EFFECT_WIDE_LENS: + calc = (calc * (100 + atkParam)) / 100; + break; + case HOLD_EFFECT_ZOOM_LENS: + if (GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef)) + calc = (calc * (100 + atkParam)) / 100; + break; + } + + // Target's hold effect + switch (defHoldEffect) + { + case HOLD_EFFECT_EVASION_UP: calc = (calc * (100 - defParam)) / 100; - - if (atkHoldEffect == HOLD_EFFECT_WIDE_LENS) - calc = (calc * (100 + atkParam)) / 100; - else if (atkHoldEffect == HOLD_EFFECT_ZOOM_LENS && GetBattlerTurnOrderNum(battlerAtk) > GetBattlerTurnOrderNum(battlerDef)) - calc = (calc * (100 + atkParam)) / 100; + break; + } if (gProtectStructs[battlerAtk].usedMicleBerry) { From 5eec3b2fc3e863326e5bb0f6a1828528c15d7c29 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sun, 30 Jul 2023 16:50:51 +0200 Subject: [PATCH 18/34] fix various issues with primal weather blocking water/fire type moves (#3138) * fix various issues with primal weather blocking water/fire type moves * forgot to change return to effect=1 * fix bugs --- data/battle_scripts_1.s | 20 +--- include/battle_scripts.h | 3 +- include/battle_util.h | 2 +- include/constants/battle_string_ids.h | 4 + src/battle_message.c | 6 ++ src/battle_script_commands.c | 37 ++++---- src/battle_util.c | 7 +- test/primal_weather.c | 127 ++++++++++++++++++++++++++ 8 files changed, 164 insertions(+), 42 deletions(-) create mode 100644 test/primal_weather.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 39712db73..372e0e8e6 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8782,15 +8782,14 @@ BattleScript_DesolateLandActivates:: call BattleScript_ActivateWeatherAbilities end3 -BattleScript_DesolateLandEvaporatesWaterTypeMoves:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE +BattleScript_PrimalWeatherBlocksMove:: + jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_MoveEnd @in case of multi-target moves, if move fails once, no point in printing the message twice + accuracycheck BattleScript_PrintMoveMissed, NO_ACC_CALC_CHECK_LOCK_ON attackstring pause B_WAIT_TIME_SHORT ppreduce - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_STRING_PRINTED, BattleScript_MoveEnd - printstring STRINGID_MOVEEVAPORATEDINTHEHARSHSUNLIGHT + printfromtable gPrimalWeatherBlocksStringIds waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_STRING_PRINTED goto BattleScript_MoveEnd BattleScript_PrimordialSeaActivates:: @@ -8802,17 +8801,6 @@ BattleScript_PrimordialSeaActivates:: call BattleScript_ActivateWeatherAbilities end3 -BattleScript_PrimordialSeaFizzlesOutFireTypeMoves:: - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - attackstring - pause B_WAIT_TIME_SHORT - ppreduce - jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_STRING_PRINTED, BattleScript_MoveEnd - printstring STRINGID_MOVEFIZZLEDOUTINTHEHEAVYRAIN - waitmessage B_WAIT_TIME_LONG - orword gHitMarker, HITMARKER_STRING_PRINTED - goto BattleScript_MoveEnd - BattleScript_DeltaStreamActivates:: pause B_WAIT_TIME_SHORT call BattleScript_AbilityPopUp diff --git a/include/battle_scripts.h b/include/battle_scripts.h index b20ac35dd..95f068cf5 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -409,9 +409,8 @@ extern const u8 BattleScript_GulpMissileGorging[]; extern const u8 BattleScript_GulpMissileGulping[]; extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[]; extern const u8 BattleScript_DesolateLandActivates[]; -extern const u8 BattleScript_DesolateLandEvaporatesWaterTypeMoves[]; extern const u8 BattleScript_PrimordialSeaActivates[]; -extern const u8 BattleScript_PrimordialSeaFizzlesOutFireTypeMoves[]; +extern const u8 BattleScript_PrimalWeatherBlocksMove[]; extern const u8 BattleScript_DeltaStreamActivates[]; extern const u8 BattleScript_MysteriousAirCurrentBlowsOn[]; extern const u8 BattleScript_AttackWeakenedByStrongWinds[]; diff --git a/include/battle_util.h b/include/battle_util.h index 15fbe2432..51375000c 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -136,8 +136,8 @@ u8 DoBattlerEndTurnEffects(void); bool8 HandleWishPerishSongOnTurnEnd(void); bool8 HandleFaintedMonActions(void); void TryClearRageAndFuryCutter(void); +u8 AtkCanceller_UnableToUseMove(u32 moveType); void SetAtkCancellerForCalledMove(void); -u8 AtkCanceller_UnableToUseMove(void); u8 AtkCanceller_UnableToUseMove2(void); bool8 HasNoMonsToSwitch(u8 battlerId, u8 r1, u8 r2); bool32 TryChangeBattleWeather(u8 battler, u32 weatherEnumId, bool32 viaAbility); diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 174c611e2..0597612d1 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -827,6 +827,10 @@ #define B_MSG_SOMEONES_BOX_FULL 2 #define B_MSG_LANETTES_BOX_FULL 3 +// gPrimalWeatherBlocksStringIds +#define B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN 0 +#define B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN 1 + // gInobedientStringIds #define B_MSG_LOAFING 0 #define B_MSG_WONT_OBEY 1 diff --git a/src/battle_message.c b/src/battle_message.c index 1585f8c47..0613906c3 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1850,6 +1850,12 @@ const u16 gWeatherStartsStringIds[] = [WEATHER_ABNORMAL] = STRINGID_ITISRAINING }; +const u16 gPrimalWeatherBlocksStringIds[] = +{ + [B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN] = STRINGID_MOVEFIZZLEDOUTINTHEHEAVYRAIN, + [B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN] = STRINGID_MOVEEVAPORATEDINTHEHARSHSUNLIGHT, +}; + const u16 gInobedientStringIds[] = { [B_MSG_LOAFING] = STRINGID_PKMNLOAFING, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ccd4a404f..cf793bf24 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1503,25 +1503,8 @@ static void Cmd_attackcanceler(void) s32 i, moveType; u16 attackerAbility = GetBattlerAbility(gBattlerAttacker); - GET_MOVE_TYPE(gCurrentMove, moveType); - if (WEATHER_HAS_EFFECT && gBattleMoves[gCurrentMove].power) - { - if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL)) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_PrimordialSeaFizzlesOutFireTypeMoves; - return; - } - else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL)) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_DesolateLandEvaporatesWaterTypeMoves; - return; - } - } - if (gBattleOutcome != 0) { gCurrentActionFuncId = B_ACTION_FINISHED; @@ -1537,9 +1520,27 @@ static void Cmd_attackcanceler(void) if (TryAegiFormChange()) return; #endif - if (AtkCanceller_UnableToUseMove()) + if (AtkCanceller_UnableToUseMove(moveType)) return; + if (WEATHER_HAS_EFFECT && gBattleMoves[gCurrentMove].power) + { + if (moveType == TYPE_FIRE && (gBattleWeather & B_WEATHER_RAIN_PRIMAL)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_FIZZLED_BY_RAIN; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove; + return; + } + else if (moveType == TYPE_WATER && (gBattleWeather & B_WEATHER_SUN_PRIMAL)) + { + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_PRIMAL_WEATHER_EVAPORATED_IN_SUN; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_PrimalWeatherBlocksMove; + return; + } + } + if (gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_OFF && GetBattlerAbility(gBattlerAttacker) == ABILITY_PARENTAL_BOND && IsMoveAffectedByParentalBond(gCurrentMove, gBattlerAttacker) diff --git a/src/battle_util.c b/src/battle_util.c index d549b71b9..168d5432d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3389,10 +3389,9 @@ void SetAtkCancellerForCalledMove(void) gBattleStruct->isAtkCancelerForCalledMove = TRUE; } -u8 AtkCanceller_UnableToUseMove(void) +u8 AtkCanceller_UnableToUseMove(u32 moveType) { u8 effect = 0; - s32 *bideDmg = &gBattleScripting.bideDmg; do { switch (gBattleStruct->atkCancellerTracker) @@ -3653,7 +3652,7 @@ u8 AtkCanceller_UnableToUseMove(void) if (gTakenDmg[gBattlerAttacker]) { gCurrentMove = MOVE_BIDE; - *bideDmg = gTakenDmg[gBattlerAttacker] * 2; + gBattleScripting.bideDmg = gTakenDmg[gBattlerAttacker] * 2; gBattlerTarget = gTakenDmgByBattler[gBattlerAttacker]; if (gAbsentBattlerFlags & gBitTable[gBattlerTarget]) gBattlerTarget = GetMoveTarget(MOVE_BIDE, MOVE_TARGET_SELECTED + 1); @@ -3723,8 +3722,6 @@ u8 AtkCanceller_UnableToUseMove(void) case CANCELLER_POWDER_STATUS: if (gBattleMons[gBattlerAttacker].status2 & STATUS2_POWDER) { - u32 moveType; - GET_MOVE_TYPE(gCurrentMove, moveType); if (moveType == TYPE_FIRE) { gProtectStructs[gBattlerAttacker].powderSelfDmg = TRUE; diff --git a/test/primal_weather.c b/test/primal_weather.c new file mode 100644 index 000000000..650a79921 --- /dev/null +++ b/test/primal_weather.c @@ -0,0 +1,127 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_EMBER].power != 0); + ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); + ASSUME(gBattleMoves[MOVE_WATER_GUN].power != 0); + ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER); +} + +SINGLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves") +{ + GIVEN { + PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + MESSAGE("Foe Wobbuffet used Ember!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + NOT HP_BAR(player); + MESSAGE("Foe Wobbuffet used Ember!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + NOT HP_BAR(player); + } THEN { + EXPECT_EQ(player->hp, player->maxHP); + } +} + +DOUBLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves and prints the message only once with moves hitting multiple targets") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_ERUPTION].power != 0); + ASSUME(gBattleMoves[MOVE_ERUPTION].type == TYPE_FIRE); + ASSUME(gBattleMoves[MOVE_ERUPTION].target == MOVE_TARGET_BOTH); + PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB); {Speed(5);}} + PLAYER(SPECIES_WOBBUFFET) {Speed(5);} + OPPONENT(SPECIES_WOBBUFFET) {Speed(10);} + OPPONENT(SPECIES_WOBBUFFET) {Speed(8);} + } WHEN { + TURN { MOVE(opponentLeft, MOVE_ERUPTION); } + } SCENE { + MESSAGE("Foe Wobbuffet used Eruption!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ERUPTION, opponentLeft); + MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + } THEN { + EXPECT_EQ(playerLeft->hp, playerLeft->maxHP); + EXPECT_EQ(playerRight->hp, playerRight->maxHP); + } +} + +SINGLE_BATTLE_TEST("Primordial Sea does not block a move if pokemon is asleep and uses a Fire-type move") // Sleep/confusion/paralysis all happen before the check for primal weather +{ + GIVEN { + PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);} + OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);} + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + MESSAGE("Foe Wobbuffet is fast asleep."); + } +} + +SINGLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves") +{ + GIVEN { + PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_WATER_GUN); } + TURN { MOVE(opponent, MOVE_WATER_GUN); } + } SCENE { + MESSAGE("Foe Wobbuffet used Water Gun!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); + MESSAGE("The Water-type attack evaporated in the harsh sunlight!"); + NOT HP_BAR(player); + MESSAGE("Foe Wobbuffet used Water Gun!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_GUN, opponent); + MESSAGE("The Water-type attack evaporated in the harsh sunlight!"); + NOT HP_BAR(player); + } THEN { + EXPECT_EQ(player->hp, player->maxHP); + } +} + +DOUBLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves and prints the message only once with moves hitting multiple targets") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SURF].power != 0); + ASSUME(gBattleMoves[MOVE_SURF].type == TYPE_WATER); + ASSUME(gBattleMoves[MOVE_SURF].target == MOVE_TARGET_FOES_AND_ALLY); + PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB); {Speed(5);}} + PLAYER(SPECIES_WOBBUFFET) {Speed(5);} + OPPONENT(SPECIES_WOBBUFFET) {Speed(10);} + OPPONENT(SPECIES_WOBBUFFET) {Speed(8);} + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SURF); } + } SCENE { + MESSAGE("Foe Wobbuffet used Surf!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, opponentLeft); + MESSAGE("The Water-type attack evaporated in the harsh sunlight!"); + NOT MESSAGE("The Water-type attack evaporated in the harsh sunlight!"); + } THEN { + EXPECT_EQ(playerLeft->hp, playerLeft->maxHP); + EXPECT_EQ(playerRight->hp, playerRight->maxHP); + EXPECT_EQ(opponentRight->hp, opponentRight->maxHP); + } +} + +SINGLE_BATTLE_TEST("Desolate Land does not block a move if pokemon is asleep and uses a Water-type move") // Sleep/confusion/paralysis all happen before the check for primal weather +{ + GIVEN { + PLAYER(SPECIES_GROUDON) {Item(ITEM_RED_ORB);} + OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);} + } WHEN { + TURN { MOVE(opponent, MOVE_WATER_GUN); } + } SCENE { + NOT MESSAGE("The Water-type attack evaporated in the harsh sunlight!"); + MESSAGE("Foe Wobbuffet is fast asleep."); + } +} From efb98e97c76d453f3ecd7cd773696b18c325632a Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 31 Jul 2023 14:22:48 +0200 Subject: [PATCH 19/34] remove unused config B_CHECK_IF_CHARGED_UP --- include/config/battle.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/config/battle.h b/include/config/battle.h index 20cb7eb81..10d2648a8 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -118,7 +118,6 @@ #define B_PLUS_MINUS_INTERACTION GEN_LATEST // In Gen5+, Plus and Minus can be activated with themselves and the opposite ability. Before, only the opposing ability could activate it. #define B_WEATHER_FORMS GEN_LATEST // In Gen5+, Castform and Cherrim revert to their base form upon losing their respective ability. Cherrim needs Flower Gift to swap forms. #define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply. -#define B_CHECK_IF_CHARGED_UP TRUE // If set to TRUE, certain abilities such as Electromorphosis WILL check if the STATUS3_CHARGED_UP status flag is applied. #define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases. #define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight. #define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail. From 0bace94dc724ed1a170eed12a7755eaa09c94bd8 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Thu, 3 Aug 2023 14:46:45 -0300 Subject: [PATCH 20/34] Updated Cmd_jumpifsideaffecting --- src/battle_script_commands.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 32477451b..8b69e36fb 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4183,11 +4183,7 @@ static void Cmd_jumpifsideaffecting(void) u32 flags; const u8 *jumpInstr; - if (cmd->battler == BS_ATTACKER) - side = GET_BATTLER_SIDE(gBattlerAttacker); - else - side = GET_BATTLER_SIDE(gBattlerTarget); - + side = GET_BATTLER_SIDE(GetBattlerForBattleScript(cmd->battler)); flags = cmd->flags; jumpInstr = cmd->jumpInstr; From 5226935857e77b85259fa5aece46eb431709da3f Mon Sep 17 00:00:00 2001 From: Eclipse <115349505+SubzeroEclipse@users.noreply.github.com> Date: Sat, 5 Aug 2023 04:56:05 +0200 Subject: [PATCH 21/34] =?UTF-8?q?Fixed=20Trainer=20class=20ball=20not=20as?= =?UTF-8?q?signed=20to=20second=20Pok=C3=A9mon=20(#3203)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/battle_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_main.c b/src/battle_main.c index 5841f8f61..b75c44b77 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -1964,7 +1964,6 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer u8 fixedIV; s32 i, j; u8 monsCount; - s32 ball = -1; if (battleTypeFlags & BATTLE_TYPE_TRAINER && !(battleTypeFlags & (BATTLE_TYPE_FRONTIER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_TRAINER_HILL))) @@ -1986,6 +1985,7 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer for (i = 0; i < monsCount; i++) { + s32 ball = -1; u32 personalityHash = GeneratePartyHash(trainer, i); if (trainer->doubleBattle == TRUE) personalityValue = 0x80; From d74cbca0b915d91db9d573a93cd10ed690a51753 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 6 Aug 2023 21:02:16 -0400 Subject: [PATCH 22/34] LF shenanigans --- .../ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 100 +++++++++--------- .../ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 100 +++++++++--------- .../ISSUE_TEMPLATE/03_feature_requests.yaml | 54 +++++----- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 100 +++++++++--------- 4 files changed, 177 insertions(+), 177 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 55d4fada4..c4404a039 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -1,50 +1,50 @@ -name: ⚔️ Battle Engine mechanical bugs 🐛 -description: File a bug report related to battle mechanic, be it moves, abilities and/or items. -labels: ["bug", "status: unconfirmed", "category: battle-mechanic"] -body: - - type: markdown - attributes: - value: | - Please fill in all required fields with as many details as possible. - - type: textarea - id: description - attributes: - label: Description - description: | - Describe the issue you are experiencing. - Attach images/videos if possible. - placeholder: | - Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video - validations: - required: true - - type: dropdown - id: version - attributes: - label: Version - description: What version of pokeemerald-expansion are you using as a base? - options: - - 1.5.1 (Default) - - upcoming (Edge) - - 1.5.0 - - 1.4.3 - - 1.4.2 - - 1.4.1 - - 1.4.0 - - pre-1.4.0 - validations: - required: true - - type: input - id: upcomingversion - attributes: - label: Upcoming Version - description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. - validations: - required: false - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). - placeholder: ex. Lunos#4026 - validations: - required: false +name: ⚔️ Battle Engine mechanical bugs 🐛 +description: File a bug report related to battle mechanic, be it moves, abilities and/or items. +labels: ["bug", "status: unconfirmed", "category: battle-mechanic"] +body: + - type: markdown + attributes: + value: | + Please fill in all required fields with as many details as possible. + - type: textarea + id: description + attributes: + label: Description + description: | + Describe the issue you are experiencing. + Attach images/videos if possible. + placeholder: | + Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of pokeemerald-expansion are you using as a base? + options: + - 1.5.1 (Default) + - upcoming (Edge) + - 1.5.0 + - 1.4.3 + - 1.4.2 + - 1.4.1 + - 1.4.0 + - pre-1.4.0 + validations: + required: true + - type: input + id: upcomingversion + attributes: + label: Upcoming Version + description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. + validations: + required: false + - type: input + id: contact + attributes: + label: Discord contact info + description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). + placeholder: ex. Lunos#4026 + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 8c28b3942..a24757fc7 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -1,50 +1,50 @@ -name: 🧠 Battle AI bugs 🐛 -description: File a bug report related to battle AI. -labels: ["bug", "status: unconfirmed", "category: battle-ai"] -body: - - type: markdown - attributes: - value: | - Please fill in all required fields with as many details as possible. - - type: textarea - id: description - attributes: - label: Description - description: | - Describe the issue you are experiencing. - Attach images/videos if possible. - placeholder: | - Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video - validations: - required: true - - type: dropdown - id: version - attributes: - label: Version - description: What version of pokeemerald-expansion are you using as a base? - options: - - 1.5.1 (Default) - - upcoming (Edge) - - 1.5.0 - - 1.4.3 - - 1.4.2 - - 1.4.1 - - 1.4.0 - - pre-1.4.0 - validations: - required: true - - type: input - id: upcomingversion - attributes: - label: Upcoming Version - description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. - validations: - required: false - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). - placeholder: ex. Lunos#4026 - validations: - required: false +name: 🧠 Battle AI bugs 🐛 +description: File a bug report related to battle AI. +labels: ["bug", "status: unconfirmed", "category: battle-ai"] +body: + - type: markdown + attributes: + value: | + Please fill in all required fields with as many details as possible. + - type: textarea + id: description + attributes: + label: Description + description: | + Describe the issue you are experiencing. + Attach images/videos if possible. + placeholder: | + Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of pokeemerald-expansion are you using as a base? + options: + - 1.5.1 (Default) + - upcoming (Edge) + - 1.5.0 + - 1.4.3 + - 1.4.2 + - 1.4.1 + - 1.4.0 + - pre-1.4.0 + validations: + required: true + - type: input + id: upcomingversion + attributes: + label: Upcoming Version + description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. + validations: + required: false + - type: input + id: contact + attributes: + label: Discord contact info + description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). + placeholder: ex. Lunos#4026 + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/03_feature_requests.yaml b/.github/ISSUE_TEMPLATE/03_feature_requests.yaml index 79e85709f..682f0dc09 100644 --- a/.github/ISSUE_TEMPLATE/03_feature_requests.yaml +++ b/.github/ISSUE_TEMPLATE/03_feature_requests.yaml @@ -1,27 +1,27 @@ -name: 🙏 Feature Request 🙏 -description: Do you want a feature to be added to the Expansion? Let us know! -labels: ["feature-request"] -body: - - type: markdown - attributes: - value: | - Please fill in all required fields with as many details as possible. - - type: textarea - id: description - attributes: - label: Description - description: | - Describe the issue you are experiencing. - Attach images/videos if possible. - placeholder: | - Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video - validations: - required: true - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). - placeholder: ex. Lunos#4026 - validations: - required: false +name: 🙏 Feature Request 🙏 +description: Do you want a feature to be added to the Expansion? Let us know! +labels: ["feature-request"] +body: + - type: markdown + attributes: + value: | + Please fill in all required fields with as many details as possible. + - type: textarea + id: description + attributes: + label: Description + description: | + Describe the issue you are experiencing. + Attach images/videos if possible. + placeholder: | + Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video + validations: + required: true + - type: input + id: contact + attributes: + label: Discord contact info + description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). + placeholder: ex. Lunos#4026 + validations: + required: false diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index 6f11d5b9a..e25695c0b 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -1,50 +1,50 @@ -name: 💾 Other errors 🖥️ -description: Everything else that doesn't fit in the above categories. -labels: ["bug", "status: unconfirmed"] -body: - - type: markdown - attributes: - value: | - Please fill in all required fields with as many details as possible. - - type: textarea - id: description - attributes: - label: Description - description: | - Describe the issue you are experiencing. - Attach images/videos if possible. - placeholder: | - Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video - validations: - required: true - - type: dropdown - id: version - attributes: - label: Version - description: What version of pokeemerald-expansion are you using as a base? - options: - - 1.5.1 (Default) - - upcoming (Edge) - - 1.5.0 - - 1.4.3 - - 1.4.2 - - 1.4.1 - - 1.4.0 - - pre-1.4.0 - validations: - required: true - - type: input - id: upcomingversion - attributes: - label: Upcoming Version - description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. - validations: - required: false - - type: input - id: contact - attributes: - label: Discord contact info - description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). - placeholder: ex. Lunos#4026 - validations: - required: false +name: 💾 Other errors 🖥️ +description: Everything else that doesn't fit in the above categories. +labels: ["bug", "status: unconfirmed"] +body: + - type: markdown + attributes: + value: | + Please fill in all required fields with as many details as possible. + - type: textarea + id: description + attributes: + label: Description + description: | + Describe the issue you are experiencing. + Attach images/videos if possible. + placeholder: | + Please enter a description of the issue. Here you can also attach log screenshots, gifs or a video + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of pokeemerald-expansion are you using as a base? + options: + - 1.5.1 (Default) + - upcoming (Edge) + - 1.5.0 + - 1.4.3 + - 1.4.2 + - 1.4.1 + - 1.4.0 + - pre-1.4.0 + validations: + required: true + - type: input + id: upcomingversion + attributes: + label: Upcoming Version + description: If you're using the upcoming branch, please specify what was the commit hash you pulled from. + validations: + required: false + - type: input + id: contact + attributes: + label: Discord contact info + description: Provide your Discord tag here so we can contact you in case we need more details. Be sure to join our server ([here](https://discord.gg/6CzjAG6GZk)). + placeholder: ex. Lunos#4026 + validations: + required: false From 1fb42e44972ef77422a4efe9776d2d129417846e Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 7 Aug 2023 16:27:57 +0200 Subject: [PATCH 23/34] Sticky web / Court Change / Mirror Armor tests + small fixes (#3160) Co-authored-by: Eduardo Quezada D'Ottone Co-authored-by: Martin Griffin --- include/battle.h | 2 +- src/battle_main.c | 21 ++- src/battle_message.c | 4 +- src/battle_script_commands.c | 15 +- test/ability_mirror_armor.c | 202 +++++++++++++++++++++++++++ test/hold_effect_berserk_gene.c | 2 +- test/move_effect_court_change.c | 153 +++++++++++++++++++++ test/move_effect_defog.c | 2 +- test/move_effect_sticky_web.c | 237 ++++++++++++++++++++++++++++++++ 9 files changed, 620 insertions(+), 18 deletions(-) create mode 100644 test/ability_mirror_armor.c create mode 100644 test/move_effect_court_change.c create mode 100644 test/move_effect_sticky_web.c diff --git a/include/battle.h b/include/battle.h index b27062c12..e3f2e90d0 100644 --- a/include/battle.h +++ b/include/battle.h @@ -212,6 +212,7 @@ struct SideTimer u8 toxicSpikesAmount; u8 stealthRockAmount; u8 stickyWebAmount; + u8 stickyWebBattlerId; u8 stickyWebBattlerSide; // Used for Court Change u8 auroraVeilTimer; u8 auroraVeilBattlerId; @@ -644,7 +645,6 @@ struct BattleStruct u8 forcedSwitch:4; // For each battler u8 switchInAbilityPostponed:4; // To not activate against an empty field, each bit for battler u8 ballSpriteIds[2]; // item gfx, window gfx - u8 stickyWebUser; u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. diff --git a/src/battle_main.c b/src/battle_main.c index b75c44b77..855e77017 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3170,7 +3170,10 @@ static void BattleStartClearSetData(void) gBattleStruct->mega.triggerSpriteId = 0xFF; - gBattleStruct->stickyWebUser = 0xFF; + for (i = 0; i < ARRAY_COUNT(gSideTimers); i++) + { + gSideTimers[i].stickyWebBattlerId = 0xFF; + } gBattleStruct->appearedInBattle = 0; gBattleStruct->beatUpSlot = 0; @@ -3276,8 +3279,12 @@ void SwitchInClearSetData(void) gBattleStruct->lastMoveFailed &= ~(gBitTable[gActiveBattler]); gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]); - if (gActiveBattler == gBattleStruct->stickyWebUser) - gBattleStruct->stickyWebUser = 0xFF; // Switched into sticky web user slot so reset it + for (i = 0; i < ARRAY_COUNT(gSideTimers); i++) + { + // Switched into sticky web user slot, so reset stored battler ID + if (gSideTimers[i].stickyWebBattlerId == gActiveBattler) + gSideTimers[i].stickyWebBattlerId = 0xFF; + } for (i = 0; i < gBattlersCount; i++) { @@ -3390,8 +3397,12 @@ void FaintClearSetData(void) gBattleStruct->palaceFlags &= ~(gBitTable[gActiveBattler]); - if (gActiveBattler == gBattleStruct->stickyWebUser) - gBattleStruct->stickyWebUser = 0xFF; // User of sticky web fainted, so reset the stored battler ID + for (i = 0; i < ARRAY_COUNT(gSideTimers); i++) + { + // User of sticky web fainted, so reset the stored battler ID + if (gSideTimers[i].stickyWebBattlerId == gActiveBattler) + gSideTimers[i].stickyWebBattlerId = 0xFF; + } for (i = 0; i < gBattlersCount; i++) { diff --git a/src/battle_message.c b/src/battle_message.c index 32c4d7b04..307b539a5 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -142,8 +142,8 @@ static const u8 sText_PkmnRaisedSpDefALittle[] = _("{B_ATK_PREFIX2}'s {B_CURRENT static const u8 sText_PkmnRaisedDef[] = _("{B_ATK_PREFIX2}'s {B_CURRENT_MOVE}\nraised DEFENSE!"); static const u8 sText_PkmnRaisedDefALittle[] = _("{B_ATK_PREFIX2}'s {B_CURRENT_MOVE}\nraised DEFENSE a little!"); static const u8 sText_PkmnCoveredByVeil[] = _("{B_ATK_PREFIX2}'s party is covered\nby a veil!"); -static const u8 sText_PkmnUsedSafeguard[] = _("{B_DEF_NAME_WITH_PREFIX}'s party is protected\nby SAFEGUARD!"); -static const u8 sText_PkmnSafeguardExpired[] = _("{B_ATK_PREFIX3}'s party is no longer\nprotected by SAFEGUARD!"); +static const u8 sText_PkmnUsedSafeguard[] = _("{B_DEF_NAME_WITH_PREFIX}'s party is protected\nby Safeguard!"); +static const u8 sText_PkmnSafeguardExpired[] = _("{B_ATK_PREFIX3}'s party is no longer\nprotected by Safeguard!"); static const u8 sText_PkmnWentToSleep[] = _("{B_ATK_NAME_WITH_PREFIX} went\nto sleep!"); static const u8 sText_PkmnSleptHealthy[] = _("{B_ATK_NAME_WITH_PREFIX} slept and\nbecame healthy!"); static const u8 sText_PkmnWhippedWhirlwind[] = _("{B_ATK_NAME_WITH_PREFIX} whipped\nup a whirlwind!"); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8b69e36fb..f1bb07281 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8760,8 +8760,9 @@ static bool32 IsTeatimeAffected(u32 battlerId) #define UPDATE_COURTCHANGED_BATTLER(structField)\ { \ - sideTimerPlayer->structField ^= BIT_SIDE; \ - sideTimerOpp->structField ^= BIT_SIDE; \ + temp = sideTimerPlayer->structField; \ + sideTimerPlayer->structField = BATTLE_OPPOSITE(sideTimerOpp->structField); \ + sideTimerOpp->structField = BATTLE_OPPOSITE(temp); \ } \ static bool32 CourtChangeSwapSideStatuses(void) @@ -8796,9 +8797,7 @@ static bool32 CourtChangeSwapSideStatuses(void) UPDATE_COURTCHANGED_BATTLER(auroraVeilBattlerId); UPDATE_COURTCHANGED_BATTLER(tailwindBattlerId); UPDATE_COURTCHANGED_BATTLER(luckyChantBattlerId); - - // For Mirror Armor only - gBattleStruct->stickyWebUser = gBattlerAttacker; + UPDATE_COURTCHANGED_BATTLER(stickyWebBattlerId); // Track which side originally set the Sticky Web SWAP(sideTimerPlayer->stickyWebBattlerSide, sideTimerOpp->stickyWebBattlerSide, temp); @@ -10830,8 +10829,8 @@ static void Cmd_various(void) // If Pokémon which set up Sticky Web is not on the field, no Pokémon have their Speed lowered." gBattlerAttacker = gBattlerTarget; // Initialize 'fail' condition SET_STATCHANGER(STAT_SPEED, 1, TRUE); - if (gBattleStruct->stickyWebUser != 0xFF) - gBattlerAttacker = gBattleStruct->stickyWebUser; + if (gSideTimers[GetBattlerSide(gActiveBattler)].stickyWebBattlerId != 0xFF) + gBattlerAttacker = gSideTimers[GetBattlerSide(gActiveBattler)].stickyWebBattlerId; break; } case VARIOUS_CUT_1_3_HP_RAISE_STATS: @@ -14092,9 +14091,9 @@ static void Cmd_setstickyweb(void) else { gSideStatuses[targetSide] |= SIDE_STATUS_STICKY_WEB; + gSideTimers[targetSide].stickyWebBattlerId = gBattlerAttacker; // For Mirror Armor gSideTimers[targetSide].stickyWebBattlerSide = GetBattlerSide(gBattlerAttacker); // For Court Change/Defiant - set this to the user's side gSideTimers[targetSide].stickyWebAmount = 1; - gBattleStruct->stickyWebUser = gBattlerAttacker; // For Mirror Armor gBattlescriptCurrInstr = cmd->nextInstr; } } diff --git a/test/ability_mirror_armor.c b/test/ability_mirror_armor.c new file mode 100644 index 000000000..7e15e029b --- /dev/null +++ b/test/ability_mirror_armor.c @@ -0,0 +1,202 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(P_GEN_8_POKEMON == TRUE); +} + +SINGLE_BATTLE_TEST("Mirror Armor lowers a stat of the attacking pokemon") +{ + u16 move, statId; + + PARAMETRIZE { move = MOVE_LEER; statId = STAT_DEF; } + PARAMETRIZE { move = MOVE_GROWL; statId = STAT_ATK; } + PARAMETRIZE { move = MOVE_SWEET_SCENT; statId = STAT_EVASION; } + PARAMETRIZE { move = MOVE_SAND_ATTACK; statId = STAT_ACC; } + PARAMETRIZE { move = MOVE_CONFIDE; statId = STAT_SPATK; } + PARAMETRIZE { move = MOVE_FAKE_TEARS; statId = STAT_SPDEF; } + + GIVEN { + PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR);} + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, move); } + } SCENE { + ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + switch (statId) + { + case STAT_DEF: + MESSAGE("Foe Wynaut's Defense fell!"); + break; + case STAT_ATK: + MESSAGE("Foe Wynaut's Attack fell!"); + break; + case STAT_EVASION: + MESSAGE("Foe Wynaut's evasiveness harshly fell!"); + break; + case STAT_ACC: + MESSAGE("Foe Wynaut's accuracy fell!"); + break; + case STAT_SPATK: + MESSAGE("Foe Wynaut's Sp. Atk fell!"); + break; + case STAT_SPDEF: + MESSAGE("Foe Wynaut's Sp. Def harshly fell!"); + break; + } + } THEN { + EXPECT_EQ(player->statStages[statId], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[statId], (statId == STAT_SPDEF || statId == STAT_EVASION) ? DEFAULT_STAT_STAGE - 2 : DEFAULT_STAT_STAGE - 1); + } +} + +SINGLE_BATTLE_TEST("Mirror Armor triggers even if the attacking Pokemon also has Mirror Armor ability") +{ + GIVEN { + PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + OPPONENT(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + } WHEN { + TURN { MOVE(opponent, MOVE_LEER); } + } SCENE { + MESSAGE("Foe Corviknigh used Leer!"); + ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Corviknigh's Defense fell!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE - 1); + } +} + +SINGLE_BATTLE_TEST("Mirror Armor doesn't lower the stats of an attacking Pokemon with the Clear Body ability") +{ + GIVEN { + PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + OPPONENT(SPECIES_WYNAUT) { Ability(ABILITY_CLEAR_BODY); } + } WHEN { + TURN { MOVE(opponent, MOVE_LEER); } + } SCENE { + MESSAGE("Foe Wynaut used Leer!"); + ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR); + ABILITY_POPUP(opponent, ABILITY_CLEAR_BODY); + MESSAGE("Foe Wynaut's Clear Body prevents stat loss!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Mirror Armor lowers the Attack of Pokemon with Intimidate") +{ + GIVEN { + PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + OPPONENT(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); } + } WHEN { + TURN {} + } SCENE { + ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); + ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Gyarados's Attack fell!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_ATK], DEFAULT_STAT_STAGE - 1); + } +} + +// Unsure whether this should or should not fail, as Showdown has conflicting information. Needs testing in gen8 games. +SINGLE_BATTLE_TEST("Mirror Armor doesn't lower the stats of an attacking Pokemon behind Substitute") +{ + KNOWN_FAILING; + GIVEN { + PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); } + TURN { MOVE(opponent, MOVE_LEER); } + } SCENE { + MESSAGE("Foe Wynaut used Substitute!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent); + MESSAGE("Foe Wynaut used Leer!"); + ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Mirror Armor raises the stat of an attacking Pokemon with Contrary") +{ + GIVEN { + PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR);} + OPPONENT(SPECIES_SHUCKLE) {Ability(ABILITY_CONTRARY);} + } WHEN { + TURN { MOVE(opponent, MOVE_LEER); } + } SCENE { + MESSAGE("Foe Shuckle used Leer!"); + ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Shuckle's Defense rose!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_DEF], DEFAULT_STAT_STAGE + 1); + } +} + +SINGLE_BATTLE_TEST("Mirror Armor doesn't lower the stat of the attacking Pokemon if it is already at -6") +{ + GIVEN { + PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR);} + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_SCREECH); } + TURN { MOVE(player, MOVE_SCREECH); } + TURN { MOVE(player, MOVE_SCREECH); } + TURN { MOVE(opponent, MOVE_LEER); } + } SCENE { + MESSAGE("Corviknigh used Screech!"); + MESSAGE("Corviknigh used Screech!"); + MESSAGE("Corviknigh used Screech!"); + MESSAGE("Foe Wynaut used Leer!"); + ABILITY_POPUP(player, ABILITY_MIRROR_ARMOR); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wynaut's Defense won't go lower!"); + } THEN { + EXPECT_EQ(player->statStages[STAT_DEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_DEF], MIN_STAT_STAGE); + } +} + +// This behaviour needs to be verified in the actual games. Currently it's written to follow Showdown's logic. +DOUBLE_BATTLE_TEST("Mirror Armor lowers Speed of the partner Pokemon after Court Change was used by the opponent after it set up Sticky Web") +{ + KNOWN_FAILING; + GIVEN { + ASSUME(gBattleMoves[MOVE_STICKY_WEB].effect == EFFECT_STICKY_WEB); + ASSUME(gBattleMoves[MOVE_COURT_CHANGE].effect == EFFECT_COURT_CHANGE); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR); Item(ITEM_IRON_BALL); } + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerLeft, MOVE_STICKY_WEB); } + TURN { MOVE(opponentLeft, MOVE_COURT_CHANGE); } + TURN { SWITCH(playerRight, 2);} + TURN { } + } SCENE { + MESSAGE("Wobbuffet used Sticky Web!"); + MESSAGE("Foe Wynaut used Court Change!"); + MESSAGE("Foe Wynaut swapped the battle effects affecting each side!"); + MESSAGE("Go! Corviknigh!"); + MESSAGE("Corviknigh was caught in a Sticky Web!"); + ABILITY_POPUP(playerRight, ABILITY_MIRROR_ARMOR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Wobbuffet's Speed fell!"); + } +} diff --git a/test/hold_effect_berserk_gene.c b/test/hold_effect_berserk_gene.c index 8a473e8da..981881e74 100644 --- a/test/hold_effect_berserk_gene.c +++ b/test/hold_effect_berserk_gene.c @@ -112,7 +112,7 @@ SINGLE_BATTLE_TEST("Berserk Gene does not confuse when Safeguard is active") } SCENE { ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); MESSAGE("Using Berserk Gene, the Attack of Wobbuffet sharply rose!"); - MESSAGE("Wobbuffet's party is protected by SAFEGUARD!"); + MESSAGE("Wobbuffet's party is protected by Safeguard!"); NOT MESSAGE("Wobbuffet became confused!"); } } diff --git a/test/move_effect_court_change.c b/test/move_effect_court_change.c new file mode 100644 index 000000000..9d03efddf --- /dev/null +++ b/test/move_effect_court_change.c @@ -0,0 +1,153 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_COURT_CHANGE].effect == EFFECT_COURT_CHANGE); +} + +DOUBLE_BATTLE_TEST("Court Change swaps entry hazards used by the opponent") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); MOVE(opponentRight, MOVE_STEALTH_ROCK); } + TURN { MOVE(opponentLeft, MOVE_SPIKES); MOVE(opponentRight, MOVE_TOXIC_SPIKES); } + TURN { MOVE(playerLeft, MOVE_COURT_CHANGE); } + TURN { SWITCH(playerLeft, 2); SWITCH(opponentLeft, 2); } + } SCENE { + MESSAGE("Foe Wobbuffet used Sticky Web!"); + MESSAGE("Foe Wobbuffet used Stealth Rock!"); + MESSAGE("Foe Wobbuffet used Spikes!"); + MESSAGE("Foe Wobbuffet used Toxic Spikes!"); + MESSAGE("Wynaut used Court Change!"); + MESSAGE("Wynaut swapped the battle effects affecting each side!"); + MESSAGE("Go! Wynaut!"); + NONE_OF { + MESSAGE("Wynaut is hurt by spikes!"); + MESSAGE("Pointed stones dug into Wynaut!"); + MESSAGE("Wynaut was poisoned!"); + MESSAGE("Wynaut was caught in a Sticky Web!"); + } + MESSAGE("2 sent out Wobbuffet!"); + MESSAGE("Foe Wobbuffet is hurt by spikes!"); + MESSAGE("Pointed stones dug into Foe Wobbuffet!"); + MESSAGE("Foe Wobbuffet was poisoned!"); + MESSAGE("Foe Wobbuffet was caught in a Sticky Web!"); + } +} + +DOUBLE_BATTLE_TEST("Court Change swaps entry hazards used by the player") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerLeft, MOVE_STICKY_WEB); MOVE(playerRight, MOVE_STEALTH_ROCK); } + TURN { MOVE(playerLeft, MOVE_SPIKES); MOVE(playerRight, MOVE_TOXIC_SPIKES); } + TURN { MOVE(opponentLeft, MOVE_COURT_CHANGE); } + TURN { SWITCH(opponentLeft, 2); SWITCH(playerLeft, 2); } + } SCENE { + MESSAGE("Wobbuffet used Sticky Web!"); + MESSAGE("Wobbuffet used Stealth Rock!"); + MESSAGE("Wobbuffet used Spikes!"); + MESSAGE("Wobbuffet used Toxic Spikes!"); + MESSAGE("Foe Wynaut used Court Change!"); + MESSAGE("Foe Wynaut swapped the battle effects affecting each side!"); + MESSAGE("Go! Wobbuffet!"); + MESSAGE("Wobbuffet is hurt by spikes!"); + MESSAGE("Pointed stones dug into Wobbuffet!"); + MESSAGE("Wobbuffet was poisoned!"); + MESSAGE("Wobbuffet was caught in a Sticky Web!"); + MESSAGE("2 sent out Wynaut!"); + NONE_OF { + MESSAGE("Foe Wynaut is hurt by spikes!"); + MESSAGE("Pointed stones dug into Foe Wynaut!"); + MESSAGE("Foe Wynaut was poisoned!"); + MESSAGE("Foe Wynaut was caught in a Sticky Web!"); + } + } +} + +DOUBLE_BATTLE_TEST("Court Change used by the player swaps Mist, Safeguard, Lucky Chant, Reflect, Light Screen, Tailwind") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentLeft, MOVE_MIST); MOVE(opponentRight, MOVE_SAFEGUARD); } + TURN { MOVE(opponentLeft, MOVE_LUCKY_CHANT); MOVE(opponentRight, MOVE_REFLECT); } + TURN { MOVE(opponentLeft, MOVE_LIGHT_SCREEN); MOVE(opponentRight, MOVE_TAILWIND); } + TURN { MOVE(playerLeft, MOVE_COURT_CHANGE); } + TURN { } + TURN { } + TURN { } + TURN { } + } SCENE { + MESSAGE("Foe Wobbuffet used Mist!"); + MESSAGE("Foe Wobbuffet used Safeguard!"); + MESSAGE("Foe Wobbuffet used Lucky Chant!"); + MESSAGE("Foe Wobbuffet used Reflect!"); + MESSAGE("Foe Wobbuffet used Light Screen!"); + MESSAGE("Foe Wobbuffet used Tailwind!"); + MESSAGE("Wynaut used Court Change!"); + MESSAGE("Wynaut swapped the battle effects affecting each side!"); + // The effects now end for the player side. + MESSAGE("Ally's Mist wore off!"); + MESSAGE("Ally's party is no longer protected by Safeguard!"); + MESSAGE("Ally's Reflect wore off!"); + MESSAGE("Your team's Lucky Chant wore off!"); + MESSAGE("Your team's tailwind petered out!"); + MESSAGE("Ally's Light Screen wore off!"); + } +} + +DOUBLE_BATTLE_TEST("Court Change used by the opponent swaps Mist, Safeguard, Lucky Chant, Reflect, Light Screen, Tailwind") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerLeft, MOVE_MIST); MOVE(playerRight, MOVE_SAFEGUARD); } + TURN { MOVE(playerLeft, MOVE_LUCKY_CHANT); MOVE(playerRight, MOVE_REFLECT); } + TURN { MOVE(playerLeft, MOVE_LIGHT_SCREEN); MOVE(playerRight, MOVE_TAILWIND); } + TURN { MOVE(opponentLeft, MOVE_COURT_CHANGE); } + TURN { } + TURN { } + TURN { } + TURN { } + } SCENE { + MESSAGE("Wobbuffet used Mist!"); + MESSAGE("Wobbuffet used Safeguard!"); + MESSAGE("Wobbuffet used Lucky Chant!"); + MESSAGE("Wobbuffet used Reflect!"); + MESSAGE("Wobbuffet used Light Screen!"); + MESSAGE("Wobbuffet used Tailwind!"); + MESSAGE("Foe Wynaut used Court Change!"); + MESSAGE("Foe Wynaut swapped the battle effects affecting each side!"); + // The effects now end for the player side. + MESSAGE("Foe's Mist wore off!"); + MESSAGE("Foe's party is no longer protected by Safeguard!"); + MESSAGE("Foe's Reflect wore off!"); + MESSAGE("The opposing team's Lucky Chant wore off!"); + MESSAGE("The opposing team's tailwind petered out!"); + MESSAGE("Foe's Light Screen wore off!"); + } +} diff --git a/test/move_effect_defog.c b/test/move_effect_defog.c index b55d5eab6..055f3f61a 100644 --- a/test/move_effect_defog.c +++ b/test/move_effect_defog.c @@ -125,7 +125,7 @@ DOUBLE_BATTLE_TEST("Defog lowers evasiveness by 1 and removes Mist and Safeguard STATUS_ICON(opponentRight, badPoison: TRUE); } else { - MESSAGE("Foe Wobbuffet's party is protected by SAFEGUARD!"); + MESSAGE("Foe Wobbuffet's party is protected by Safeguard!"); NOT STATUS_ICON(opponentRight, badPoison: TRUE); } } diff --git a/test/move_effect_sticky_web.c b/test/move_effect_sticky_web.c new file mode 100644 index 000000000..f0a6eb8d8 --- /dev/null +++ b/test/move_effect_sticky_web.c @@ -0,0 +1,237 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_STICKY_WEB].effect == EFFECT_STICKY_WEB); +} + +SINGLE_BATTLE_TEST("Sticky Web lowers Speed by 1 on switch-in") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_STICKY_WEB); } + TURN { SWITCH(opponent, 1); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player); + MESSAGE("A sticky web spreads out on the ground around the opposing team!"); + MESSAGE("2 sent out Wynaut!"); + MESSAGE("Foe Wynaut was caught in a Sticky Web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Wynaut's Speed fell!"); + } +} + +SINGLE_BATTLE_TEST("Sticky Web can only be set up 1 time") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_STICKY_WEB); } + TURN { MOVE(player, MOVE_STICKY_WEB); } + } SCENE { + MESSAGE("Wobbuffet used Sticky Web!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player); + MESSAGE("A sticky web spreads out on the ground around the opposing team!"); + + MESSAGE("Wobbuffet used Sticky Web!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player); + MESSAGE("But it failed!"); + } +} + + +DOUBLE_BATTLE_TEST("Sticky Web lowers Speed by 1 in a double battle after Explosion fainting both mons") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_EXPLOSION].effect == EFFECT_EXPLOSION); + PLAYER(SPECIES_WOBBUFFET) {Speed(5);} + PLAYER(SPECIES_WOBBUFFET) {HP(1500); Speed(10);} + PLAYER(SPECIES_WOBBUFFET) {Speed(10);} + OPPONENT(SPECIES_WOBBUFFET) {HP(1); Speed(1);} + OPPONENT(SPECIES_WOBBUFFET) {HP(1); Speed(1);} + OPPONENT(SPECIES_WYNAUT) {Speed(10);} + OPPONENT(SPECIES_WYNAUT) {Speed(10);} + } WHEN { + TURN { MOVE(playerRight, MOVE_STICKY_WEB); MOVE(playerLeft, MOVE_EXPLOSION); SEND_OUT(playerLeft, 2); SEND_OUT(opponentLeft, 2); SEND_OUT(opponentRight, 3); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, playerRight); + MESSAGE("A sticky web spreads out on the ground around the opposing team!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EXPLOSION, playerLeft); + MESSAGE("2 sent out Wynaut!"); + MESSAGE("Foe Wynaut was caught in a Sticky Web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("Foe Wynaut's Speed fell!"); + MESSAGE("2 sent out Wynaut!"); + MESSAGE("Foe Wynaut was caught in a Sticky Web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("Foe Wynaut's Speed fell!"); + } +} + +SINGLE_BATTLE_TEST("Sticky Web raises Speed by 1 for a Pokemon with Contrary") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SHUCKLE) { Ability(ABILITY_CONTRARY); } + } WHEN { + TURN { MOVE(player, MOVE_STICKY_WEB); } + TURN { SWITCH(opponent, 1); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, player); + MESSAGE("A sticky web spreads out on the ground around the opposing team!"); + MESSAGE("2 sent out Shuckle!"); + MESSAGE("Foe Shuckle was caught in a Sticky Web!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Shuckle's Speed rose!"); + } +} + +#define BATTLER_OPPONENT (opponentSetUpper == 0 ? opponentLeft : opponentRight) +#define BATTLER_PLAYER (playerSetUpper == 0 ? playerLeft : playerRight) + +DOUBLE_BATTLE_TEST("Sticky Web has correct interactions with Mirror Armor - the battler which set up Sticky Web has its Speed lowered instead") +{ + u8 playerSetUpper, opponentSetUpper; // 0 left, 1 right + + PARAMETRIZE {playerSetUpper = 0; opponentSetUpper = 0; } + PARAMETRIZE {playerSetUpper = 0; opponentSetUpper = 1; } + PARAMETRIZE {playerSetUpper = 1; opponentSetUpper = 0; } + PARAMETRIZE {playerSetUpper = 1; opponentSetUpper = 1; } + + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_SQUIRTLE); + PLAYER(SPECIES_CHARMANDER); + PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); Item(ITEM_IRON_BALL); } // Iron Ball, so that flying type Corviknight is affected by Sticky Web. + OPPONENT(SPECIES_CATERPIE); + OPPONENT(SPECIES_WEEDLE); + } WHEN { + TURN { MOVE(BATTLER_OPPONENT, MOVE_STICKY_WEB); } + TURN { MOVE(BATTLER_PLAYER, MOVE_STICKY_WEB); } + TURN { SWITCH(playerRight, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, BATTLER_OPPONENT); + MESSAGE("A sticky web spreads out on the ground around your team!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, BATTLER_PLAYER); + MESSAGE("A sticky web spreads out on the ground around the opposing team!"); + + MESSAGE("Go! Corviknigh!"); + MESSAGE("Corviknigh was caught in a Sticky Web!"); + ABILITY_POPUP(playerRight, ABILITY_MIRROR_ARMOR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, BATTLER_OPPONENT); + if (opponentSetUpper == 0) { + MESSAGE("Foe Caterpie's Speed fell!"); + } else { + MESSAGE("Foe Weedle's Speed fell!"); + } + } +} + +#undef BATTLER_OPPONENT +#undef BATTLER_PLAYER + +DOUBLE_BATTLE_TEST("Sticky Web has correct interactions with Mirror Armor - no one has their Speed lowered if the set upper switched") +{ + u16 speedPlayer, speedOpponent; + + // We need to make sure Sticky Web user saves for both sides, so it doesn't matter who sets it first. + PARAMETRIZE { speedPlayer = 5; speedOpponent = 10; } + PARAMETRIZE { speedPlayer = 10; speedOpponent = 5; } + + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + PLAYER(SPECIES_SQUIRTLE) { Speed(speedPlayer); } + PLAYER(SPECIES_CHARMANDER) { Speed(speedPlayer); } + PLAYER(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); Item(ITEM_IRON_BALL); Speed(speedOpponent); } // Iron Ball, so that flying type Corviknight is affected by Sticky Web. + OPPONENT(SPECIES_CATERPIE) { Speed(speedOpponent); } + OPPONENT(SPECIES_WEEDLE) { Speed(speedOpponent); } + OPPONENT(SPECIES_PIDGEY) { Speed(speedOpponent); } // Flying type,so not affected by Sticky Web. + } WHEN { + TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); MOVE(playerRight, MOVE_STICKY_WEB); } + TURN { SWITCH(opponentLeft, 2); } + TURN { SWITCH(playerRight, 2); } + } SCENE { + if (speedPlayer > speedOpponent) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, playerRight); + MESSAGE("A sticky web spreads out on the ground around the opposing team!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentLeft); + MESSAGE("A sticky web spreads out on the ground around your team!"); + } else { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentLeft); + MESSAGE("A sticky web spreads out on the ground around your team!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, playerRight); + MESSAGE("A sticky web spreads out on the ground around the opposing team!"); + } + + MESSAGE("Go! Corviknigh!"); + MESSAGE("Corviknigh was caught in a Sticky Web!"); + ABILITY_POPUP(playerRight, ABILITY_MIRROR_ARMOR); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(playerRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponentLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponentRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } +} + +DOUBLE_BATTLE_TEST("Sticky Web has correct interactions with Mirror Armor - no one has their Speed lowered if the set upper fainted") +{ + bool8 hasReplacement; + + // We need to make sure Sticky Web user saves for both sides, so it doesn't matter who sets it first. + PARAMETRIZE {hasReplacement = TRUE;} + PARAMETRIZE {hasReplacement = FALSE;} + + GIVEN { + ASSUME(P_GEN_8_POKEMON == TRUE); + ASSUME(gBattleMoves[MOVE_MEMENTO].effect == EFFECT_MEMENTO); + PLAYER(SPECIES_SQUIRTLE) {Speed(5); } + PLAYER(SPECIES_CHARMANDER) {Speed(5); } + PLAYER(SPECIES_CORVIKNIGHT) {Ability(ABILITY_MIRROR_ARMOR); Item(ITEM_IRON_BALL); Speed(5); } // Iron Ball, so that flying type Corviknight is affected by Sticky Web. + OPPONENT(SPECIES_CATERPIE) {Speed(7); } + OPPONENT(SPECIES_WEEDLE) {Speed(7); } + if (hasReplacement) { + OPPONENT(SPECIES_PIDGEY) {Speed(7); } + } + + } WHEN { + TURN { MOVE(opponentLeft, MOVE_STICKY_WEB); } + if (hasReplacement) { + TURN { MOVE(opponentLeft, MOVE_MEMENTO, target:playerLeft); SEND_OUT(opponentLeft, 2); } + } else { + TURN { MOVE(opponentLeft, MOVE_MEMENTO, target:playerLeft);} + } + TURN { SWITCH(playerRight, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_STICKY_WEB, opponentLeft); + MESSAGE("A sticky web spreads out on the ground around your team!"); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, opponentLeft); + MESSAGE("Foe Caterpie fainted!"); + if (hasReplacement) { + MESSAGE("2 sent out Pidgey!"); + } + + MESSAGE("Go! Corviknigh!"); + MESSAGE("Corviknigh was caught in a Sticky Web!"); + ABILITY_POPUP(playerRight, ABILITY_MIRROR_ARMOR); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + } THEN { + if (hasReplacement) { + EXPECT_EQ(opponentLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } + EXPECT_EQ(playerLeft->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(playerRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponentRight->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } +} From 42992ca5ce4b6da00ef98a2952a40547ef8ba71e Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 7 Aug 2023 17:23:12 +0200 Subject: [PATCH 24/34] Fix Teleport ending trainer battles (#3166) --- asm/macros/battle_script.inc | 17 +++++----- data/battle_scripts_1.s | 34 +++----------------- src/battle_script_commands.c | 34 -------------------- test/move_effect_teleport.c | 61 ++++++++++++++++++++++++++++++++++++ 4 files changed, 74 insertions(+), 72 deletions(-) create mode 100644 test/move_effect_teleport.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 9ba68ef05..93c747810 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1318,7 +1318,7 @@ .2byte \holdEffect .4byte \jumpInstr .endm - + .macro dostockpilestatchangeswearoff, battler:req, statChangeInstr:req callnative BS_DoStockpileStatChangesWearOff .byte \battler @@ -1354,7 +1354,7 @@ .macro setsnow callnative BS_SetSnow .endm - + .macro setzeffect callnative BS_SetZEffect .endm @@ -1364,12 +1364,6 @@ callnative BS_TrySymbiosis .endm - @ returns TRUE or FALSE to gBattleCommunication[0] - .macro canteleport battler:req - callnative BS_CanTeleport - .byte \battler - .endm - @ returns B_SIDE_x to gBattleCommunication[0] .macro getbattlerside battler:req callnative BS_GetBattlerSide @@ -2077,7 +2071,7 @@ .macro swapsidestatuses various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES .endm - + .macro swapstats stat:req various BS_ATTACKER, VARIOUS_SWAP_STATS .byte \stat @@ -2178,6 +2172,11 @@ jumpifbyte CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_NO_EFFECT, \jumpInstr .endm + .macro jumpifside battler:req, side:req, equalJumpInstr:req + getbattlerside \battler + jumpifbyte CMP_EQUAL, gBattleCommunication, \side, \equalJumpInstr + .endm + .macro jumpifbattletype flags:req, jumpInstr:req jumpifword CMP_COMMON_BITS, gBattleTypeFlags, \flags, \jumpInstr .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c707ef75f..0375c1325 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5401,15 +5401,14 @@ BattleScript_EffectHurricane: BattleScript_EffectTeleport: attackcanceler attackstring - ppreduce .if B_TELEPORT_BEHAVIOR >= GEN_7 - canteleport BS_ATTACKER - jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_EffectTeleportNew - goto BattleScript_ButItFailed + jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_EffectBatonPass + jumpifside BS_ATTACKER, B_SIDE_PLAYER, BattleScript_EffectBatonPass .else jumpifbattletype BATTLE_TYPE_TRAINER, BattleScript_ButItFailed .endif BattleScript_EffectTeleportTryToRunAway: + ppreduce getifcantrunfrombattle BS_ATTACKER jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FORBIDDEN, BattleScript_ButItFailed jumpifbyte CMP_EQUAL, gBattleCommunication, BATTLE_RUN_FAILURE, BattleScript_PrintAbilityMadeIneffective @@ -5420,29 +5419,6 @@ BattleScript_EffectTeleportTryToRunAway: setoutcomeonteleport BS_ATTACKER goto BattleScript_MoveEnd -BattleScript_EffectTeleportNew: - getbattlerside BS_ATTACKER - jumpifbyte CMP_EQUAL, gBattleCommunication, B_SIDE_OPPONENT, BattleScript_EffectTeleportTryToRunAway - attackanimation - waitanimation - openpartyscreen BS_ATTACKER, BattleScript_EffectTeleportNewEnd - switchoutabilities BS_ATTACKER - waitstate - switchhandleorder BS_ATTACKER, 2 - returntoball BS_ATTACKER - getswitchedmondata BS_ATTACKER - switchindataupdate BS_ATTACKER - hpthresholds BS_ATTACKER - trytoclearprimalweather - printstring STRINGID_EMPTYSTRING3 - waitmessage 1 - printstring STRINGID_SWITCHINMON - switchinanim BS_ATTACKER, TRUE - waitstate - switchineffects BS_ATTACKER -BattleScript_EffectTeleportNewEnd: - goto BattleScript_MoveEnd - BattleScript_EffectBeatUp:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE @@ -7897,7 +7873,7 @@ BattleScript_WishMegaEvolution:: BattleScript_PrimalReversion:: call BattleScript_PrimalReversionRet end2 - + BattleScript_PrimalReversionRestoreAttacker:: call BattleScript_PrimalReversionRet copybyte gBattlerAttacker, sSAVED_BATTLER @@ -8944,7 +8920,7 @@ BattleScript_BadDreams_ShowPopUp: goto BattleScript_BadDreams_DmgAfterPopUp BattleScript_BadDreams_HidePopUp: destroyabilitypopup - tryfaintmon BS_TARGET + tryfaintmon BS_TARGET goto BattleScript_BadDreamsIncrement BattleScript_TookAttack:: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f1bb07281..af222e6ba 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8837,33 +8837,6 @@ static void HandleScriptMegaPrimal(u32 caseId, u32 battlerId, bool32 isMega) } } -static bool32 CanTeleport(u8 battlerId) -{ - struct Pokemon *party = GetBattlerParty(battlerId); - u32 species, count, i; - - for (i = 0; i < PARTY_SIZE; i++) - { - species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); - if (species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(&party[i], MON_DATA_HP) != 0) - count++; - } - - switch (GetBattlerSide(battlerId)) - { - case B_SIDE_OPPONENT: - if (count == 1 || gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - return FALSE; - break; - case B_SIDE_PLAYER: - if (count == 1 || (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && count <= 2)) - return FALSE; - break; - } - - 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) { @@ -16327,13 +16300,6 @@ void BS_GetBattlerSide(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_CanTeleport(void) -{ - NATIVE_ARGS(u8 battler); - gBattleCommunication[0] = CanTeleport(cmd->battler); - gBattlescriptCurrInstr = cmd->nextInstr; -} - void BS_TrySymbiosis(void) { NATIVE_ARGS(); diff --git a/test/move_effect_teleport.c b/test/move_effect_teleport.c new file mode 100644 index 000000000..9c8a16d4b --- /dev/null +++ b/test/move_effect_teleport.c @@ -0,0 +1,61 @@ +#include "global.h" +#include "test_battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_TELEPORT].effect == EFFECT_TELEPORT); +} + +SINGLE_BATTLE_TEST("Teleport fails when there is no pokemon to switch in") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TELEPORT); } + } SCENE { + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Teleport fails when there no alive pokemon left") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT) { HP(0); } + } WHEN { + TURN { MOVE(opponent, MOVE_TELEPORT); } + } SCENE { + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Teleport forces the pokemon to switch out") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_TELEPORT); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TELEPORT, opponent); + MESSAGE("2 sent out Wynaut!"); + } +} + +SINGLE_BATTLE_TEST("Teleport does not fail if the user is trapped") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_FIRE_SPIN); MOVE(opponent, MOVE_TELEPORT); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_SPIN, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TELEPORT, opponent); + MESSAGE("2 sent out Wynaut!"); + } +} From f6e6a1f3839b82e547bc54c5163132927b3a3f15 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 9 Aug 2023 15:06:03 +0100 Subject: [PATCH 25/34] Initialize save to empty in test runner (#3215) --- test/test_runner.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/test_runner.c b/test/test_runner.c index d91ad02d1..3f1352e5a 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -2,6 +2,7 @@ #include "global.h" #include "characters.h" #include "gpu_regs.h" +#include "load_save.h" #include "main.h" #include "malloc.h" #include "random.h" @@ -114,6 +115,10 @@ void CB2_TestRunner(void) return; } + MoveSaveBlocks_ResetHeap(); + ClearSav1(); + ClearSav2(); + gIntrTable[7] = Intr_Timer2; // The current test restarted the ROM (e.g. by jumping to NULL). From bd7960ef211c0f3383785a40d7464e6c92cc518b Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Fri, 11 Aug 2023 12:04:03 -0400 Subject: [PATCH 26/34] Updated versions for issue templates (#3220) --- .github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 3 ++- .github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 3 ++- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index c4404a039..558f249e4 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.1 (Default) + - 1.5.2 (Default) - upcoming (Edge) + - 1.5.1 - 1.5.0 - 1.4.3 - 1.4.2 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index a24757fc7..157177dce 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.1 (Default) + - 1.5.2 (Default) - upcoming (Edge) + - 1.5.1 - 1.5.0 - 1.4.3 - 1.4.2 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index e25695c0b..a73096bab 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.1 (Default) + - 1.5.2 (Default) - upcoming (Edge) + - 1.5.1 - 1.5.0 - 1.4.3 - 1.4.2 From 1ba70a46f250672b0bdfd577cafde9c2c61a81f6 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Fri, 11 Aug 2023 17:26:43 -0400 Subject: [PATCH 27/34] Fixed Jump Kick's recoil not happening after Spiky Shield's damage (#3208) Co-authored-by: DizzyEggg --- data/battle_scripts_1.s | 2 ++ test/move_effect_recoil_if_miss.c | 47 +++++++++++++++++++++++++++++-- 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 0375c1325..5f38029a5 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4101,6 +4101,8 @@ BattleScript_MoveMissedDoDamage:: .if B_CRASH_IF_TARGET_IMMUNE < GEN_4 jumpifhalfword CMP_COMMON_BITS, gMoveResultFlags, MOVE_RESULT_DOESNT_AFFECT_FOE, BattleScript_MoveEnd .endif + moveendcase MOVEEND_PROTECT_LIKE_EFFECT @ Spiky Shield's damage happens before recoil. + jumpifhasnohp BS_ATTACKER, BattleScript_MoveEnd printstring STRINGID_PKMNCRASHED waitmessage B_WAIT_TIME_LONG damagecalc diff --git a/test/move_effect_recoil_if_miss.c b/test/move_effect_recoil_if_miss.c index 8a80309d7..51b5fe5e9 100644 --- a/test/move_effect_recoil_if_miss.c +++ b/test/move_effect_recoil_if_miss.c @@ -8,7 +8,6 @@ ASSUMPTIONS SINGLE_BATTLE_TEST("Jump Kick has 50% recoil on miss") { - s16 recoil; GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -25,7 +24,6 @@ SINGLE_BATTLE_TEST("Jump Kick has 50% recoil on miss") SINGLE_BATTLE_TEST("Jump Kick has 50% recoil on protect") { - s16 recoil; GIVEN { ASSUME(gBattleMoves[MOVE_JUMP_KICK].flags & FLAG_PROTECT_AFFECTED); PLAYER(SPECIES_WOBBUFFET); @@ -55,3 +53,48 @@ SINGLE_BATTLE_TEST("Jump Kick has no recoil if no target") NOT HP_BAR(player, damage: maxHP / 2); } } + +SINGLE_BATTLE_TEST("Jump Kick's recoil happens after Spiky Shield damage and Pokemon can faint from either of these") +{ + s16 hp, maxHp = 256; + bool32 faintOnSpiky = FALSE, faintOnJumpKick = FALSE; + + PARAMETRIZE { hp = maxHp; } + PARAMETRIZE { hp = maxHp / 2; faintOnJumpKick = TRUE; } // Faints after Jump Kick's recoil + PARAMETRIZE { hp = maxHp / 8; faintOnSpiky = TRUE; } // Faints after Spiky Shield's recoil + + GIVEN { + ASSUME(gBattleMoves[MOVE_SPIKY_SHIELD].effect == EFFECT_PROTECT); + PLAYER(SPECIES_WOBBUFFET) { HP(hp); MaxHP(maxHp); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (!faintOnJumpKick && !faintOnSpiky) { + TURN { MOVE(opponent, MOVE_SPIKY_SHIELD); MOVE(player, MOVE_JUMP_KICK, hit: FALSE); } + } else { + TURN { MOVE(opponent, MOVE_SPIKY_SHIELD); MOVE(player, MOVE_JUMP_KICK, hit: FALSE); SEND_OUT(player, 1); } + } + TURN { ; } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPIKY_SHIELD, opponent); + MESSAGE("Wobbuffet used Jump Kick!"); + MESSAGE("Foe Wobbuffet protected itself!"); + HP_BAR(player, damage: maxHp / 8); + MESSAGE("Wobbuffet was hurt by Foe Wobbuffet's Spiky Shield!"); + if (faintOnSpiky){ + MESSAGE("Wobbuffet fainted!"); + MESSAGE("Go! Wynaut!"); + NONE_OF { + MESSAGE("Wobbuffet kept going and crashed!"); + HP_BAR(player); + } + } else { + MESSAGE("Wobbuffet kept going and crashed!"); + HP_BAR(player); + if (faintOnJumpKick) { + MESSAGE("Wobbuffet fainted!"); + MESSAGE("Go! Wynaut!"); + } + } + } +} From ada29313de9959334a5aea75292538c769568890 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Fri, 11 Aug 2023 17:29:10 -0400 Subject: [PATCH 28/34] Fix for wild double battles with an in-game partner (#3210) Co-authored-by: DizzyEggg --- src/battle_controllers.c | 2 +- src/battle_main.c | 6 +++- src/battle_message.c | 2 +- src/battle_util.c | 66 +++++++++++++++++++++++---------------- src/script_pokemon_util.c | 0 5 files changed, 46 insertions(+), 30 deletions(-) mode change 100755 => 100644 src/script_pokemon_util.c diff --git a/src/battle_controllers.c b/src/battle_controllers.c index d5d3e479e..6424bee41 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -152,7 +152,7 @@ static void InitSinglePlayerBtlControllers(void) gBattlerPartyIndexes[0] = 0; gBattlerPartyIndexes[1] = 0; - if (BATTLE_TWO_VS_ONE_OPPONENT) + if (BATTLE_TWO_VS_ONE_OPPONENT || WILD_DOUBLE_BATTLE) { gBattlerPartyIndexes[2] = 3; gBattlerPartyIndexes[3] = 1; diff --git a/src/battle_main.c b/src/battle_main.c index 855e77017..25736731c 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4595,7 +4595,11 @@ static void HandleTurnActionSelectionState(void) { // if we choose to throw a ball with our second mon, skip the action of the first // (if we have chosen throw ball with first, second's is already skipped) - gChosenActionByBattler[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] = B_ACTION_NOTHING_FAINTED; + // if throwing a ball in a wild battle with an in-game partner, skip partner's turn when throwing a ball + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) + gChosenActionByBattler[GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT)] = B_ACTION_NOTHING_FAINTED; + else + gChosenActionByBattler[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)] = B_ACTION_NOTHING_FAINTED; } gBattleMainFunc = SetActionsAndBattlersTurnOrder; diff --git a/src/battle_message.c b/src/battle_message.c index 307b539a5..e0ebf9f1f 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -2698,7 +2698,7 @@ void BufferStringBattle(u16 stringID) { if (gBattleTypeFlags & BATTLE_TYPE_LEGENDARY) stringPtr = sText_LegendaryPkmnAppeared; - else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(gActiveBattler)]])) // interesting, looks like they had something planned for wild double battles + else if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE && IsValidForBattle(&gEnemyParty[gBattlerPartyIndexes[GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT)]])) stringPtr = sText_TwoWildPkmnAppeared; else if (gBattleTypeFlags & BATTLE_TYPE_WALLY_TUTORIAL) stringPtr = sText_WildPkmnAppearedPause; diff --git a/src/battle_util.c b/src/battle_util.c index 8f981fe3f..b5fb8732d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3877,14 +3877,15 @@ u8 AtkCanceller_UnableToUseMove2(void) bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) { - u8 playerId, flankId; + u32 i, side, playerId, flankId; struct Pokemon *party; - s32 i; if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) return FALSE; - if (BATTLE_TWO_VS_ONE_OPPONENT && GetBattlerSide(battler) == B_SIDE_OPPONENT) + side = GetBattlerSide(battler); + + if (BATTLE_TWO_VS_ONE_OPPONENT && side == B_SIDE_OPPONENT) { flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); @@ -3897,9 +3898,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) for (i = 0; i < PARTY_SIZE; i++) { - if (GetMonData(&party[i], MON_DATA_HP) != 0 - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG + if (IsValidForBattle(&party[i]) && i != partyIdBattlerOn1 && i != partyIdBattlerOn2 && i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId]) break; @@ -3909,22 +3908,41 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) else if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { party = GetBattlerParty(battler); - - playerId = ((battler & BIT_FLANK) / 2); - for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++) + if (side == B_SIDE_OPPONENT && WILD_DOUBLE_BATTLE) { - if (GetMonData(&party[i], MON_DATA_HP) != 0 - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG) - break; + flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); + playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); + + if (partyIdBattlerOn1 == PARTY_SIZE) + partyIdBattlerOn1 = gBattlerPartyIndexes[flankId]; + if (partyIdBattlerOn2 == PARTY_SIZE) + partyIdBattlerOn2 = gBattlerPartyIndexes[playerId]; + + for (i = 0; i < PARTY_SIZE; i++) + { + if (IsValidForBattle(&party[i]) + && i != partyIdBattlerOn1 && i != partyIdBattlerOn2 + && i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId]) + break; + } + return (i == PARTY_SIZE); + } + else + { + playerId = ((battler & BIT_FLANK) / 2); + for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++) + { + if (IsValidForBattle(&party[i])) + break; + } + return (i == playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE); } - return (i == playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE); } else if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { if (gBattleTypeFlags & BATTLE_TYPE_TOWER_LINK_MULTI) { - if (GetBattlerSide(battler) == B_SIDE_PLAYER) + if (side == B_SIDE_PLAYER) { party = gPlayerParty; flankId = GetBattlerMultiplayerId(battler); @@ -3948,14 +3966,12 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) for (i = playerId * MULTI_PARTY_SIZE; i < playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE; i++) { - if (GetMonData(&party[i], MON_DATA_HP) != 0 - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG) + if (IsValidForBattle(&party[i])) break; } return (i == playerId * MULTI_PARTY_SIZE + MULTI_PARTY_SIZE); } - else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && GetBattlerSide(battler) == B_SIDE_OPPONENT) + else if ((gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) && side == B_SIDE_OPPONENT) { party = gEnemyParty; @@ -3966,16 +3982,14 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) for (i = playerId; i < playerId + MULTI_PARTY_SIZE; i++) { - if (GetMonData(&party[i], MON_DATA_HP) != 0 - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG) + if (IsValidForBattle(&party[i])) break; } return (i == playerId + 3); } else { - if (GetBattlerSide(battler) == B_SIDE_OPPONENT) + if (side == B_SIDE_OPPONENT) { flankId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); playerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); @@ -3995,9 +4009,7 @@ bool8 HasNoMonsToSwitch(u8 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2) for (i = 0; i < PARTY_SIZE; i++) { - if (GetMonData(&party[i], MON_DATA_HP) != 0 - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_NONE - && GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG) != SPECIES_EGG + if (IsValidForBattle(&party[i]) && i != partyIdBattlerOn1 && i != partyIdBattlerOn2 && i != *(gBattleStruct->monToSwitchIntoId + flankId) && i != playerId[gBattleStruct->monToSwitchIntoId]) break; @@ -8000,7 +8012,7 @@ u8 IsMonDisobedient(void) if (IsBattlerModernFatefulEncounter(gBattlerAttacker)) // only false if illegal Mew or Deoxys { - if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gBattlerAttacker) == 2) + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gBattlerAttacker) == B_POSITION_PLAYER_RIGHT) return 0; if (gBattleTypeFlags & BATTLE_TYPE_FRONTIER) return 0; diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c old mode 100755 new mode 100644 From d62c0d6d51942afac048532f92f57d5e0746a72a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada D'Ottone Date: Sat, 12 Aug 2023 15:00:15 -0400 Subject: [PATCH 29/34] Organized tests into subfolders (#2822) --- Makefile | 2 +- test/test_battle.h => include/test/battle.h | 3 +- {test => include/test}/test.h | 0 .../ability/bad_dreams.c} | 2 +- .../ability/beads_of_ruin.c} | 2 +- .../ability/blaze.c} | 2 +- .../ability/clear_body.c} | 2 +- .../ability/cloud_nine.c} | 2 +- .../ability/compound_eyes.c} | 2 +- .../ability/contrary.c} | 2 +- .../ability/cute_charm.c} | 2 +- .../{ability_damp.c => battle/ability/damp.c} | 2 +- .../ability/desolate_land.c} | 62 +----- .../ability/download.c} | 2 +- .../ability/drizzle.c} | 2 +- .../ability/dry_skin.c} | 2 +- .../ability/electromorphosis.c} | 2 +- .../ability/flame_body.c} | 2 +- .../ability/flower_gift.c} | 2 +- .../ability/forecast.c} | 2 +- .../ability/full_metal_body.c} | 2 +- .../ability/hunger_switch.c} | 2 +- .../ability/hydration.c} | 2 +- .../ability/hyper_cutter.c} | 2 +- .../ability/ice_body.c} | 2 +- .../ability/immunity.c} | 2 +- .../ability/inner_focus.c} | 2 +- .../ability/insomnia.c} | 2 +- .../ability/intimidate.c} | 2 +- .../ability/leaf_guard.c} | 2 +- .../ability/limber.c} | 2 +- .../ability/magic_bounce.c} | 2 +- .../ability/mirror_armor.c} | 2 +- .../ability/oblivious.c} | 2 +- test/battle/ability/overcoat.c | 21 ++ .../ability/overgrow.c} | 2 +- .../ability/own_tempo.c} | 2 +- .../ability/pastel_veil.c} | 2 +- .../ability/poison_point.c} | 2 +- test/battle/ability/primordial_sea.c | 66 ++++++ .../ability/protosynthesis.c} | 2 +- .../ability/quark_drive.c} | 2 +- .../ability/rain_dish.c} | 2 +- .../ability/rattled.c} | 2 +- .../ability/sand_veil.c} | 2 +- .../ability/schooling.c} | 2 +- .../ability/scrappy.c} | 2 +- .../ability/snow_cloak.c} | 2 +- .../ability/snow_warning.c} | 2 +- .../ability/speed_boost.c} | 2 +- .../ability/stamina.c} | 2 +- .../ability/static.c} | 2 +- .../ability/stench.c} | 2 +- .../ability/sturdy.c} | 2 +- .../ability/swarm.c} | 2 +- .../ability/sword_of_ruin.c} | 2 +- .../ability/tablets_of_ruin.c} | 2 +- .../ability/torrent.c} | 2 +- .../ability/vessel_of_ruin.c} | 2 +- .../ability/volt_absorb.c} | 2 +- .../ability/water_absorb.c} | 2 +- .../ability/white_smoke.c} | 2 +- .../ability/wind_power.c} | 2 +- .../ability/zen_mode.c} | 2 +- test/battle/form_change/battle_switch.c | 23 +++ .../form_change/begin_battle.c} | 40 +--- test/battle/form_change/faint.c | 19 ++ .../{ => battle/form_change}/mega_evolution.c | 2 +- .../form_change}/primal_reversion.c | 2 +- .../hold_effect/air_balloon.c} | 2 +- .../hold_effect/berserk_gene.c} | 2 +- .../hold_effect/clear_amulet.c} | 2 +- .../hold_effect/eject_button.c} | 2 +- .../hold_effect/gems.c} | 2 +- .../hold_effect/leftovers.c} | 2 +- .../hold_effect/mirror_herb.c} | 2 +- .../hold_effect/red_card.c} | 2 +- test/battle/hold_effect/safety_goggles.c | 26 +++ .../hold_effect/utility_umbrella.c} | 2 +- .../item_effect/cure_status.c} | 2 +- .../item_effect/heal_and_cure_status.c} | 2 +- .../item_effect/increase_stat.c} | 2 +- .../item_effect/restore_hp.c} | 2 +- .../item_effect/restore_pp.c} | 2 +- .../item_effect/revive.c} | 2 +- .../item_effect/set_focus_energy.c} | 2 +- .../item_effect/set_mist.c} | 2 +- test/{ => battle}/move.c | 2 +- .../move_effect/absorb.c} | 2 +- .../move_effect/accuracy_down.c} | 2 +- .../move_effect/after_you.c} | 2 +- .../move_effect/assist.c} | 2 +- .../move_effect/attack_down.c} | 2 +- .../move_effect/attack_up.c} | 2 +- .../move_effect/attack_up_user_ally.c} | 2 +- .../move_effect/barb_barrage.c} | 2 +- .../move_effect/beak_blast.c} | 2 +- .../move_effect/bide.c} | 2 +- .../move_effect/burn_hit.c} | 2 +- .../move_effect/burn_up.c} | 2 +- .../move_effect/court_change.c} | 2 +- .../move_effect/defense_down.c} | 2 +- .../move_effect/defense_up.c} | 2 +- .../move_effect/defog.c} | 2 +- .../move_effect/dire_claw.c} | 2 +- .../move_effect/double_shock.c} | 2 +- .../move_effect/dream_eater.c} | 2 +- .../move_effect/encore.c} | 2 +- .../move_effect/evasion_up.c} | 2 +- .../move_effect/explosion.c} | 2 +- .../move_effect/focus_punch.c} | 2 +- .../move_effect/freeze_hit.c} | 2 +- .../move_effect/haze.c} | 2 +- .../move_effect/healing_wish.c} | 2 +- .../move_effect/hex.c} | 2 +- .../move_effect/hit_escape.c} | 2 +- .../move_effect/hit_set_entry_hazardss.c} | 2 +- .../move_effect/hit_switch_target.c} | 2 +- .../move_effect/hydro_steam.c} | 2 +- .../move_effect/metronome.c} | 2 +- .../move_effect/mind_blown.c} | 2 +- .../move_effect/mirror_move.c} | 2 +- .../move_effect/paralyze_hit.c} | 2 +- .../move_effect/poison_hit.c} | 2 +- .../move_effect/rampage.c} | 2 +- .../move_effect/recoil_if_miss.c} | 2 +- .../move_effect/reflect.c} | 2 +- .../move_effect/revival_blessing.c} | 2 +- .../move_effect/roar.c} | 2 +- .../move_effect/shell_trap.c} | 2 +- .../move_effect/sleep.c} | 2 +- .../move_effect/special_attack_down.c} | 2 +- .../move_effect/special_attack_up_3.c} | 2 +- .../move_effect/spikes.c} | 2 +- .../move_effect/sticky_web.c} | 2 +- .../move_effect/stockpile.c} | 2 +- .../move_effect/tailwind.c} | 2 +- .../move_effect/teleport.c} | 2 +- .../move_effect/torment.c} | 2 +- .../move_effect/toxic.c} | 2 +- .../move_effect/toxic_spikes.c} | 2 +- .../move_effect/tri_attack.c} | 2 +- .../move_effect/triple_kick.c} | 2 +- .../move_effect/venoshock.c} | 2 +- .../move_flags/three_strikes.c} | 2 +- test/battle/status1/bad_poison.c | 39 ++++ test/battle/status1/burn.c | 35 ++++ test/battle/status1/freeze.c | 45 ++++ .../status1/frostbite.c} | 2 +- test/battle/status1/paralysis.c | 44 ++++ test/battle/status1/poison.c | 17 ++ test/battle/status1/sleep.c | 23 +++ .../terrain/electric.c} | 2 +- .../terrain/grassy.c} | 2 +- .../terrain/misty.c} | 2 +- .../terrain/psychic.c} | 2 +- test/{ => battle}/trainer_control.c | 2 +- test/battle/type/grass.c | 17 ++ .../{weather_rain.c => battle/weather/rain.c} | 2 +- .../{weather_snow.c => battle/weather/snow.c} | 2 +- .../weather/sunlight.c} | 2 +- test/powder_moves.c | 47 ----- test/random.c | 2 +- test/status1.c | 193 ------------------ test/test_runner.c | 2 +- test/test_runner_battle.c | 2 +- 166 files changed, 527 insertions(+), 489 deletions(-) rename test/test_battle.h => include/test/battle.h (99%) rename {test => include/test}/test.h (100%) rename test/{ability_bad_dreams.c => battle/ability/bad_dreams.c} (99%) rename test/{ability_beads_of_ruin.c => battle/ability/beads_of_ruin.c} (98%) rename test/{ability_blaze.c => battle/ability/blaze.c} (95%) rename test/{ability_clear_body.c => battle/ability/clear_body.c} (98%) rename test/{ability_cloud_nine.c => battle/ability/cloud_nine.c} (94%) rename test/{ability_compound_eyes.c => battle/ability/compound_eyes.c} (97%) rename test/{ability_contrary.c => battle/ability/contrary.c} (99%) rename test/{ability_cute_charm.c => battle/ability/cute_charm.c} (98%) rename test/{ability_damp.c => battle/ability/damp.c} (98%) rename test/{primal_weather.c => battle/ability/desolate_land.c} (51%) rename test/{ability_download.c => battle/ability/download.c} (99%) rename test/{ability_drizzle.c => battle/ability/drizzle.c} (96%) rename test/{ability_dry_skin.c => battle/ability/dry_skin.c} (99%) rename test/{ability_electromorphosis.c => battle/ability/electromorphosis.c} (98%) rename test/{ability_flame_body.c => battle/ability/flame_body.c} (97%) rename test/{ability_flower_gift.c => battle/ability/flower_gift.c} (99%) rename test/{ability_forecast.c => battle/ability/forecast.c} (99%) rename test/{ability_full_metal_body.c => battle/ability/full_metal_body.c} (98%) rename test/{ability_hunger_switch.c => battle/ability/hunger_switch.c} (96%) rename test/{ability_hydration.c => battle/ability/hydration.c} (95%) rename test/{ability_hyper_cutter.c => battle/ability/hyper_cutter.c} (98%) rename test/{ability_ice_body.c => battle/ability/ice_body.c} (96%) rename test/{ability_immunity.c => battle/ability/immunity.c} (98%) rename test/{ability_inner_focus.c => battle/ability/inner_focus.c} (98%) rename test/{ability_insomnia.c => battle/ability/insomnia.c} (98%) rename test/{ability_intimidate.c => battle/ability/intimidate.c} (99%) rename test/{ability_leaf_guard.c => battle/ability/leaf_guard.c} (99%) rename test/{ability_limber.c => battle/ability/limber.c} (94%) rename test/{ability_magic_bounce.c => battle/ability/magic_bounce.c} (99%) rename test/{ability_mirror_armor.c => battle/ability/mirror_armor.c} (99%) rename test/{ability_oblivious.c => battle/ability/oblivious.c} (98%) create mode 100644 test/battle/ability/overcoat.c rename test/{ability_overgrow.c => battle/ability/overgrow.c} (96%) rename test/{ability_own_tempo.c => battle/ability/own_tempo.c} (99%) rename test/{ability_pastel_veil.c => battle/ability/pastel_veil.c} (99%) rename test/{ability_poison_point.c => battle/ability/poison_point.c} (97%) create mode 100644 test/battle/ability/primordial_sea.c rename test/{ability_protosynthesis.c => battle/ability/protosynthesis.c} (99%) rename test/{ability_quark_drive.c => battle/ability/quark_drive.c} (99%) rename test/{ability_rain_dish.c => battle/ability/rain_dish.c} (94%) rename test/{ability_rattled.c => battle/ability/rattled.c} (99%) rename test/{ability_sand_veil.c => battle/ability/sand_veil.c} (96%) rename test/{ability_schooling.c => battle/ability/schooling.c} (99%) rename test/{ability_scrappy.c => battle/ability/scrappy.c} (98%) rename test/{ability_snow_cloak.c => battle/ability/snow_cloak.c} (96%) rename test/{ability_snow_warning.c => battle/ability/snow_warning.c} (96%) rename test/{ability_speed_boost.c => battle/ability/speed_boost.c} (96%) rename test/{ability_stamina.c => battle/ability/stamina.c} (99%) rename test/{ability_static.c => battle/ability/static.c} (97%) rename test/{ability_stench.c => battle/ability/stench.c} (97%) rename test/{ability_sturdy.c => battle/ability/sturdy.c} (98%) rename test/{ability_swarm.c => battle/ability/swarm.c} (95%) rename test/{ability_sword_of_ruin.c => battle/ability/sword_of_ruin.c} (98%) rename test/{ability_tablets_of_ruin.c => battle/ability/tablets_of_ruin.c} (98%) rename test/{ability_torrent.c => battle/ability/torrent.c} (95%) rename test/{ability_vessel_of_ruin.c => battle/ability/vessel_of_ruin.c} (98%) rename test/{ability_volt_absorb.c => battle/ability/volt_absorb.c} (99%) rename test/{ability_water_absorb.c => battle/ability/water_absorb.c} (99%) rename test/{ability_white_smoke.c => battle/ability/white_smoke.c} (98%) rename test/{ability_wind_power.c => battle/ability/wind_power.c} (99%) rename test/{ability_zen_mode.c => battle/ability/zen_mode.c} (99%) create mode 100644 test/battle/form_change/battle_switch.c rename test/{form_change.c => battle/form_change/begin_battle.c} (68%) create mode 100644 test/battle/form_change/faint.c rename test/{ => battle/form_change}/mega_evolution.c (99%) rename test/{ => battle/form_change}/primal_reversion.c (99%) rename test/{hold_effect_air_balloon.c => battle/hold_effect/air_balloon.c} (99%) rename test/{hold_effect_berserk_gene.c => battle/hold_effect/berserk_gene.c} (99%) rename test/{hold_effect_clear_amulet.c => battle/hold_effect/clear_amulet.c} (99%) rename test/{hold_effect_eject_button.c => battle/hold_effect/eject_button.c} (99%) rename test/{hold_effect_gems.c => battle/hold_effect/gems.c} (99%) rename test/{hold_effect_leftovers.c => battle/hold_effect/leftovers.c} (98%) rename test/{hold_effect_mirror_herb.c => battle/hold_effect/mirror_herb.c} (98%) rename test/{hold_effect_red_card.c => battle/hold_effect/red_card.c} (99%) create mode 100644 test/battle/hold_effect/safety_goggles.c rename test/{hold_effect_utility_umbrella.c => battle/hold_effect/utility_umbrella.c} (99%) rename test/{item_effect_cure_status.c => battle/item_effect/cure_status.c} (99%) rename test/{item_effect_heal_and_cure_status.c => battle/item_effect/heal_and_cure_status.c} (98%) rename test/{item_effect_increase_stat.c => battle/item_effect/increase_stat.c} (99%) rename test/{item_effect_restore_hp.c => battle/item_effect/restore_hp.c} (98%) rename test/{item_effect_restore_pp.c => battle/item_effect/restore_pp.c} (98%) rename test/{item_effect_revive.c => battle/item_effect/revive.c} (98%) rename test/{item_effect_set_focus_energy.c => battle/item_effect/set_focus_energy.c} (96%) rename test/{item_effect_set_mist.c => battle/item_effect/set_mist.c} (96%) rename test/{ => battle}/move.c (99%) rename test/{move_effect_absorb.c => battle/move_effect/absorb.c} (97%) rename test/{move_effect_accuracy_down.c => battle/move_effect/accuracy_down.c} (96%) rename test/{move_effect_after_you.c => battle/move_effect/after_you.c} (98%) rename test/{move_effect_assist.c => battle/move_effect/assist.c} (96%) rename test/{move_effect_attack_down.c => battle/move_effect/attack_down.c} (97%) rename test/{move_effect_attack_up.c => battle/move_effect/attack_up.c} (97%) rename test/{move_effect_attack_up_user_ally.c => battle/move_effect/attack_up_user_ally.c} (99%) rename test/{move_effect_barb_barrage.c => battle/move_effect/barb_barrage.c} (98%) rename test/{move_effect_beak_blast.c => battle/move_effect/beak_blast.c} (99%) rename test/{move_effect_bide.c => battle/move_effect/bide.c} (97%) rename test/{move_effect_burn_hit.c => battle/move_effect/burn_hit.c} (97%) rename test/{move_effect_burn_up.c => battle/move_effect/burn_up.c} (98%) rename test/{move_effect_court_change.c => battle/move_effect/court_change.c} (99%) rename test/{move_effect_defense_down.c => battle/move_effect/defense_down.c} (97%) rename test/{move_effect_defense_up.c => battle/move_effect/defense_up.c} (97%) rename test/{move_effect_defog.c => battle/move_effect/defog.c} (99%) rename test/{move_effect_dire_claw.c => battle/move_effect/dire_claw.c} (99%) rename test/{move_effect_double_shock.c => battle/move_effect/double_shock.c} (98%) rename test/{move_effect_dream_eater.c => battle/move_effect/dream_eater.c} (98%) rename test/{move_effect_encore.c => battle/move_effect/encore.c} (98%) rename test/{move_effect_evasion_up.c => battle/move_effect/evasion_up.c} (96%) rename test/{move_effect_explosion.c => battle/move_effect/explosion.c} (99%) rename test/{move_effect_focus_punch.c => battle/move_effect/focus_punch.c} (99%) rename test/{move_effect_freeze_hit.c => battle/move_effect/freeze_hit.c} (97%) rename test/{move_effect_haze.c => battle/move_effect/haze.c} (97%) rename test/{move_effect_healing_wish.c => battle/move_effect/healing_wish.c} (99%) rename test/{move_effect_hex.c => battle/move_effect/hex.c} (97%) rename test/{move_effect_hit_escape.c => battle/move_effect/hit_escape.c} (99%) rename test/{move_effect_hit_set_entry_hazardss.c => battle/move_effect/hit_set_entry_hazardss.c} (99%) rename test/{move_effect_hit_switch_target.c => battle/move_effect/hit_switch_target.c} (98%) rename test/{move_effect_hydro_steam.c => battle/move_effect/hydro_steam.c} (98%) rename test/{move_effect_metronome.c => battle/move_effect/metronome.c} (98%) rename test/{move_effect_mind_blown.c => battle/move_effect/mind_blown.c} (99%) rename test/{move_effect_mirror_move.c => battle/move_effect/mirror_move.c} (99%) rename test/{move_effect_paralyze_hit.c => battle/move_effect/paralyze_hit.c} (97%) rename test/{move_effect_poison_hit.c => battle/move_effect/poison_hit.c} (97%) rename test/{move_effect_rampage.c => battle/move_effect/rampage.c} (99%) rename test/{move_effect_recoil_if_miss.c => battle/move_effect/recoil_if_miss.c} (99%) rename test/{move_effect_reflect.c => battle/move_effect/reflect.c} (99%) rename test/{move_effect_revival_blessing.c => battle/move_effect/revival_blessing.c} (99%) rename test/{move_effect_roar.c => battle/move_effect/roar.c} (98%) rename test/{move_effect_shell_trap.c => battle/move_effect/shell_trap.c} (99%) rename test/{move_effect_sleep.c => battle/move_effect/sleep.c} (97%) rename test/{move_effect_special_attack_down.c => battle/move_effect/special_attack_down.c} (97%) rename test/{move_effect_special_attack_up_3.c => battle/move_effect/special_attack_up_3.c} (97%) rename test/{move_effect_spikes.c => battle/move_effect/spikes.c} (99%) rename test/{move_effect_sticky_web.c => battle/move_effect/sticky_web.c} (99%) rename test/{move_effect_stockpile.c => battle/move_effect/stockpile.c} (99%) rename test/{move_effect_tailwind.c => battle/move_effect/tailwind.c} (98%) rename test/{move_effect_teleport.c => battle/move_effect/teleport.c} (98%) rename test/{move_effect_torment.c => battle/move_effect/torment.c} (98%) rename test/{move_effect_toxic.c => battle/move_effect/toxic.c} (98%) rename test/{move_effect_toxic_spikes.c => battle/move_effect/toxic_spikes.c} (99%) rename test/{move_effect_tri_attack.c => battle/move_effect/tri_attack.c} (99%) rename test/{move_effect_triple_kick.c => battle/move_effect/triple_kick.c} (97%) rename test/{move_effect_venoshock.c => battle/move_effect/venoshock.c} (97%) rename test/{move_flag_three_strikes.c => battle/move_flags/three_strikes.c} (98%) create mode 100644 test/battle/status1/bad_poison.c create mode 100644 test/battle/status1/burn.c create mode 100644 test/battle/status1/freeze.c rename test/{status_frostbite.c => battle/status1/frostbite.c} (99%) create mode 100644 test/battle/status1/paralysis.c create mode 100644 test/battle/status1/poison.c create mode 100644 test/battle/status1/sleep.c rename test/{terrain_electric.c => battle/terrain/electric.c} (99%) rename test/{terrain_grassy.c => battle/terrain/grassy.c} (99%) rename test/{terrain_misty.c => battle/terrain/misty.c} (99%) rename test/{terrain_psychic.c => battle/terrain/psychic.c} (99%) rename test/{ => battle}/trainer_control.c (99%) create mode 100644 test/battle/type/grass.c rename test/{weather_rain.c => battle/weather/rain.c} (98%) rename test/{weather_snow.c => battle/weather/snow.c} (99%) rename test/{weather_sunlight.c => battle/weather/sunlight.c} (98%) delete mode 100644 test/powder_moves.c delete mode 100644 test/status1.c diff --git a/Makefile b/Makefile index c4964e42e..79ed8f160 100644 --- a/Makefile +++ b/Makefile @@ -450,7 +450,7 @@ $(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt # NOTE: Based on C_DEP above, but without NODEP and KEEP_TEMPS handling. define TEST_DEP -$1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib -I test $2) +$1: $2 $$(shell $(SCANINC) -I include -I tools/agbcc/include -I gflib $2) @echo "$$(CC1) -o $$@ $$<" @$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ - endef diff --git a/test/test_battle.h b/include/test/battle.h similarity index 99% rename from test/test_battle.h rename to include/test/battle.h index b4f38ed91..dc40a8a20 100644 --- a/test/test_battle.h +++ b/include/test/battle.h @@ -447,13 +447,13 @@ #ifndef GUARD_TEST_BATTLE_H #define GUARD_TEST_BATTLE_H +#include "global.h" #include "battle.h" #include "battle_anim.h" #include "data.h" #include "item.h" #include "random.h" #include "recorded_battle.h" -#include "test.h" #include "util.h" #include "constants/abilities.h" #include "constants/battle_anim.h" @@ -462,6 +462,7 @@ #include "constants/items.h" #include "constants/moves.h" #include "constants/species.h" +#include "test/test.h" // NOTE: If the stack is too small the test runner will probably crash // or loop. diff --git a/test/test.h b/include/test/test.h similarity index 100% rename from test/test.h rename to include/test/test.h diff --git a/test/ability_bad_dreams.c b/test/battle/ability/bad_dreams.c similarity index 99% rename from test/ability_bad_dreams.c rename to test/battle/ability/bad_dreams.c index 9bf800534..42ac3f04a 100644 --- a/test/ability_bad_dreams.c +++ b/test/battle/ability/bad_dreams.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_beads_of_ruin.c b/test/battle/ability/beads_of_ruin.c similarity index 98% rename from test/ability_beads_of_ruin.c rename to test/battle/ability/beads_of_ruin.c index 28b39a430..1c6f740e8 100644 --- a/test/ability_beads_of_ruin.c +++ b/test/battle/ability/beads_of_ruin.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_blaze.c b/test/battle/ability/blaze.c similarity index 95% rename from test/ability_blaze.c rename to test/battle/ability/blaze.c index 1e12c6b29..12ccced93 100644 --- a/test/ability_blaze.c +++ b/test/battle/ability/blaze.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Blaze boosts Fire-type moves in a pinch", s16 damage) { diff --git a/test/ability_clear_body.c b/test/battle/ability/clear_body.c similarity index 98% rename from test/ability_clear_body.c rename to test/battle/ability/clear_body.c index 11789aaf6..7f167c9fe 100644 --- a/test/ability_clear_body.c +++ b/test/battle/ability/clear_body.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Clear Body prevents intimidate") { diff --git a/test/ability_cloud_nine.c b/test/battle/ability/cloud_nine.c similarity index 94% rename from test/ability_cloud_nine.c rename to test/battle/ability/cloud_nine.c index 02da15ee1..e8de0fd8a 100644 --- a/test/ability_cloud_nine.c +++ b/test/battle/ability/cloud_nine.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Cloud Nine prevents weather effects") { diff --git a/test/ability_compound_eyes.c b/test/battle/ability/compound_eyes.c similarity index 97% rename from test/ability_compound_eyes.c rename to test/battle/ability/compound_eyes.c index 6bdb15fa7..cc005943b 100644 --- a/test/ability_compound_eyes.c +++ b/test/battle/ability/compound_eyes.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Compound Eyes raises accuracy") { diff --git a/test/ability_contrary.c b/test/battle/ability/contrary.c similarity index 99% rename from test/ability_contrary.c rename to test/battle/ability/contrary.c index 52347f379..de4093716 100644 --- a/test/ability_contrary.c +++ b/test/battle/ability/contrary.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_cute_charm.c b/test/battle/ability/cute_charm.c similarity index 98% rename from test/ability_cute_charm.c rename to test/battle/ability/cute_charm.c index ccf5c490b..1a55fc359 100644 --- a/test/ability_cute_charm.c +++ b/test/battle/ability/cute_charm.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Cute Charm inflicts infatuation on contact") { diff --git a/test/ability_damp.c b/test/battle/ability/damp.c similarity index 98% rename from test/ability_damp.c rename to test/battle/ability/damp.c index 19a4ac5ad..ce53db112 100644 --- a/test/ability_damp.c +++ b/test/battle/ability/damp.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Damp prevents explosion-like moves from enemies") { diff --git a/test/primal_weather.c b/test/battle/ability/desolate_land.c similarity index 51% rename from test/primal_weather.c rename to test/battle/ability/desolate_land.c index 650a79921..ca52c9cd6 100644 --- a/test/primal_weather.c +++ b/test/battle/ability/desolate_land.c @@ -1,72 +1,12 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { - ASSUME(gBattleMoves[MOVE_EMBER].power != 0); - ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); ASSUME(gBattleMoves[MOVE_WATER_GUN].power != 0); ASSUME(gBattleMoves[MOVE_WATER_GUN].type == TYPE_WATER); } -SINGLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves") -{ - GIVEN { - PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);} - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, MOVE_EMBER); } - TURN { MOVE(opponent, MOVE_EMBER); } - } SCENE { - MESSAGE("Foe Wobbuffet used Ember!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); - MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); - NOT HP_BAR(player); - MESSAGE("Foe Wobbuffet used Ember!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); - MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); - NOT HP_BAR(player); - } THEN { - EXPECT_EQ(player->hp, player->maxHP); - } -} - -DOUBLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves and prints the message only once with moves hitting multiple targets") -{ - GIVEN { - ASSUME(gBattleMoves[MOVE_ERUPTION].power != 0); - ASSUME(gBattleMoves[MOVE_ERUPTION].type == TYPE_FIRE); - ASSUME(gBattleMoves[MOVE_ERUPTION].target == MOVE_TARGET_BOTH); - PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB); {Speed(5);}} - PLAYER(SPECIES_WOBBUFFET) {Speed(5);} - OPPONENT(SPECIES_WOBBUFFET) {Speed(10);} - OPPONENT(SPECIES_WOBBUFFET) {Speed(8);} - } WHEN { - TURN { MOVE(opponentLeft, MOVE_ERUPTION); } - } SCENE { - MESSAGE("Foe Wobbuffet used Eruption!"); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ERUPTION, opponentLeft); - MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); - NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); - } THEN { - EXPECT_EQ(playerLeft->hp, playerLeft->maxHP); - EXPECT_EQ(playerRight->hp, playerRight->maxHP); - } -} - -SINGLE_BATTLE_TEST("Primordial Sea does not block a move if pokemon is asleep and uses a Fire-type move") // Sleep/confusion/paralysis all happen before the check for primal weather -{ - GIVEN { - PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);} - OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);} - } WHEN { - TURN { MOVE(opponent, MOVE_EMBER); } - } SCENE { - NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); - MESSAGE("Foe Wobbuffet is fast asleep."); - } -} - SINGLE_BATTLE_TEST("Desolate Land blocks damaging Water-type moves") { GIVEN { diff --git a/test/ability_download.c b/test/battle/ability/download.c similarity index 99% rename from test/ability_download.c rename to test/battle/ability/download.c index ee03f6911..5b59e37f0 100644 --- a/test/ability_download.c +++ b/test/battle/ability/download.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_drizzle.c b/test/battle/ability/drizzle.c similarity index 96% rename from test/ability_drizzle.c rename to test/battle/ability/drizzle.c index fd0d42616..ce0fc9514 100644 --- a/test/ability_drizzle.c +++ b/test/battle/ability/drizzle.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Drizzle summons rain", s16 damage) { diff --git a/test/ability_dry_skin.c b/test/battle/ability/dry_skin.c similarity index 99% rename from test/ability_dry_skin.c rename to test/battle/ability/dry_skin.c index 028076d5a..832b7baaf 100644 --- a/test/ability_dry_skin.c +++ b/test/battle/ability/dry_skin.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Dry Skin causes 1/8th Max HP damage in Sun") { diff --git a/test/ability_electromorphosis.c b/test/battle/ability/electromorphosis.c similarity index 98% rename from test/ability_electromorphosis.c rename to test/battle/ability/electromorphosis.c index 25d33aac0..9111fa328 100644 --- a/test/ability_electromorphosis.c +++ b/test/battle/ability/electromorphosis.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Electromorphosis sets up Charge when hit by any move") { diff --git a/test/ability_flame_body.c b/test/battle/ability/flame_body.c similarity index 97% rename from test/ability_flame_body.c rename to test/battle/ability/flame_body.c index 303337693..ae9138e12 100644 --- a/test/ability_flame_body.c +++ b/test/battle/ability/flame_body.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Flame Body inflicts burn on contact") { diff --git a/test/ability_flower_gift.c b/test/battle/ability/flower_gift.c similarity index 99% rename from test/ability_flower_gift.c rename to test/battle/ability/flower_gift.c index 560706af4..fdd191f55 100644 --- a/test/ability_flower_gift.c +++ b/test/battle/ability/flower_gift.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim in harsh sunlight") { diff --git a/test/ability_forecast.c b/test/battle/ability/forecast.c similarity index 99% rename from test/ability_forecast.c rename to test/battle/ability/forecast.c index 696c0383a..26ad789da 100644 --- a/test/ability_forecast.c +++ b/test/battle/ability/forecast.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Forecast transforms Castform in weather from an opponent's move") { diff --git a/test/ability_full_metal_body.c b/test/battle/ability/full_metal_body.c similarity index 98% rename from test/ability_full_metal_body.c rename to test/battle/ability/full_metal_body.c index c47ce9d4d..d00714d52 100644 --- a/test/ability_full_metal_body.c +++ b/test/battle/ability/full_metal_body.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Full Metal Body prevents intimidate") { diff --git a/test/ability_hunger_switch.c b/test/battle/ability/hunger_switch.c similarity index 96% rename from test/ability_hunger_switch.c rename to test/battle/ability/hunger_switch.c index 336c2c160..c0802d664 100644 --- a/test/ability_hunger_switch.c +++ b/test/battle/ability/hunger_switch.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the turn") { diff --git a/test/ability_hydration.c b/test/battle/ability/hydration.c similarity index 95% rename from test/ability_hydration.c rename to test/battle/ability/hydration.c index 45689b212..2dca490c0 100644 --- a/test/ability_hydration.c +++ b/test/battle/ability/hydration.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Hydration cures non-volatile Status conditions if it is raining") { diff --git a/test/ability_hyper_cutter.c b/test/battle/ability/hyper_cutter.c similarity index 98% rename from test/ability_hyper_cutter.c rename to test/battle/ability/hyper_cutter.c index 67dac4c66..ac942039b 100644 --- a/test/ability_hyper_cutter.c +++ b/test/battle/ability/hyper_cutter.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Hyper Cutter prevents intimidate") { diff --git a/test/ability_ice_body.c b/test/battle/ability/ice_body.c similarity index 96% rename from test/ability_ice_body.c rename to test/battle/ability/ice_body.c index 0658ace81..aca84532a 100644 --- a/test/ability_ice_body.c +++ b/test/battle/ability/ice_body.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Ice Body prevents damage from hail") { diff --git a/test/ability_immunity.c b/test/battle/ability/immunity.c similarity index 98% rename from test/ability_immunity.c rename to test/battle/ability/immunity.c index fea2eb522..3c6c4afa6 100644 --- a/test/ability_immunity.c +++ b/test/battle/ability/immunity.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Immunity prevents Poison Sting poison") { diff --git a/test/ability_inner_focus.c b/test/battle/ability/inner_focus.c similarity index 98% rename from test/ability_inner_focus.c rename to test/battle/ability/inner_focus.c index 5b713475d..574c860a7 100644 --- a/test/ability_inner_focus.c +++ b/test/battle/ability/inner_focus.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Inner Focus prevents intimidate") { diff --git a/test/ability_insomnia.c b/test/battle/ability/insomnia.c similarity index 98% rename from test/ability_insomnia.c rename to test/battle/ability/insomnia.c index 2fcb6a97e..cb22be925 100644 --- a/test/ability_insomnia.c +++ b/test/battle/ability/insomnia.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Insomnia prevents sleep") { diff --git a/test/ability_intimidate.c b/test/battle/ability/intimidate.c similarity index 99% rename from test/ability_intimidate.c rename to test/battle/ability/intimidate.c index f9681493b..a0a23cc13 100644 --- a/test/ability_intimidate.c +++ b/test/battle/ability/intimidate.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_leaf_guard.c b/test/battle/ability/leaf_guard.c similarity index 99% rename from test/ability_leaf_guard.c rename to test/battle/ability/leaf_guard.c index 92727175a..2c052b5a6 100644 --- a/test/ability_leaf_guard.c +++ b/test/battle/ability/leaf_guard.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Leaf Guard prevents non-volatile status conditions in sun") { diff --git a/test/ability_limber.c b/test/battle/ability/limber.c similarity index 94% rename from test/ability_limber.c rename to test/battle/ability/limber.c index ff701b663..87d4177ff 100644 --- a/test/ability_limber.c +++ b/test/battle/ability/limber.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Limber prevents paralysis") { diff --git a/test/ability_magic_bounce.c b/test/battle/ability/magic_bounce.c similarity index 99% rename from test/ability_magic_bounce.c rename to test/battle/ability/magic_bounce.c index ab51369ef..348b80f0a 100644 --- a/test/ability_magic_bounce.c +++ b/test/battle/ability/magic_bounce.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Magic Bounce bounces back status moves") diff --git a/test/ability_mirror_armor.c b/test/battle/ability/mirror_armor.c similarity index 99% rename from test/ability_mirror_armor.c rename to test/battle/ability/mirror_armor.c index 7e15e029b..2b0a59044 100644 --- a/test/ability_mirror_armor.c +++ b/test/battle/ability/mirror_armor.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_oblivious.c b/test/battle/ability/oblivious.c similarity index 98% rename from test/ability_oblivious.c rename to test/battle/ability/oblivious.c index 9d9aeeb29..51d27bb16 100644 --- a/test/ability_oblivious.c +++ b/test/battle/ability/oblivious.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Oblivious prevents Infatuation") { diff --git a/test/battle/ability/overcoat.c b/test/battle/ability/overcoat.c new file mode 100644 index 000000000..5f2405167 --- /dev/null +++ b/test/battle/ability/overcoat.c @@ -0,0 +1,21 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Overcoat blocks powder and spore moves") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); } + } WHEN { + TURN { MOVE(player, MOVE_STUN_SPORE); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_OVERCOAT); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player); + MESSAGE("It doesn't affect Foe Pineco…"); + } +} + +TO_DO_BATTLE_TEST("Overcoat blocks damage from hail"); +TO_DO_BATTLE_TEST("Overcoat blocks damage from sandstorm"); +TO_DO_BATTLE_TEST("Overcoat blocks Effect Spore's effect"); diff --git a/test/ability_overgrow.c b/test/battle/ability/overgrow.c similarity index 96% rename from test/ability_overgrow.c rename to test/battle/ability/overgrow.c index 82d8dd467..548dc9bb3 100644 --- a/test/ability_overgrow.c +++ b/test/battle/ability/overgrow.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Overgrow boosts Grass-type moves in a pinch", s16 damage) { diff --git a/test/ability_own_tempo.c b/test/battle/ability/own_tempo.c similarity index 99% rename from test/ability_own_tempo.c rename to test/battle/ability/own_tempo.c index 2440ac779..4c6a3167f 100644 --- a/test/ability_own_tempo.c +++ b/test/battle/ability/own_tempo.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Own Tempo prevents intimidate") { diff --git a/test/ability_pastel_veil.c b/test/battle/ability/pastel_veil.c similarity index 99% rename from test/ability_pastel_veil.c rename to test/battle/ability/pastel_veil.c index 363c018c1..74d764fc3 100644 --- a/test/ability_pastel_veil.c +++ b/test/battle/ability/pastel_veil.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Pastel Veil prevents Poison Sting poison") { diff --git a/test/ability_poison_point.c b/test/battle/ability/poison_point.c similarity index 97% rename from test/ability_poison_point.c rename to test/battle/ability/poison_point.c index a85edd85b..63690d84d 100644 --- a/test/ability_poison_point.c +++ b/test/battle/ability/poison_point.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Poison Point inflicts poison on contact") { diff --git a/test/battle/ability/primordial_sea.c b/test/battle/ability/primordial_sea.c new file mode 100644 index 000000000..37fbb1b23 --- /dev/null +++ b/test/battle/ability/primordial_sea.c @@ -0,0 +1,66 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_EMBER].power != 0); + ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); +} + +SINGLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves") +{ + GIVEN { + PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + MESSAGE("Foe Wobbuffet used Ember!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + NOT HP_BAR(player); + MESSAGE("Foe Wobbuffet used Ember!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, opponent); + MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + NOT HP_BAR(player); + } THEN { + EXPECT_EQ(player->hp, player->maxHP); + } +} + +DOUBLE_BATTLE_TEST("Primordial Sea blocks damaging Fire-type moves and prints the message only once with moves hitting multiple targets") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_ERUPTION].power != 0); + ASSUME(gBattleMoves[MOVE_ERUPTION].type == TYPE_FIRE); + ASSUME(gBattleMoves[MOVE_ERUPTION].target == MOVE_TARGET_BOTH); + PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB); {Speed(5);}} + PLAYER(SPECIES_WOBBUFFET) {Speed(5);} + OPPONENT(SPECIES_WOBBUFFET) {Speed(10);} + OPPONENT(SPECIES_WOBBUFFET) {Speed(8);} + } WHEN { + TURN { MOVE(opponentLeft, MOVE_ERUPTION); } + } SCENE { + MESSAGE("Foe Wobbuffet used Eruption!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_ERUPTION, opponentLeft); + MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + } THEN { + EXPECT_EQ(playerLeft->hp, playerLeft->maxHP); + EXPECT_EQ(playerRight->hp, playerRight->maxHP); + } +} + +SINGLE_BATTLE_TEST("Primordial Sea does not block a move if pokemon is asleep and uses a Fire-type move") // Sleep/confusion/paralysis all happen before the check for primal weather +{ + GIVEN { + PLAYER(SPECIES_KYOGRE) {Item(ITEM_BLUE_ORB);} + OPPONENT(SPECIES_WOBBUFFET) {Status1(STATUS1_SLEEP);} + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); } + } SCENE { + NOT MESSAGE("The Fire-type attack fizzled out\nin the heavy rain!"); + MESSAGE("Foe Wobbuffet is fast asleep."); + } +} \ No newline at end of file diff --git a/test/ability_protosynthesis.c b/test/battle/ability/protosynthesis.c similarity index 99% rename from test/ability_protosynthesis.c rename to test/battle/ability/protosynthesis.c index 9f794e00a..0ed74d4f6 100644 --- a/test/ability_protosynthesis.c +++ b/test/battle/ability/protosynthesis.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_quark_drive.c b/test/battle/ability/quark_drive.c similarity index 99% rename from test/ability_quark_drive.c rename to test/battle/ability/quark_drive.c index b004c760c..bce6795ca 100644 --- a/test/ability_quark_drive.c +++ b/test/battle/ability/quark_drive.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_rain_dish.c b/test/battle/ability/rain_dish.c similarity index 94% rename from test/ability_rain_dish.c rename to test/battle/ability/rain_dish.c index 04009507c..dd647f0eb 100644 --- a/test/ability_rain_dish.c +++ b/test/battle/ability/rain_dish.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Rain Dish recovers 1/16th of Max HP in Rain") { diff --git a/test/ability_rattled.c b/test/battle/ability/rattled.c similarity index 99% rename from test/ability_rattled.c rename to test/battle/ability/rattled.c index 493e3cfca..e936ed7de 100644 --- a/test/ability_rattled.c +++ b/test/battle/ability/rattled.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_sand_veil.c b/test/battle/ability/sand_veil.c similarity index 96% rename from test/ability_sand_veil.c rename to test/battle/ability/sand_veil.c index 50abad51c..c2f6440c3 100644 --- a/test/ability_sand_veil.c +++ b/test/battle/ability/sand_veil.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Sand Veil prevents damage from sandstorm") { diff --git a/test/ability_schooling.c b/test/battle/ability/schooling.c similarity index 99% rename from test/ability_schooling.c rename to test/battle/ability/schooling.c index 87f69ea31..448e37261 100644 --- a/test/ability_schooling.c +++ b/test/battle/ability/schooling.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Schooling switches Level 20+ Wishiwashi's form when HP is 25-percent or less at the end of the turn") { diff --git a/test/ability_scrappy.c b/test/battle/ability/scrappy.c similarity index 98% rename from test/ability_scrappy.c rename to test/battle/ability/scrappy.c index b4f83afcf..df4ededa4 100644 --- a/test/ability_scrappy.c +++ b/test/battle/ability/scrappy.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Scrappy prevents intimidate") { diff --git a/test/ability_snow_cloak.c b/test/battle/ability/snow_cloak.c similarity index 96% rename from test/ability_snow_cloak.c rename to test/battle/ability/snow_cloak.c index 8a95a8ea0..88fe6e509 100644 --- a/test/ability_snow_cloak.c +++ b/test/battle/ability/snow_cloak.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Snow Cloak prevents damage from hail") { diff --git a/test/ability_snow_warning.c b/test/battle/ability/snow_warning.c similarity index 96% rename from test/ability_snow_warning.c rename to test/battle/ability/snow_warning.c index 5e8b13d54..17f18814b 100644 --- a/test/ability_snow_warning.c +++ b/test/battle/ability/snow_warning.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" #if B_SNOW_WARNING < GEN_9 SINGLE_BATTLE_TEST("Snow Warning summons hail") diff --git a/test/ability_speed_boost.c b/test/battle/ability/speed_boost.c similarity index 96% rename from test/ability_speed_boost.c rename to test/battle/ability/speed_boost.c index 78aa876e6..0cc82e806 100644 --- a/test/ability_speed_boost.c +++ b/test/battle/ability/speed_boost.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Speed Boost gradually boosts Speed") { diff --git a/test/ability_stamina.c b/test/battle/ability/stamina.c similarity index 99% rename from test/ability_stamina.c rename to test/battle/ability/stamina.c index 70cf3cdc0..3470cce51 100644 --- a/test/ability_stamina.c +++ b/test/battle/ability/stamina.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" #define STAMINA_STAT_RAISE(target, msg) \ { \ diff --git a/test/ability_static.c b/test/battle/ability/static.c similarity index 97% rename from test/ability_static.c rename to test/battle/ability/static.c index 022efa5bb..eb52a838b 100644 --- a/test/ability_static.c +++ b/test/battle/ability/static.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Static inflicts paralysis on contact") { diff --git a/test/ability_stench.c b/test/battle/ability/stench.c similarity index 97% rename from test/ability_stench.c rename to test/battle/ability/stench.c index dd1d027e9..a91c861fc 100644 --- a/test/ability_stench.c +++ b/test/battle/ability/stench.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Stench has a 10% chance to flinch") { diff --git a/test/ability_sturdy.c b/test/battle/ability/sturdy.c similarity index 98% rename from test/ability_sturdy.c rename to test/battle/ability/sturdy.c index 42cdab11f..7a7fdf39f 100644 --- a/test/ability_sturdy.c +++ b/test/battle/ability/sturdy.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Sturdy prevents OHKO moves") { diff --git a/test/ability_swarm.c b/test/battle/ability/swarm.c similarity index 95% rename from test/ability_swarm.c rename to test/battle/ability/swarm.c index 7709e976e..c6479412a 100644 --- a/test/ability_swarm.c +++ b/test/battle/ability/swarm.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Swarm boosts Bug-type moves in a pinch", s16 damage) { diff --git a/test/ability_sword_of_ruin.c b/test/battle/ability/sword_of_ruin.c similarity index 98% rename from test/ability_sword_of_ruin.c rename to test/battle/ability/sword_of_ruin.c index 6ec4f8fe8..2abc0c04f 100644 --- a/test/ability_sword_of_ruin.c +++ b/test/battle/ability/sword_of_ruin.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_tablets_of_ruin.c b/test/battle/ability/tablets_of_ruin.c similarity index 98% rename from test/ability_tablets_of_ruin.c rename to test/battle/ability/tablets_of_ruin.c index 38dcfc856..ca12b6813 100644 --- a/test/ability_tablets_of_ruin.c +++ b/test/battle/ability/tablets_of_ruin.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_torrent.c b/test/battle/ability/torrent.c similarity index 95% rename from test/ability_torrent.c rename to test/battle/ability/torrent.c index e5c701775..673e21b79 100644 --- a/test/ability_torrent.c +++ b/test/battle/ability/torrent.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Torrent boosts Water-type moves in a pinch", s16 damage) { diff --git a/test/ability_vessel_of_ruin.c b/test/battle/ability/vessel_of_ruin.c similarity index 98% rename from test/ability_vessel_of_ruin.c rename to test/battle/ability/vessel_of_ruin.c index 6c7b2664f..4f8408795 100644 --- a/test/ability_vessel_of_ruin.c +++ b/test/battle/ability/vessel_of_ruin.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_volt_absorb.c b/test/battle/ability/volt_absorb.c similarity index 99% rename from test/ability_volt_absorb.c rename to test/battle/ability/volt_absorb.c index f9af7e17b..2f69a287b 100644 --- a/test/ability_volt_absorb.c +++ b/test/battle/ability/volt_absorb.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Volt Absorb heals 25% when hit by electric type moves") { diff --git a/test/ability_water_absorb.c b/test/battle/ability/water_absorb.c similarity index 99% rename from test/ability_water_absorb.c rename to test/battle/ability/water_absorb.c index 50547d13d..cda319603 100644 --- a/test/ability_water_absorb.c +++ b/test/battle/ability/water_absorb.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Water Absorb heals 25% when hit by water type moves") { diff --git a/test/ability_white_smoke.c b/test/battle/ability/white_smoke.c similarity index 98% rename from test/ability_white_smoke.c rename to test/battle/ability/white_smoke.c index 9689aee6c..7bedbca24 100644 --- a/test/ability_white_smoke.c +++ b/test/battle/ability/white_smoke.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("White Smoke prevents intimidate") { diff --git a/test/ability_wind_power.c b/test/battle/ability/wind_power.c similarity index 99% rename from test/ability_wind_power.c rename to test/battle/ability/wind_power.c index 8488db269..996910640 100644 --- a/test/ability_wind_power.c +++ b/test/battle/ability/wind_power.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/ability_zen_mode.c b/test/battle/ability/zen_mode.c similarity index 99% rename from test/ability_zen_mode.c rename to test/battle/ability/zen_mode.c index e0e72471f..37bb4160f 100644 --- a/test/ability_zen_mode.c +++ b/test/battle/ability/zen_mode.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Zen Mode switches Darmanitan's form when HP is half or less at the end of the turn") { diff --git a/test/battle/form_change/battle_switch.c b/test/battle/form_change/battle_switch.c new file mode 100644 index 000000000..bd18e0ccf --- /dev/null +++ b/test/battle/form_change/battle_switch.c @@ -0,0 +1,23 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon switching out") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + } SCENE { + ABILITY_POPUP(player, ABILITY_STANCE_CHANGE); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Aegislash used Tackle!"); + MESSAGE("Foe Wobbuffet used Celebrate!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_AEGISLASH); + } +} diff --git a/test/form_change.c b/test/battle/form_change/begin_battle.c similarity index 68% rename from test/form_change.c rename to test/battle/form_change/begin_battle.c index 43497101c..328db756d 100644 --- a/test/form_change.c +++ b/test/battle/form_change/begin_battle.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Xerneas changes into Active Form upon battle start") { @@ -79,41 +79,3 @@ SINGLE_BATTLE_TEST("Zamazenta's Iron Head becomes Behemoth Bash upon form change EXPECT_EQ(player->moves[0], MOVE_BEHEMOTH_BASH); } } - -SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon switching out") -{ - GIVEN { - ASSUME(P_GEN_6_POKEMON == TRUE); - PLAYER(SPECIES_AEGISLASH); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_TACKLE); } - TURN { SWITCH(player, 1); } - TURN { SWITCH(player, 0); } - } SCENE { - ABILITY_POPUP(player, ABILITY_STANCE_CHANGE); - ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); - MESSAGE("Aegislash used Tackle!"); - MESSAGE("Foe Wobbuffet used Celebrate!"); - } THEN { - EXPECT_EQ(player->species, SPECIES_AEGISLASH); - } -} - -SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting") -{ - GIVEN { - ASSUME(P_GEN_6_POKEMON == TRUE); - PLAYER(SPECIES_AEGISLASH) { HP(1); } - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, MOVE_GUST); SEND_OUT(player, 1); } - } SCENE { - MESSAGE("Foe Wobbuffet used Gust!"); - MESSAGE("Aegislash fainted!"); - } THEN { - EXPECT_EQ(GetMonData(&PLAYER_PARTY[0], MON_DATA_SPECIES), SPECIES_AEGISLASH); - } -} diff --git a/test/battle/form_change/faint.c b/test/battle/form_change/faint.c new file mode 100644 index 000000000..f4baa2894 --- /dev/null +++ b/test/battle/form_change/faint.c @@ -0,0 +1,19 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Aegislash reverts to Shield Form upon fainting") +{ + GIVEN { + ASSUME(P_GEN_6_POKEMON == TRUE); + PLAYER(SPECIES_AEGISLASH) { HP(1); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_GUST); SEND_OUT(player, 1); } + } SCENE { + MESSAGE("Foe Wobbuffet used Gust!"); + MESSAGE("Aegislash fainted!"); + } THEN { + EXPECT_EQ(GetMonData(&PLAYER_PARTY[0], MON_DATA_SPECIES), SPECIES_AEGISLASH); + } +} diff --git a/test/mega_evolution.c b/test/battle/form_change/mega_evolution.c similarity index 99% rename from test/mega_evolution.c rename to test/battle/form_change/mega_evolution.c index 5597f5396..32cfb2c59 100644 --- a/test/mega_evolution.c +++ b/test/battle/form_change/mega_evolution.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Venusaur can Mega Evolve holding Venusaurite") { diff --git a/test/primal_reversion.c b/test/battle/form_change/primal_reversion.c similarity index 99% rename from test/primal_reversion.c rename to test/battle/form_change/primal_reversion.c index f888d17f7..3e271f67c 100644 --- a/test/primal_reversion.c +++ b/test/battle/form_change/primal_reversion.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Primal reversion happens for Groudon only when holding Red Orb") { diff --git a/test/hold_effect_air_balloon.c b/test/battle/hold_effect/air_balloon.c similarity index 99% rename from test/hold_effect_air_balloon.c rename to test/battle/hold_effect/air_balloon.c index ba740948a..1ed8a89e4 100644 --- a/test/hold_effect_air_balloon.c +++ b/test/battle/hold_effect/air_balloon.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/hold_effect_berserk_gene.c b/test/battle/hold_effect/berserk_gene.c similarity index 99% rename from test/hold_effect_berserk_gene.c rename to test/battle/hold_effect/berserk_gene.c index 981881e74..6fd0f8a85 100644 --- a/test/hold_effect_berserk_gene.c +++ b/test/battle/hold_effect/berserk_gene.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/hold_effect_clear_amulet.c b/test/battle/hold_effect/clear_amulet.c similarity index 99% rename from test/hold_effect_clear_amulet.c rename to test/battle/hold_effect/clear_amulet.c index 83c887b2d..39e6c22a6 100644 --- a/test/hold_effect_clear_amulet.c +++ b/test/battle/hold_effect/clear_amulet.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/hold_effect_eject_button.c b/test/battle/hold_effect/eject_button.c similarity index 99% rename from test/hold_effect_eject_button.c rename to test/battle/hold_effect/eject_button.c index 7e6312656..4409f5d5b 100644 --- a/test/hold_effect_eject_button.c +++ b/test/battle/hold_effect/eject_button.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/hold_effect_gems.c b/test/battle/hold_effect/gems.c similarity index 99% rename from test/hold_effect_gems.c rename to test/battle/hold_effect/gems.c index 9a90b81f9..c98718313 100644 --- a/test/hold_effect_gems.c +++ b/test/battle/hold_effect/gems.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/hold_effect_leftovers.c b/test/battle/hold_effect/leftovers.c similarity index 98% rename from test/hold_effect_leftovers.c rename to test/battle/hold_effect/leftovers.c index 01b0655a5..7e51a3bd7 100644 --- a/test/hold_effect_leftovers.c +++ b/test/battle/hold_effect/leftovers.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/hold_effect_mirror_herb.c b/test/battle/hold_effect/mirror_herb.c similarity index 98% rename from test/hold_effect_mirror_herb.c rename to test/battle/hold_effect/mirror_herb.c index 22f564b85..1e9058b08 100644 --- a/test/hold_effect_mirror_herb.c +++ b/test/battle/hold_effect/mirror_herb.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/hold_effect_red_card.c b/test/battle/hold_effect/red_card.c similarity index 99% rename from test/hold_effect_red_card.c rename to test/battle/hold_effect/red_card.c index 0a8bb3460..aad7fea64 100644 --- a/test/hold_effect_red_card.c +++ b/test/battle/hold_effect/red_card.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/battle/hold_effect/safety_goggles.c b/test/battle/hold_effect/safety_goggles.c new file mode 100644 index 000000000..bec703443 --- /dev/null +++ b/test/battle/hold_effect/safety_goggles.c @@ -0,0 +1,26 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + gItems[ITEM_SAFETY_GOGGLES].holdEffect == HOLD_EFFECT_SAFETY_GOGGLES; +}; + +SINGLE_BATTLE_TEST("Safety Goggles block powder and spore moves") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER); + ASSUME(gItems[ITEM_SAFETY_GOGGLES].holdEffect == HOLD_EFFECT_SAFETY_GOGGLES); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_ABRA) { Item(ITEM_SAFETY_GOGGLES); } + } WHEN { + TURN { MOVE(player, MOVE_STUN_SPORE); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player); + MESSAGE("Foe Abra is not affected thanks to its SafetyGoggles!"); + } +} + +TO_DO_BATTLE_TEST("Safety Goggles blocks damage from hail"); +TO_DO_BATTLE_TEST("Safety Goggles blocks damage from sandstorm"); +TO_DO_BATTLE_TEST("Safety Goggles blocks Effect Spore's effect"); diff --git a/test/hold_effect_utility_umbrella.c b/test/battle/hold_effect/utility_umbrella.c similarity index 99% rename from test/hold_effect_utility_umbrella.c rename to test/battle/hold_effect/utility_umbrella.c index 6716ee72f..837bacc90 100644 --- a/test/hold_effect_utility_umbrella.c +++ b/test/battle/hold_effect/utility_umbrella.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" // Please add Utility Umbrella interactions with move, item and ability effects on their respective files. ASSUMPTIONS diff --git a/test/item_effect_cure_status.c b/test/battle/item_effect/cure_status.c similarity index 99% rename from test/item_effect_cure_status.c rename to test/battle/item_effect/cure_status.c index 1f7c9d7a2..c8b16dfdb 100644 --- a/test/item_effect_cure_status.c +++ b/test/battle/item_effect/cure_status.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Paralyze Heal heals a battler from being paralyzed") { diff --git a/test/item_effect_heal_and_cure_status.c b/test/battle/item_effect/heal_and_cure_status.c similarity index 98% rename from test/item_effect_heal_and_cure_status.c rename to test/battle/item_effect/heal_and_cure_status.c index 1f81ad922..de6a459a1 100644 --- a/test/item_effect_heal_and_cure_status.c +++ b/test/battle/item_effect/heal_and_cure_status.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Full Restore restores a battler's HP and cures any primary status") { diff --git a/test/item_effect_increase_stat.c b/test/battle/item_effect/increase_stat.c similarity index 99% rename from test/item_effect_increase_stat.c rename to test/battle/item_effect/increase_stat.c index ab4113064..3aeb8d525 100644 --- a/test/item_effect_increase_stat.c +++ b/test/battle/item_effect/increase_stat.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("X Attack sharply raises battler's Attack stat", s16 damage) { diff --git a/test/item_effect_restore_hp.c b/test/battle/item_effect/restore_hp.c similarity index 98% rename from test/item_effect_restore_hp.c rename to test/battle/item_effect/restore_hp.c index a469b21ff..b9e4be034 100644 --- a/test/item_effect_restore_hp.c +++ b/test/battle/item_effect/restore_hp.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Items can restore a battler's HP by a fixed amount") { diff --git a/test/item_effect_restore_pp.c b/test/battle/item_effect/restore_pp.c similarity index 98% rename from test/item_effect_restore_pp.c rename to test/battle/item_effect/restore_pp.c index 7194efbbb..e998ef3d9 100644 --- a/test/item_effect_restore_pp.c +++ b/test/battle/item_effect/restore_pp.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Ether restores the PP of one of a battler's moves by 10 ") { diff --git a/test/item_effect_revive.c b/test/battle/item_effect/revive.c similarity index 98% rename from test/item_effect_revive.c rename to test/battle/item_effect/revive.c index c2a22f80a..2be2ac4a6 100644 --- a/test/item_effect_revive.c +++ b/test/battle/item_effect/revive.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Revive restores a fainted battler's HP to half") { diff --git a/test/item_effect_set_focus_energy.c b/test/battle/item_effect/set_focus_energy.c similarity index 96% rename from test/item_effect_set_focus_energy.c rename to test/battle/item_effect/set_focus_energy.c index 95648465e..da326bbe3 100644 --- a/test/item_effect_set_focus_energy.c +++ b/test/battle/item_effect/set_focus_energy.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Dire Hit increases a battler's critical hit chance by 2 stages") { diff --git a/test/item_effect_set_mist.c b/test/battle/item_effect/set_mist.c similarity index 96% rename from test/item_effect_set_mist.c rename to test/battle/item_effect/set_mist.c index e01775ec4..a369e70d9 100644 --- a/test/item_effect_set_mist.c +++ b/test/battle/item_effect/set_mist.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Guard Spec. sets Mist effect on the battlers side") { diff --git a/test/move.c b/test/battle/move.c similarity index 99% rename from test/move.c rename to test/battle/move.c index 9e23c2bd0..e89c2ad35 100644 --- a/test/move.c +++ b/test/battle/move.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Accuracy controls the proportion of misses") { diff --git a/test/move_effect_absorb.c b/test/battle/move_effect/absorb.c similarity index 97% rename from test/move_effect_absorb.c rename to test/battle/move_effect/absorb.c index 2ea49ef9e..d46dbd9c5 100644 --- a/test/move_effect_absorb.c +++ b/test/battle/move_effect/absorb.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_accuracy_down.c b/test/battle/move_effect/accuracy_down.c similarity index 96% rename from test/move_effect_accuracy_down.c rename to test/battle/move_effect/accuracy_down.c index a6a79d8db..a30430a28 100644 --- a/test/move_effect_accuracy_down.c +++ b/test/battle/move_effect/accuracy_down.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_after_you.c b/test/battle/move_effect/after_you.c similarity index 98% rename from test/move_effect_after_you.c rename to test/battle/move_effect/after_you.c index a488d7a8c..576267cb4 100644 --- a/test/move_effect_after_you.c +++ b/test/battle/move_effect/after_you.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_assist.c b/test/battle/move_effect/assist.c similarity index 96% rename from test/move_effect_assist.c rename to test/battle/move_effect/assist.c index 28ae78572..ed2f43dc1 100644 --- a/test/move_effect_assist.c +++ b/test/battle/move_effect/assist.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_attack_down.c b/test/battle/move_effect/attack_down.c similarity index 97% rename from test/move_effect_attack_down.c rename to test/battle/move_effect/attack_down.c index 0df14f701..2149624c8 100644 --- a/test/move_effect_attack_down.c +++ b/test/battle/move_effect/attack_down.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_attack_up.c b/test/battle/move_effect/attack_up.c similarity index 97% rename from test/move_effect_attack_up.c rename to test/battle/move_effect/attack_up.c index 4978d03f9..7cd8f953c 100644 --- a/test/move_effect_attack_up.c +++ b/test/battle/move_effect/attack_up.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_attack_up_user_ally.c b/test/battle/move_effect/attack_up_user_ally.c similarity index 99% rename from test/move_effect_attack_up_user_ally.c rename to test/battle/move_effect/attack_up_user_ally.c index 3d2ac6bb8..6691b49ed 100644 --- a/test/move_effect_attack_up_user_ally.c +++ b/test/battle/move_effect/attack_up_user_ally.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_barb_barrage.c b/test/battle/move_effect/barb_barrage.c similarity index 98% rename from test/move_effect_barb_barrage.c rename to test/battle/move_effect/barb_barrage.c index ad9f1ec2e..89062b3de 100644 --- a/test/move_effect_barb_barrage.c +++ b/test/battle/move_effect/barb_barrage.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_beak_blast.c b/test/battle/move_effect/beak_blast.c similarity index 99% rename from test/move_effect_beak_blast.c rename to test/battle/move_effect/beak_blast.c index a2d66b405..50bff2411 100644 --- a/test/move_effect_beak_blast.c +++ b/test/battle/move_effect/beak_blast.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_bide.c b/test/battle/move_effect/bide.c similarity index 97% rename from test/move_effect_bide.c rename to test/battle/move_effect/bide.c index 0b0e18408..4dfdc3430 100644 --- a/test/move_effect_bide.c +++ b/test/battle/move_effect/bide.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_burn_hit.c b/test/battle/move_effect/burn_hit.c similarity index 97% rename from test/move_effect_burn_hit.c rename to test/battle/move_effect/burn_hit.c index 88fef17cb..3f257dfcb 100644 --- a/test/move_effect_burn_hit.c +++ b/test/battle/move_effect/burn_hit.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_burn_up.c b/test/battle/move_effect/burn_up.c similarity index 98% rename from test/move_effect_burn_up.c rename to test/battle/move_effect/burn_up.c index a53b1afa8..d24e47992 100644 --- a/test/move_effect_burn_up.c +++ b/test/battle/move_effect/burn_up.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_court_change.c b/test/battle/move_effect/court_change.c similarity index 99% rename from test/move_effect_court_change.c rename to test/battle/move_effect/court_change.c index 9d03efddf..4aa2e9d36 100644 --- a/test/move_effect_court_change.c +++ b/test/battle/move_effect/court_change.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_defense_down.c b/test/battle/move_effect/defense_down.c similarity index 97% rename from test/move_effect_defense_down.c rename to test/battle/move_effect/defense_down.c index 9ecd1c25f..8a8c69ec3 100644 --- a/test/move_effect_defense_down.c +++ b/test/battle/move_effect/defense_down.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_defense_up.c b/test/battle/move_effect/defense_up.c similarity index 97% rename from test/move_effect_defense_up.c rename to test/battle/move_effect/defense_up.c index 492ce7bc9..b4c7cb4db 100644 --- a/test/move_effect_defense_up.c +++ b/test/battle/move_effect/defense_up.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_defog.c b/test/battle/move_effect/defog.c similarity index 99% rename from test/move_effect_defog.c rename to test/battle/move_effect/defog.c index 055f3f61a..1cd78fb50 100644 --- a/test/move_effect_defog.c +++ b/test/battle/move_effect/defog.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_dire_claw.c b/test/battle/move_effect/dire_claw.c similarity index 99% rename from test/move_effect_dire_claw.c rename to test/battle/move_effect/dire_claw.c index 712b6ea25..421ba201d 100644 --- a/test/move_effect_dire_claw.c +++ b/test/battle/move_effect/dire_claw.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_double_shock.c b/test/battle/move_effect/double_shock.c similarity index 98% rename from test/move_effect_double_shock.c rename to test/battle/move_effect/double_shock.c index c3651c403..89f758681 100644 --- a/test/move_effect_double_shock.c +++ b/test/battle/move_effect/double_shock.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_dream_eater.c b/test/battle/move_effect/dream_eater.c similarity index 98% rename from test/move_effect_dream_eater.c rename to test/battle/move_effect/dream_eater.c index fa17b94a6..047fe7898 100644 --- a/test/move_effect_dream_eater.c +++ b/test/battle/move_effect/dream_eater.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_encore.c b/test/battle/move_effect/encore.c similarity index 98% rename from test/move_effect_encore.c rename to test/battle/move_effect/encore.c index f8a178512..eff6c33b2 100644 --- a/test/move_effect_encore.c +++ b/test/battle/move_effect/encore.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_evasion_up.c b/test/battle/move_effect/evasion_up.c similarity index 96% rename from test/move_effect_evasion_up.c rename to test/battle/move_effect/evasion_up.c index 4a4e99db7..ecb6429cd 100644 --- a/test/move_effect_evasion_up.c +++ b/test/battle/move_effect/evasion_up.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_explosion.c b/test/battle/move_effect/explosion.c similarity index 99% rename from test/move_effect_explosion.c rename to test/battle/move_effect/explosion.c index 41e74044b..ef6dba6c0 100644 --- a/test/move_effect_explosion.c +++ b/test/battle/move_effect/explosion.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_focus_punch.c b/test/battle/move_effect/focus_punch.c similarity index 99% rename from test/move_effect_focus_punch.c rename to test/battle/move_effect/focus_punch.c index 2bd1e52e5..e97deef43 100644 --- a/test/move_effect_focus_punch.c +++ b/test/battle/move_effect/focus_punch.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_freeze_hit.c b/test/battle/move_effect/freeze_hit.c similarity index 97% rename from test/move_effect_freeze_hit.c rename to test/battle/move_effect/freeze_hit.c index bb0878d0d..5d99311ce 100644 --- a/test/move_effect_freeze_hit.c +++ b/test/battle/move_effect/freeze_hit.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_haze.c b/test/battle/move_effect/haze.c similarity index 97% rename from test/move_effect_haze.c rename to test/battle/move_effect/haze.c index bd43c6947..f1e4456aa 100644 --- a/test/move_effect_haze.c +++ b/test/battle/move_effect/haze.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_healing_wish.c b/test/battle/move_effect/healing_wish.c similarity index 99% rename from test/move_effect_healing_wish.c rename to test/battle/move_effect/healing_wish.c index 00ee76561..fd25b8489 100644 --- a/test/move_effect_healing_wish.c +++ b/test/battle/move_effect/healing_wish.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_hex.c b/test/battle/move_effect/hex.c similarity index 97% rename from test/move_effect_hex.c rename to test/battle/move_effect/hex.c index 2847aeb17..e0a924906 100644 --- a/test/move_effect_hex.c +++ b/test/battle/move_effect/hex.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_hit_escape.c b/test/battle/move_effect/hit_escape.c similarity index 99% rename from test/move_effect_hit_escape.c rename to test/battle/move_effect/hit_escape.c index fb5ff2dd5..f2d513095 100644 --- a/test/move_effect_hit_escape.c +++ b/test/battle/move_effect/hit_escape.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_hit_set_entry_hazardss.c b/test/battle/move_effect/hit_set_entry_hazardss.c similarity index 99% rename from test/move_effect_hit_set_entry_hazardss.c rename to test/battle/move_effect/hit_set_entry_hazardss.c index 23f0f0b28..caf75ed49 100644 --- a/test/move_effect_hit_set_entry_hazardss.c +++ b/test/battle/move_effect/hit_set_entry_hazardss.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_hit_switch_target.c b/test/battle/move_effect/hit_switch_target.c similarity index 98% rename from test/move_effect_hit_switch_target.c rename to test/battle/move_effect/hit_switch_target.c index 5af3062a4..683b005fd 100644 --- a/test/move_effect_hit_switch_target.c +++ b/test/battle/move_effect/hit_switch_target.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_hydro_steam.c b/test/battle/move_effect/hydro_steam.c similarity index 98% rename from test/move_effect_hydro_steam.c rename to test/battle/move_effect/hydro_steam.c index 487449159..f86da07ac 100644 --- a/test/move_effect_hydro_steam.c +++ b/test/battle/move_effect/hydro_steam.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_metronome.c b/test/battle/move_effect/metronome.c similarity index 98% rename from test/move_effect_metronome.c rename to test/battle/move_effect/metronome.c index 1e68603e6..c6611ffa5 100644 --- a/test/move_effect_metronome.c +++ b/test/battle/move_effect/metronome.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_mind_blown.c b/test/battle/move_effect/mind_blown.c similarity index 99% rename from test/move_effect_mind_blown.c rename to test/battle/move_effect/mind_blown.c index 19179f990..485f2abd6 100644 --- a/test/move_effect_mind_blown.c +++ b/test/battle/move_effect/mind_blown.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_mirror_move.c b/test/battle/move_effect/mirror_move.c similarity index 99% rename from test/move_effect_mirror_move.c rename to test/battle/move_effect/mirror_move.c index ff21c0efa..b709ffce7 100644 --- a/test/move_effect_mirror_move.c +++ b/test/battle/move_effect/mirror_move.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_paralyze_hit.c b/test/battle/move_effect/paralyze_hit.c similarity index 97% rename from test/move_effect_paralyze_hit.c rename to test/battle/move_effect/paralyze_hit.c index 8e7d259f7..4efe6746c 100644 --- a/test/move_effect_paralyze_hit.c +++ b/test/battle/move_effect/paralyze_hit.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_poison_hit.c b/test/battle/move_effect/poison_hit.c similarity index 97% rename from test/move_effect_poison_hit.c rename to test/battle/move_effect/poison_hit.c index b1a154810..91d700466 100644 --- a/test/move_effect_poison_hit.c +++ b/test/battle/move_effect/poison_hit.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_rampage.c b/test/battle/move_effect/rampage.c similarity index 99% rename from test/move_effect_rampage.c rename to test/battle/move_effect/rampage.c index aa4a002fb..a1a271b37 100644 --- a/test/move_effect_rampage.c +++ b/test/battle/move_effect/rampage.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_recoil_if_miss.c b/test/battle/move_effect/recoil_if_miss.c similarity index 99% rename from test/move_effect_recoil_if_miss.c rename to test/battle/move_effect/recoil_if_miss.c index 51b5fe5e9..c72fd2648 100644 --- a/test/move_effect_recoil_if_miss.c +++ b/test/battle/move_effect/recoil_if_miss.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_reflect.c b/test/battle/move_effect/reflect.c similarity index 99% rename from test/move_effect_reflect.c rename to test/battle/move_effect/reflect.c index 4ea875f35..dd8738f72 100644 --- a/test/move_effect_reflect.c +++ b/test/battle/move_effect/reflect.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_revival_blessing.c b/test/battle/move_effect/revival_blessing.c similarity index 99% rename from test/move_effect_revival_blessing.c rename to test/battle/move_effect/revival_blessing.c index 3cb4d4ca4..a5dd32c19 100644 --- a/test/move_effect_revival_blessing.c +++ b/test/battle/move_effect/revival_blessing.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" // Note: Since these tests are recorded battle, they don't test the right battle controller // behaviors. These have been tested in-game, in double, in multi, and in link battles. AI will always diff --git a/test/move_effect_roar.c b/test/battle/move_effect/roar.c similarity index 98% rename from test/move_effect_roar.c rename to test/battle/move_effect/roar.c index 99256b298..20f934808 100644 --- a/test/move_effect_roar.c +++ b/test/battle/move_effect/roar.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_shell_trap.c b/test/battle/move_effect/shell_trap.c similarity index 99% rename from test/move_effect_shell_trap.c rename to test/battle/move_effect/shell_trap.c index 2498e12f2..7fb80210e 100644 --- a/test/move_effect_shell_trap.c +++ b/test/battle/move_effect/shell_trap.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_sleep.c b/test/battle/move_effect/sleep.c similarity index 97% rename from test/move_effect_sleep.c rename to test/battle/move_effect/sleep.c index c34e1248e..d2cac0af9 100644 --- a/test/move_effect_sleep.c +++ b/test/battle/move_effect/sleep.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_special_attack_down.c b/test/battle/move_effect/special_attack_down.c similarity index 97% rename from test/move_effect_special_attack_down.c rename to test/battle/move_effect/special_attack_down.c index 0511692d4..6e7a84f0a 100644 --- a/test/move_effect_special_attack_down.c +++ b/test/battle/move_effect/special_attack_down.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_special_attack_up_3.c b/test/battle/move_effect/special_attack_up_3.c similarity index 97% rename from test/move_effect_special_attack_up_3.c rename to test/battle/move_effect/special_attack_up_3.c index ad53bedb9..340c59360 100644 --- a/test/move_effect_special_attack_up_3.c +++ b/test/battle/move_effect/special_attack_up_3.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_spikes.c b/test/battle/move_effect/spikes.c similarity index 99% rename from test/move_effect_spikes.c rename to test/battle/move_effect/spikes.c index 0c84a5fb1..bfc0f39b5 100644 --- a/test/move_effect_spikes.c +++ b/test/battle/move_effect/spikes.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_sticky_web.c b/test/battle/move_effect/sticky_web.c similarity index 99% rename from test/move_effect_sticky_web.c rename to test/battle/move_effect/sticky_web.c index f0a6eb8d8..e12cc8090 100644 --- a/test/move_effect_sticky_web.c +++ b/test/battle/move_effect/sticky_web.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_stockpile.c b/test/battle/move_effect/stockpile.c similarity index 99% rename from test/move_effect_stockpile.c rename to test/battle/move_effect/stockpile.c index b16408d49..0e540bb5d 100644 --- a/test/move_effect_stockpile.c +++ b/test/battle/move_effect/stockpile.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" // These tests cover all 3 effects: Stockpile, Spit up and Swallow. ASSUMPTIONS diff --git a/test/move_effect_tailwind.c b/test/battle/move_effect/tailwind.c similarity index 98% rename from test/move_effect_tailwind.c rename to test/battle/move_effect/tailwind.c index 7dfffdbe0..2e9ee5ade 100644 --- a/test/move_effect_tailwind.c +++ b/test/battle/move_effect/tailwind.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_teleport.c b/test/battle/move_effect/teleport.c similarity index 98% rename from test/move_effect_teleport.c rename to test/battle/move_effect/teleport.c index 9c8a16d4b..7544ae8a4 100644 --- a/test/move_effect_teleport.c +++ b/test/battle/move_effect/teleport.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_torment.c b/test/battle/move_effect/torment.c similarity index 98% rename from test/move_effect_torment.c rename to test/battle/move_effect/torment.c index 43f05e29f..dbef1d983 100644 --- a/test/move_effect_torment.c +++ b/test/battle/move_effect/torment.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_toxic.c b/test/battle/move_effect/toxic.c similarity index 98% rename from test/move_effect_toxic.c rename to test/battle/move_effect/toxic.c index f71d2a972..78d978b26 100644 --- a/test/move_effect_toxic.c +++ b/test/battle/move_effect/toxic.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_toxic_spikes.c b/test/battle/move_effect/toxic_spikes.c similarity index 99% rename from test/move_effect_toxic_spikes.c rename to test/battle/move_effect/toxic_spikes.c index 44780da21..3be2d1627 100644 --- a/test/move_effect_toxic_spikes.c +++ b/test/battle/move_effect/toxic_spikes.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_tri_attack.c b/test/battle/move_effect/tri_attack.c similarity index 99% rename from test/move_effect_tri_attack.c rename to test/battle/move_effect/tri_attack.c index 91b465067..aec711aab 100644 --- a/test/move_effect_tri_attack.c +++ b/test/battle/move_effect/tri_attack.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_triple_kick.c b/test/battle/move_effect/triple_kick.c similarity index 97% rename from test/move_effect_triple_kick.c rename to test/battle/move_effect/triple_kick.c index e0a91b011..5ff47c840 100644 --- a/test/move_effect_triple_kick.c +++ b/test/battle/move_effect/triple_kick.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_effect_venoshock.c b/test/battle/move_effect/venoshock.c similarity index 97% rename from test/move_effect_venoshock.c rename to test/battle/move_effect/venoshock.c index 134982a60..b2b8fcda2 100644 --- a/test/move_effect_venoshock.c +++ b/test/battle/move_effect/venoshock.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/move_flag_three_strikes.c b/test/battle/move_flags/three_strikes.c similarity index 98% rename from test/move_flag_three_strikes.c rename to test/battle/move_flags/three_strikes.c index b597b4efe..794df10d3 100644 --- a/test/move_flag_three_strikes.c +++ b/test/battle/move_flags/three_strikes.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Three-strike flag turns a move into a 3-hit move") { diff --git a/test/battle/status1/bad_poison.c b/test/battle/status1/bad_poison.c new file mode 100644 index 000000000..7a430086b --- /dev/null +++ b/test/battle/status1/bad_poison.c @@ -0,0 +1,39 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Bad poison deals 1/16th cumulative damage per turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_TOXIC_POISON); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + for (i = 0; i < 4; i++) + TURN {} + } SCENE { + s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); + for (i = 0; i < 4; i++) + HP_BAR(player, damage: maxHP / 16 * (i + 1)); + } +} + +SINGLE_BATTLE_TEST("Bad poison cumulative damage resets on switch") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_TOXIC_POISON); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN {} + TURN {} + TURN { SWITCH(player, 1); } + TURN { SWITCH(player, 0); } + TURN {} + TURN {} + } SCENE { + s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); + for (i = 0; i < 2; i++) + HP_BAR(player, damage: maxHP / 16 * (i + 1)); + for (i = 0; i < 2; i++) + HP_BAR(player, damage: maxHP / 16 * (i + 1)); + } +} diff --git a/test/battle/status1/burn.c b/test/battle/status1/burn.c new file mode 100644 index 000000000..84439ec9e --- /dev/null +++ b/test/battle/status1/burn.c @@ -0,0 +1,35 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Burn deals 1/16th damage per turn") +{ + GIVEN { + ASSUME(B_BURN_DAMAGE >= GEN_LATEST); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + for (i = 0; i < 4; i++) + TURN {} + } SCENE { + s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); + for (i = 0; i < 4; i++) + HP_BAR(player, damage: maxHP / 16); + } +} + +SINGLE_BATTLE_TEST("Burn reduces Attack by 50%", s16 damage) +{ + bool32 burned; + PARAMETRIZE { burned = FALSE; } + PARAMETRIZE { burned = TRUE; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { if (burned) Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); + } +} diff --git a/test/battle/status1/freeze.c b/test/battle/status1/freeze.c new file mode 100644 index 000000000..e3c53f790 --- /dev/null +++ b/test/battle/status1/freeze.c @@ -0,0 +1,45 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Freeze has a 20% chance of being thawed") +{ + PASSES_RANDOMLY(20, 100, RNG_FROZEN); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + STATUS_ICON(player, none: TRUE); + } +} + +SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("Foe Wobbuffet used Ember!"); + MESSAGE("Wobbuffet was defrosted!"); + STATUS_ICON(player, none: TRUE); + } +} + +SINGLE_BATTLE_TEST("Freeze is thawed by user's Flame Wheel") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_FLAME_WHEEL].flags & FLAG_THAW_USER); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FLAME_WHEEL); } + } SCENE { + MESSAGE("Wobbuffet was defrosted by Flame Wheel!"); + STATUS_ICON(player, none: TRUE); + MESSAGE("Wobbuffet used Flame Wheel!"); + } +} diff --git a/test/status_frostbite.c b/test/battle/status1/frostbite.c similarity index 99% rename from test/status_frostbite.c rename to test/battle/status1/frostbite.c index d2bfa6bba..2b61c4d65 100644 --- a/test/status_frostbite.c +++ b/test/battle/status1/frostbite.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Frostbite reduces the special attack by 50 percent") { diff --git a/test/battle/status1/paralysis.c b/test/battle/status1/paralysis.c new file mode 100644 index 000000000..b6edaf263 --- /dev/null +++ b/test/battle/status1/paralysis.c @@ -0,0 +1,44 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Paralysis reduces Speed by 50%") +{ + u16 playerSpeed; + bool32 playerFirst; + PARAMETRIZE { playerSpeed = 98; playerFirst = FALSE; } + PARAMETRIZE { playerSpeed = 102; playerFirst = TRUE; } + GIVEN { + ASSUME(B_PARALYSIS_SPEED >= GEN_7); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_PARALYSIS); Speed(playerSpeed); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + if (playerFirst) { + ONE_OF { + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Wobbuffet is paralyzed! It can't move!"); + } + MESSAGE("Foe Wobbuffet used Celebrate!"); + } else { + MESSAGE("Foe Wobbuffet used Celebrate!"); + ONE_OF { + MESSAGE("Wobbuffet used Celebrate!"); + MESSAGE("Wobbuffet is paralyzed! It can't move!"); + } + } + } +} + +SINGLE_BATTLE_TEST("Paralysis has a 25% chance of skipping the turn") +{ + PASSES_RANDOMLY(25, 100, RNG_PARALYSIS); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_PARALYSIS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + MESSAGE("Wobbuffet is paralyzed! It can't move!"); + } +} diff --git a/test/battle/status1/poison.c b/test/battle/status1/poison.c new file mode 100644 index 000000000..771d0d2ec --- /dev/null +++ b/test/battle/status1/poison.c @@ -0,0 +1,17 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Poison deals 1/8th damage per turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + for (i = 0; i < 4; i++) + TURN {} + } SCENE { + s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); + for (i = 0; i < 4; i++) + HP_BAR(player, damage: maxHP / 8); + } +} diff --git a/test/battle/status1/sleep.c b/test/battle/status1/sleep.c new file mode 100644 index 000000000..8ef6137d3 --- /dev/null +++ b/test/battle/status1/sleep.c @@ -0,0 +1,23 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Sleep prevents the battler from using a move") +{ + u32 turns; + PARAMETRIZE { turns = 1; } + PARAMETRIZE { turns = 2; } + PARAMETRIZE { turns = 3; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP_TURN(turns)); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + for (i = 0; i < turns; i++) + TURN { MOVE(player, MOVE_CELEBRATE); } + } SCENE { + for (i = 0; i < turns - 1; i++) + MESSAGE("Wobbuffet is fast asleep."); + MESSAGE("Wobbuffet woke up!"); + STATUS_ICON(player, none: TRUE); + MESSAGE("Wobbuffet used Celebrate!"); + } +} diff --git a/test/terrain_electric.c b/test/battle/terrain/electric.c similarity index 99% rename from test/terrain_electric.c rename to test/battle/terrain/electric.c index 78f490c42..cebb0cb75 100644 --- a/test/terrain_electric.c +++ b/test/battle/terrain/electric.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Electric Terrain protects grounded battlers from falling asleep") { diff --git a/test/terrain_grassy.c b/test/battle/terrain/grassy.c similarity index 99% rename from test/terrain_grassy.c rename to test/battle/terrain/grassy.c index 21d64f61e..893a30528 100644 --- a/test/terrain_grassy.c +++ b/test/battle/terrain/grassy.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Grassy Terrain recovers 1/16th HP at end of turn") { diff --git a/test/terrain_misty.c b/test/battle/terrain/misty.c similarity index 99% rename from test/terrain_misty.c rename to test/battle/terrain/misty.c index f60122075..dd6489af6 100644 --- a/test/terrain_misty.c +++ b/test/battle/terrain/misty.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Misty Terrain protects grounded battlers from non-volatile status conditions") { diff --git a/test/terrain_psychic.c b/test/battle/terrain/psychic.c similarity index 99% rename from test/terrain_psychic.c rename to test/battle/terrain/psychic.c index f9f95a47d..c810af340 100644 --- a/test/terrain_psychic.c +++ b/test/battle/terrain/psychic.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" SINGLE_BATTLE_TEST("Psychic Terrain protects grounded battlers from priority moves") { diff --git a/test/trainer_control.c b/test/battle/trainer_control.c similarity index 99% rename from test/trainer_control.c rename to test/battle/trainer_control.c index 2a21dcdf6..f5ca68e36 100644 --- a/test/trainer_control.c +++ b/test/battle/trainer_control.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test.h" +#include "test/test.h" #include "battle.h" #include "battle_main.h" #include "data.h" diff --git a/test/battle/type/grass.c b/test/battle/type/grass.c new file mode 100644 index 000000000..b36813ac7 --- /dev/null +++ b/test/battle/type/grass.c @@ -0,0 +1,17 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Grass-type Pokémon block powder and spore moves") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER); + ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_ODDISH); + } WHEN { + TURN { MOVE(player, MOVE_STUN_SPORE); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player); + MESSAGE("It doesn't affect Foe Oddish…"); + } +} diff --git a/test/weather_rain.c b/test/battle/weather/rain.c similarity index 98% rename from test/weather_rain.c rename to test/battle/weather/rain.c index b99681495..00ac26304 100644 --- a/test/weather_rain.c +++ b/test/battle/weather/rain.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" // Please add Rain interactions with move, item and ability effects on their respective files. ASSUMPTIONS diff --git a/test/weather_snow.c b/test/battle/weather/snow.c similarity index 99% rename from test/weather_snow.c rename to test/battle/weather/snow.c index 93deb1432..1e8cb62cb 100644 --- a/test/weather_snow.c +++ b/test/battle/weather/snow.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" ASSUMPTIONS { diff --git a/test/weather_sunlight.c b/test/battle/weather/sunlight.c similarity index 98% rename from test/weather_sunlight.c rename to test/battle/weather/sunlight.c index beba0e9b6..9d471332a 100644 --- a/test/weather_sunlight.c +++ b/test/battle/weather/sunlight.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test_battle.h" +#include "test/battle.h" // Please add Sunlight interactions with move, item and ability effects on their respective files. ASSUMPTIONS diff --git a/test/powder_moves.c b/test/powder_moves.c deleted file mode 100644 index a0185ad37..000000000 --- a/test/powder_moves.c +++ /dev/null @@ -1,47 +0,0 @@ -#include "global.h" -#include "test_battle.h" - -SINGLE_BATTLE_TEST("Powder Moves are blocked by Grass Types") -{ - GIVEN { - ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER); - ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS); - PLAYER(SPECIES_WYNAUT); - OPPONENT(SPECIES_ODDISH); - } WHEN { - TURN { MOVE(player, MOVE_STUN_SPORE); } - } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player); - MESSAGE("It doesn't affect Foe Oddish…"); - } -} - -SINGLE_BATTLE_TEST("Powder Moves are blocked by Ability Overcoat") -{ - GIVEN { - ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER); - PLAYER(SPECIES_WYNAUT); - OPPONENT(SPECIES_PINECO) { Ability(ABILITY_OVERCOAT); } - } WHEN { - TURN { MOVE(player, MOVE_STUN_SPORE); } - } SCENE { - ABILITY_POPUP(opponent, ABILITY_OVERCOAT); - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player); - MESSAGE("It doesn't affect Foe Pineco…"); - } -} - -SINGLE_BATTLE_TEST("Powder Moves are blocked by Item Safety Goggles") -{ - GIVEN { - ASSUME(gBattleMoves[MOVE_STUN_SPORE].flags & FLAG_POWDER); - ASSUME(gItems[ITEM_SAFETY_GOGGLES].holdEffect == HOLD_EFFECT_SAFETY_GOGGLES); - PLAYER(SPECIES_WYNAUT); - OPPONENT(SPECIES_ABRA) { Item(ITEM_SAFETY_GOGGLES); } - } WHEN { - TURN { MOVE(player, MOVE_STUN_SPORE); } - } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STUN_SPORE, player); - MESSAGE("Foe Abra is not affected thanks to its SafetyGoggles!"); - } -} diff --git a/test/random.c b/test/random.c index a56e91a10..202933beb 100644 --- a/test/random.c +++ b/test/random.c @@ -1,5 +1,5 @@ #include "global.h" -#include "test.h" +#include "test/test.h" #include "random.h" TEST("RandomUniform generates lo..hi") diff --git a/test/status1.c b/test/status1.c deleted file mode 100644 index c244b9a60..000000000 --- a/test/status1.c +++ /dev/null @@ -1,193 +0,0 @@ -#include "global.h" -#include "test_battle.h" - -SINGLE_BATTLE_TEST("Sleep prevents the battler from using a move") -{ - u32 turns; - PARAMETRIZE { turns = 1; } - PARAMETRIZE { turns = 2; } - PARAMETRIZE { turns = 3; } - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP_TURN(turns)); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - for (i = 0; i < turns; i++) - TURN { MOVE(player, MOVE_CELEBRATE); } - } SCENE { - for (i = 0; i < turns - 1; i++) - MESSAGE("Wobbuffet is fast asleep."); - MESSAGE("Wobbuffet woke up!"); - STATUS_ICON(player, none: TRUE); - MESSAGE("Wobbuffet used Celebrate!"); - } -} - -SINGLE_BATTLE_TEST("Poison deals 1/8th damage per turn") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_POISON); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - for (i = 0; i < 4; i++) - TURN {} - } SCENE { - s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 4; i++) - HP_BAR(player, damage: maxHP / 8); - } -} - -SINGLE_BATTLE_TEST("Burn deals 1/16th damage per turn") -{ - GIVEN { - ASSUME(B_BURN_DAMAGE >= GEN_LATEST); - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_BURN); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - for (i = 0; i < 4; i++) - TURN {} - } SCENE { - s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 4; i++) - HP_BAR(player, damage: maxHP / 16); - } -} - -SINGLE_BATTLE_TEST("Burn reduces Attack by 50%", s16 damage) -{ - bool32 burned; - PARAMETRIZE { burned = FALSE; } - PARAMETRIZE { burned = TRUE; } - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { if (burned) Status1(STATUS1_BURN); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_TACKLE); } - } SCENE { - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - EXPECT_MUL_EQ(results[0].damage, Q_4_12(0.5), results[1].damage); - } -} - -SINGLE_BATTLE_TEST("Freeze has a 20% chance of being thawed") -{ - PASSES_RANDOMLY(20, 100, RNG_FROZEN); - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_CELEBRATE); } - } SCENE { - STATUS_ICON(player, none: TRUE); - } -} - -SINGLE_BATTLE_TEST("Freeze is thawed by opponent's Fire-type attacks") -{ - GIVEN { - ASSUME(gBattleMoves[MOVE_EMBER].type == TYPE_FIRE); - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); } - } SCENE { - MESSAGE("Foe Wobbuffet used Ember!"); - MESSAGE("Wobbuffet was defrosted!"); - STATUS_ICON(player, none: TRUE); - } -} - -SINGLE_BATTLE_TEST("Freeze is thawed by user's Flame Wheel") -{ - GIVEN { - ASSUME(gBattleMoves[MOVE_FLAME_WHEEL].flags & FLAG_THAW_USER); - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_FLAME_WHEEL); } - } SCENE { - MESSAGE("Wobbuffet was defrosted by Flame Wheel!"); - STATUS_ICON(player, none: TRUE); - MESSAGE("Wobbuffet used Flame Wheel!"); - } -} - -SINGLE_BATTLE_TEST("Paralysis reduces Speed by 50%") -{ - u16 playerSpeed; - bool32 playerFirst; - PARAMETRIZE { playerSpeed = 98; playerFirst = FALSE; } - PARAMETRIZE { playerSpeed = 102; playerFirst = TRUE; } - GIVEN { - ASSUME(B_PARALYSIS_SPEED >= GEN_7); - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_PARALYSIS); Speed(playerSpeed); } - OPPONENT(SPECIES_WOBBUFFET) { Speed(50); } - } WHEN { - TURN { MOVE(player, MOVE_CELEBRATE); MOVE(opponent, MOVE_CELEBRATE); } - } SCENE { - if (playerFirst) { - ONE_OF { - MESSAGE("Wobbuffet used Celebrate!"); - MESSAGE("Wobbuffet is paralyzed! It can't move!"); - } - MESSAGE("Foe Wobbuffet used Celebrate!"); - } else { - MESSAGE("Foe Wobbuffet used Celebrate!"); - ONE_OF { - MESSAGE("Wobbuffet used Celebrate!"); - MESSAGE("Wobbuffet is paralyzed! It can't move!"); - } - } - } -} - -SINGLE_BATTLE_TEST("Paralysis has a 25% chance of skipping the turn") -{ - PASSES_RANDOMLY(25, 100, RNG_PARALYSIS); - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_PARALYSIS); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_CELEBRATE); } - } SCENE { - MESSAGE("Wobbuffet is paralyzed! It can't move!"); - } -} - -SINGLE_BATTLE_TEST("Bad poison deals 1/16th cumulative damage per turn") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_TOXIC_POISON); } - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - for (i = 0; i < 4; i++) - TURN {} - } SCENE { - s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 4; i++) - HP_BAR(player, damage: maxHP / 16 * (i + 1)); - } -} - -SINGLE_BATTLE_TEST("Bad poison cumulative damage resets on switch") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_TOXIC_POISON); } - PLAYER(SPECIES_WYNAUT); - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN {} - TURN {} - TURN { SWITCH(player, 1); } - TURN { SWITCH(player, 0); } - TURN {} - TURN {} - } SCENE { - s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); - for (i = 0; i < 2; i++) - HP_BAR(player, damage: maxHP / 16 * (i + 1)); - for (i = 0; i < 2; i++) - HP_BAR(player, damage: maxHP / 16 * (i + 1)); - } -} diff --git a/test/test_runner.c b/test/test_runner.c index 3f1352e5a..637ff0ed8 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -6,8 +6,8 @@ #include "main.h" #include "malloc.h" #include "random.h" -#include "test.h" #include "test_runner.h" +#include "test/test.h" #define TIMEOUT_SECONDS 55 diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 4de144c38..e65066a84 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -7,7 +7,7 @@ #include "main.h" #include "malloc.h" #include "random.h" -#include "test_battle.h" +#include "test/battle.h" #include "window.h" #if defined(__INTELLISENSE__) From 2d45b9b8fe44425ba958004dfcb40fb96ae61bb6 Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Mon, 14 Aug 2023 17:14:12 -0300 Subject: [PATCH 30/34] Corrected conditionals used for B_SPEED_BUFFING_RAPID_SPIN and I_GEM_BOOST_POWER (#3232) --- data/battle_scripts_1.s | 2 +- src/data/items.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5f38029a5..55e4cc351 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5128,7 +5128,7 @@ BattleScript_EffectBatonPass:: goto BattleScript_MoveEnd BattleScript_EffectRapidSpin:: -.if B_SPEED_BUFFING_RAPID_SPIN == GEN_8 +.if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8 attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring diff --git a/src/data/items.h b/src/data/items.h index 802cd325d..5e15b2734 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -6,7 +6,7 @@ #define EVO_HELD_ITEM_FIELD_FUNC ItemUseOutOfBattle_CannotUse #endif -#if I_GEM_BOOST_POWER >= GEN_5 +#if I_GEM_BOOST_POWER >= GEN_6 #define GEM_BOOST_PARAM 30 #else #define GEM_BOOST_PARAM 50 From dba28cf93f623064e986267de745c196f637efc7 Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Mon, 14 Aug 2023 19:10:15 -0400 Subject: [PATCH 31/34] Allow Z-Moves to be selected after Mega Evolution (#3233) * Allow Z-Moves to be selected after Mega Evolution * You cannot do Wish Mega Evolution at all if you hold a z crystal * Rebase to master --- src/battle_util.c | 26 +++++++++++++++----------- src/battle_z_move.c | 10 ---------- 2 files changed, 15 insertions(+), 21 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index b5fb8732d..91df461f0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10076,19 +10076,19 @@ bool32 CanMegaEvolve(u8 battlerId) species = GetMonData(mon, MON_DATA_SPECIES); itemId = GetMonData(mon, MON_DATA_HELD_ITEM); +#if DEBUG_BATTLE_MENU == TRUE + if (gBattleStruct->debugHoldEffects[battlerId]) + holdEffect = gBattleStruct->debugHoldEffects[battlerId]; + else +#endif + if (itemId == ITEM_ENIGMA_BERRY_E_READER) + holdEffect = gEnigmaBerries[battlerId].holdEffect; + else + holdEffect = ItemId_GetHoldEffect(itemId); + // Check if there is an entry in the evolution table for regular Mega Evolution. if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE) { - #if DEBUG_BATTLE_MENU == TRUE - if (gBattleStruct->debugHoldEffects[battlerId]) - holdEffect = gBattleStruct->debugHoldEffects[battlerId]; - else - #endif - if (itemId == ITEM_ENIGMA_BERRY_E_READER) - holdEffect = gEnigmaBerries[battlerId].holdEffect; - else - holdEffect = ItemId_GetHoldEffect(itemId); - // Can Mega Evolve via Mega Stone. if (holdEffect == HOLD_EFFECT_MEGA_STONE) return TRUE; @@ -10096,7 +10096,11 @@ bool32 CanMegaEvolve(u8 battlerId) // Check if there is an entry in the evolution table for Wish Mega Evolution. if (GetBattleFormChangeTargetSpecies(battlerId, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) - return TRUE; + { + // Can't Wish Mega Evolve if holding a Z Crystal. + if (holdEffect != HOLD_EFFECT_Z_CRYSTAL) + return TRUE; + } // No checks passed, the mon CAN'T mega evolve. return FALSE; diff --git a/src/battle_z_move.c b/src/battle_z_move.c index dec3701c0..a24ad8f38 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -159,7 +159,6 @@ void QueueZMove(u8 battlerId, u16 baseMove) bool32 IsViableZMove(u8 battlerId, u16 move) { struct Pokemon *mon; - struct MegaEvolutionData *mega = &(((struct ChooseMoveStruct *)(&gBattleResources->bufferA[gActiveBattler][4]))->mega); u8 battlerPosition = GetBattlerPosition(battlerId); u8 partnerPosition = GetBattlerPosition(BATTLE_PARTNER(battlerId)); u32 item; @@ -185,15 +184,6 @@ bool32 IsViableZMove(u8 battlerId, u16 move) if ((GetBattlerPosition(battlerId) == B_POSITION_PLAYER_LEFT || (!(gBattleTypeFlags & BATTLE_TYPE_MULTI) && GetBattlerPosition(battlerId) == B_POSITION_PLAYER_RIGHT)) && !CheckBagHasItem(ITEM_Z_POWER_RING, 1)) return FALSE; - if (mega->alreadyEvolved[battlerPosition]) - return FALSE; // Trainer has mega evolved - - if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) - { - if (IsPartnerMonFromSameTrainer(battlerId) && (mega->alreadyEvolved[partnerPosition] || (mega->toEvolve & gBitTable[BATTLE_PARTNER(battlerId)]))) - return FALSE; // Partner has mega evolved or is about to mega evolve - } - #if DEBUG_BATTLE_MENU == TRUE if (gBattleStruct->debugHoldEffects[battlerId]) holdEffect = gBattleStruct->debugHoldEffects[battlerId]; From cd90fdec5d33e9e17849f95a9647722bb3ff230a Mon Sep 17 00:00:00 2001 From: Philipp AUER Date: Thu, 17 Aug 2023 02:21:16 +0200 Subject: [PATCH 32/34] [Critical] fix memory corruption when handling trigger sprites (#3238) Co-authored-by: sbird --- src/battle_interface.c | 9 ++++----- src/battle_z_move.c | 7 +++++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/battle_interface.c b/src/battle_interface.c index 3e6029ab7..196e6050f 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -1409,11 +1409,10 @@ bool32 IsMegaTriggerSpriteActive(void) void HideMegaTriggerSprite(void) { - if (gBattleStruct->mega.triggerSpriteId != 0xFF) - { - ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0); - gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE; - } + if (gBattleStruct->mega.triggerSpriteId >= MAX_SPRITES) + return; + ChangeMegaTriggerSprite(gBattleStruct->mega.triggerSpriteId, 0); + gSprites[gBattleStruct->mega.triggerSpriteId].tHide = TRUE; } void HideTriggerSprites(void) diff --git a/src/battle_z_move.c b/src/battle_z_move.c index a24ad8f38..f17de921d 100644 --- a/src/battle_z_move.c +++ b/src/battle_z_move.c @@ -345,9 +345,12 @@ bool32 IsZMoveTriggerSpriteActive(void) void HideZMoveTriggerSprite(void) { - struct Sprite *sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId]; - sprite->tHide = TRUE; + struct Sprite *sprite; gBattleStruct->zmove.viable = FALSE; + if (gBattleStruct->zmove.triggerSpriteId >= MAX_SPRITES) + return; + sprite = &gSprites[gBattleStruct->zmove.triggerSpriteId]; + sprite->tHide = TRUE; } static void ShowZMoveTriggerSprite(u8 battlerId) From f2391cd82372ced4b2ca0b6a815a736444be1984 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Sat, 19 Aug 2023 17:20:40 +0200 Subject: [PATCH 33/34] Add female Basculegion to cry table (#3242) --- sound/cry_tables.inc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/cry_tables.inc b/sound/cry_tables.inc index 618c610e6..dc15e0f04 100644 --- a/sound/cry_tables.inc +++ b/sound/cry_tables.inc @@ -2080,6 +2080,8 @@ gCryTable:: @ Calyrex cry Cry_CalyrexIceRider cry Cry_CalyrexShadowRider + @ Basculegion + cry Cry_Basculegion .else @ Cramorant cry Cry_Unown @@ -2118,6 +2120,8 @@ gCryTable:: @ Calyrex cry Cry_Unown cry Cry_Unown + @ Basculegion + cry Cry_Unown .endif .align 2 @@ -4163,6 +4167,8 @@ gCryTable_Reverse:: @ Calyrex cry_reverse Cry_CalyrexIceRider cry_reverse Cry_CalyrexShadowRider + @ Basculegion + cry_reverse Cry_Basculegion .else cry_reverse Cry_Unown cry_reverse Cry_Unown @@ -4187,4 +4193,5 @@ gCryTable_Reverse:: cry_reverse Cry_Unown cry_reverse Cry_Unown cry_reverse Cry_Unown + cry_reverse Cry_Unown .endif From d360deb3b61885f9e14fc03ad5e79a92875ad66f Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 24 Aug 2023 20:44:50 -0400 Subject: [PATCH 34/34] 1.5.3 in templates --- .github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 3 ++- .github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 3 ++- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 3 ++- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 558f249e4..e838ba1f8 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.2 (Default) + - 1.5.3 (Default) - upcoming (Edge) + - 1.5.2 - 1.5.1 - 1.5.0 - 1.4.3 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 157177dce..d0653094c 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.2 (Default) + - 1.5.3 (Default) - upcoming (Edge) + - 1.5.2 - 1.5.1 - 1.5.0 - 1.4.3 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index a73096bab..51998d730 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -23,8 +23,9 @@ body: label: Version description: What version of pokeemerald-expansion are you using as a base? options: - - 1.5.2 (Default) + - 1.5.3 (Default) - upcoming (Edge) + - 1.5.2 - 1.5.1 - 1.5.0 - 1.4.3