From 7612e386419ef913bda5a62a5c8f234190542bb0 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sun, 26 Jan 2025 20:52:50 -0500 Subject: [PATCH 01/50] fix: improved FadeScreenHardware during fade-in --- src/palette.c | 41 +++++++++++++++++++++++++++++------------ src/scrcmd.c | 2 ++ 2 files changed, 31 insertions(+), 12 deletions(-) diff --git a/src/palette.c b/src/palette.c index 303e6ced42..59fbdcfab4 100644 --- a/src/palette.c +++ b/src/palette.c @@ -2,8 +2,10 @@ #include "palette.h" #include "util.h" #include "decompress.h" +#include "field_weather.h" #include "gpu_regs.h" #include "task.h" +#include "constants/field_weather.h" #include "constants/rgb.h" enum @@ -967,25 +969,41 @@ static void UpdateBlendRegisters(void) { SetGpuReg(REG_OFFSET_BLDCNT, (u16)gPaletteFade_blendCnt); SetGpuReg(REG_OFFSET_BLDY, gPaletteFade.y); - // If fade-out, also adjust BLDALPHA and DISPCNT - if (!gPaletteFade.yDec /*&& gPaletteFade.mode == HARDWARE_FADE*/) { + // if TGT2 enabled, also adjust BLDALPHA and DISPCNT + if (((u16)gPaletteFade_blendCnt) & BLDCNT_TGT2_ALL) { u16 bldAlpha = GetGpuReg(REG_OFFSET_BLDALPHA); u8 tgt1 = BLDALPHA_TGT1(bldAlpha); u8 tgt2 = BLDALPHA_TGT2(bldAlpha); - u8 bldFade; + u8 mode = (gPaletteFade_blendCnt & BLDCNT_EFFECT_EFF_MASK) == BLDCNT_EFFECT_LIGHTEN ? FADE_FROM_WHITE : FADE_FROM_BLACK; + if (!gPaletteFade.yDec) + mode++; - switch (gPaletteFade_blendCnt & BLDCNT_EFFECT_EFF_MASK) + ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); + + switch (mode) { - // FADE_TO_BLACK - case BLDCNT_EFFECT_DARKEN: - bldFade = BLDALPHA_TGT1(max(0, 16 - gPaletteFade.y)); + case FADE_FROM_BLACK: + // increment each target until reaching weather's values SetGpuReg( REG_OFFSET_BLDALPHA, - BLDALPHA_BLEND(min(tgt1, bldFade), min(tgt2, bldFade)) + BLDALPHA_BLEND( + min(++tgt1, gWeatherPtr->currBlendEVA), + min(++tgt2, gWeatherPtr->currBlendEVB) + ) ); break; - // FADE_TO_WHITE - case BLDCNT_EFFECT_LIGHTEN: + case FADE_TO_BLACK: + bldAlpha = BLDALPHA_TGT1(max(0, 16 - gPaletteFade.y)); + SetGpuReg( + REG_OFFSET_BLDALPHA, + BLDALPHA_BLEND(min(tgt1, bldAlpha), min(tgt2, bldAlpha)) + ); + break; + // Not handled; blend sprites will pop in, + // but the effect coming from white looks okay + // case FADE_FROM_WHITE: + // break; + case FADE_TO_WHITE: SetGpuReg( REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(min(++tgt1, 31), min(++tgt2, 31)) @@ -996,8 +1014,7 @@ static void UpdateBlendRegisters(void) SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); break; } - } else - ClearGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_FORCED_BLANK); + } if (gPaletteFade.hardwareFadeFinishing) { diff --git a/src/scrcmd.c b/src/scrcmd.c index edca8dbbbe..b6f15b2fbe 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -663,6 +663,8 @@ bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx) switch (mode) { case FADE_FROM_BLACK: + SetGpuReg(REG_OFFSET_BLDALPHA, BLDALPHA_BLEND(0, 0)); + break; case FADE_FROM_WHITE: // Restore last weather blend before fading in, // since BLDALPHA was modified by fade-out From b464fdbbde0ef50e816d203252ecb1f4d76189d4 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 13 Feb 2025 15:13:04 -0500 Subject: [PATCH 02/50] Fix collision comparison in PlayerNotOnBikeMoving --- src/field_player_avatar.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index 1f0708af22..6a1df01b47 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -620,9 +620,27 @@ static void PlayerNotOnBikeMoving(u8 direction, u16 heldKeys) } else { - u8 adjustedCollision = collision - COLLISION_STOP_SURFING; - if (adjustedCollision > 3) + // Player collided with something. Certain collisions have special handling that precludes the normal collision effect. + // COLLISION_STOP_SURFING and COLLISION_PUSHED_BOULDER's effects are started by CheckForObjectEventCollision. + // COLLISION_LEDGE_JUMP's effect is handled further up in this function, so it will never reach this point. + // COLLISION_ROTATING_GATE is unusual however, this was probably included by mistake. When the player walks into a + // rotating gate that cannot rotate there is no additional handling, it's just a regular collision. Its exclusion here + // means that the player avatar won't update if they encounter this kind of collision. This has two noticeable effects: + // - Colliding with it head-on stops the player dead, rather than playing the walking animation and playing a bump sound effect + // - Colliding with it by changing direction won't turn the player avatar, their walking animation will just speed up. +#ifdef BUGFIX + if (collision != COLLISION_STOP_SURFING + && collision != COLLISION_LEDGE_JUMP + && collision != COLLISION_PUSHED_BOULDER) +#else + if (collision != COLLISION_STOP_SURFING + && collision != COLLISION_LEDGE_JUMP + && collision != COLLISION_PUSHED_BOULDER + && collision != COLLISION_ROTATING_GATE) +#endif + { PlayerNotOnBikeCollide(direction); + } return; } } From 73e891a88a61dfdf3ed11d5c91cad80e5349d519 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sat, 8 Mar 2025 02:15:32 -0500 Subject: [PATCH 03/50] fix: rainy castform is no longer a Ninja Boy on return-to-field --- src/event_object_movement.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 513931c035..633167f4e2 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2772,13 +2772,13 @@ const struct ObjectEventGraphicsInfo *GetObjectEventGraphicsInfo(u16 graphicsId) if (graphicsId >= OBJ_EVENT_GFX_VARS && graphicsId <= OBJ_EVENT_GFX_VAR_F) graphicsId = VarGetObjectEventGraphicsId(graphicsId - OBJ_EVENT_GFX_VARS); - if (graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG) - graphicsId -= SPECIES_SHINY_TAG; // graphicsId may contain mon form info if (graphicsId > OBJ_EVENT_GFX_SPECIES_MASK) { form = graphicsId >> OBJ_EVENT_GFX_SPECIES_BITS; graphicsId = graphicsId & OBJ_EVENT_GFX_SPECIES_MASK; } + if (graphicsId >= OBJ_EVENT_GFX_MON_BASE + SPECIES_SHINY_TAG) + graphicsId -= SPECIES_SHINY_TAG; if (graphicsId == OBJ_EVENT_GFX_BARD) { return gMauvilleOldManGraphicsInfoPointers[GetCurrentMauvilleOldMan()]; From e2e3438674f1c12df631ba13c9df05ddc83653d0 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Fri, 20 Jun 2025 15:33:12 -0400 Subject: [PATCH 04/50] Add missing uses of LOCALID_NONE for trainerbattle --- asm/macros/event.inc | 18 +++++++++--------- .../scripts.inc | 2 +- .../MossdeepCity_SpaceCenter_2F/scripts.inc | 4 ++-- data/scripts/trainer_hill.inc | 2 +- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 6f17460d43..797d549dc9 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -747,11 +747,11 @@ @ When used with an event script, you can also pass in an optional flag to disable music .macro trainerbattle_single trainer:req, intro_text:req, lose_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_SINGLE, \trainer, 0, \intro_text, \lose_text + trainerbattle TRAINER_BATTLE_SINGLE, \trainer, LOCALID_NONE, \intro_text, \lose_text .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT, \trainer, LOCALID_NONE, \intro_text, \lose_text, \event_script .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_NO_MUSIC, \trainer, LOCALID_NONE, \intro_text, \lose_text, \event_script .endif .endm @@ -759,27 +759,27 @@ @ and an optional event script. When used with an event script you can pass in an optional flag to disable music .macro trainerbattle_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req, event_script=FALSE, music=TRUE .if \event_script == FALSE - trainerbattle TRAINER_BATTLE_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text + trainerbattle TRAINER_BATTLE_DOUBLE, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text .elseif \music == TRUE - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script .else - trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script + trainerbattle TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE_NO_MUSIC, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text, \event_script .endif .endm @ Starts a rematch battle. Takes a trainer, intro text and loss text .macro trainerbattle_rematch trainer:req, intro_text:req, lose_text:req - trainerbattle TRAINER_BATTLE_REMATCH, \trainer, 0, \intro_text, \lose_text + trainerbattle TRAINER_BATTLE_REMATCH, \trainer, LOCALID_NONE, \intro_text, \lose_text .endm @ Starts a rematch double battle. Takes a trainer, intro text, loss text, and text for when you have too few pokemon .macro trainerbattle_rematch_double trainer:req, intro_text:req, lose_text:req, not_enough_pkmn_text:req - trainerbattle TRAINER_BATTLE_REMATCH_DOUBLE, \trainer, 0, \intro_text, \lose_text, \not_enough_pkmn_text + trainerbattle TRAINER_BATTLE_REMATCH_DOUBLE, \trainer, LOCALID_NONE, \intro_text, \lose_text, \not_enough_pkmn_text .endm @ Starts a trainer battle, skipping intro text. Takes a trainer and loss text .macro trainerbattle_no_intro trainer:req, lose_text:req - trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, \trainer, 0, \lose_text + trainerbattle TRAINER_BATTLE_SINGLE_NO_INTRO_TEXT, \trainer, LOCALID_NONE, \lose_text .endm diff --git a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc index ba9d996706..021f373be2 100644 --- a/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc +++ b/data/maps/BattleFrontier_BattlePyramidFloor/scripts.inc @@ -105,7 +105,7 @@ BattlePyramid_WarpToTop:: @ TRAINER_PHILLIP is used as a placeholder BattlePyramid_TrainerBattle:: - trainerbattle TRAINER_BATTLE_PYRAMID, TRAINER_PHILLIP, 0, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText + trainerbattle TRAINER_BATTLE_PYRAMID, TRAINER_PHILLIP, LOCALID_NONE, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText pyramid_showhint waitmessage waitbuttonpress diff --git a/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc b/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc index cbb9cba9af..81ae88e42f 100644 --- a/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc +++ b/data/maps/MossdeepCity_SpaceCenter_2F/scripts.inc @@ -329,11 +329,11 @@ MossdeepCity_SpaceCenter_2F_EventScript_StevenFacePlayerWest:: return MossdeepCity_SpaceCenter_2F_EventScript_MaxieTrainer:: - trainerbattle TRAINER_BATTLE_SET_TRAINER_A, TRAINER_MAXIE_MOSSDEEP, 0, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand + trainerbattle TRAINER_BATTLE_SET_TRAINER_A, TRAINER_MAXIE_MOSSDEEP, LOCALID_NONE, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand, MossdeepCity_SpaceCenter_2F_Text_JustWantToExpandLand end MossdeepCity_SpaceCenter_2F_EventScript_TabithaTrainer:: - trainerbattle TRAINER_BATTLE_SET_TRAINER_B, TRAINER_TABITHA_MOSSDEEP, 0, MossdeepCity_SpaceCenter_Text_TabithaDefeat, MossdeepCity_SpaceCenter_Text_TabithaDefeat + trainerbattle TRAINER_BATTLE_SET_TRAINER_B, TRAINER_TABITHA_MOSSDEEP, LOCALID_NONE, MossdeepCity_SpaceCenter_Text_TabithaDefeat, MossdeepCity_SpaceCenter_Text_TabithaDefeat end MossdeepCity_SpaceCenter_2F_EventScript_RivalRayquazaCall:: diff --git a/data/scripts/trainer_hill.inc b/data/scripts/trainer_hill.inc index 04bbe05e5a..d51d1f5098 100644 --- a/data/scripts/trainer_hill.inc +++ b/data/scripts/trainer_hill.inc @@ -60,7 +60,7 @@ TrainerHill_1F_Movement_SetInvisible:: @ TRAINER_PHILLIP is an actual Trainer on the SS Tidal, but is used as a placeholder here TrainerHill_EventScript_TrainerBattle:: - trainerbattle TRAINER_BATTLE_HILL, TRAINER_PHILLIP, 0, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText + trainerbattle TRAINER_BATTLE_HILL, TRAINER_PHILLIP, LOCALID_NONE, BattleFacility_TrainerBattle_PlaceholderText, BattleFacility_TrainerBattle_PlaceholderText trainerhill_postbattletext waitmessage waitbuttonpress From 01fc7e76efc6c8e6790e9585fa6e7056a8841478 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sun, 22 Jun 2025 11:26:31 +0200 Subject: [PATCH 05/50] Fix wrong keep temps files directory in makefile --- Makefile | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index f4aecdc77b..354c335235 100644 --- a/Makefile +++ b/Makefile @@ -313,10 +313,10 @@ ifneq ($(KEEP_TEMPS),1) @echo "$(CC1) -o $@ $<" @$(CPP) $(CPPFLAGS) $< | $(PREPROC) -i $< charmap.txt | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ - else - @$(CPP) $(CPPFLAGS) $< -o $*.i - @$(PREPROC) $*.i charmap.txt | $(CC1) $(CFLAGS) -o $*.s - @echo -e ".text\n\t.align\t2, 0\n" >> $*.s - $(AS) $(ASFLAGS) -o $@ $*.s + @$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i + @$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s + @echo -e ".text\n\t.align\t2, 0\n" >> $(C_BUILDDIR)/$*.s + $(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s endif $(C_BUILDDIR)/%.d: $(C_SUBDIR)/%.c From 53f8ae11ff3ccc5333cc70d581b2ac5fd4853883 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 23 Jun 2025 01:48:37 +0200 Subject: [PATCH 06/50] Move gTradePlatform_Tilemap to header (#2088) --- include/trade.h | 1 + src/egg_hatch.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/include/trade.h b/include/trade.h index 33191f0ac6..24de69b036 100644 --- a/include/trade.h +++ b/include/trade.h @@ -7,6 +7,7 @@ extern struct Mail gTradeMail[PARTY_SIZE]; extern u8 gSelectedTradeMonPositions[2]; +extern const u16 gTradePlatform_Tilemap[]; extern const struct WindowTemplate gTradeEvolutionSceneYesNoWindowTemplate; s32 GetGameProgressForLinkTrade(void); diff --git a/src/egg_hatch.c b/src/egg_hatch.c index abf1aff841..5aa955d7e9 100644 --- a/src/egg_hatch.c +++ b/src/egg_hatch.c @@ -33,6 +33,7 @@ #include "naming_screen.h" #include "pokemon_storage_system.h" #include "field_screen_effect.h" +#include "trade.h" #include "data.h" #include "battle.h" // to get rid of later #include "constants/rgb.h" @@ -62,7 +63,6 @@ struct EggHatchData u8 textColor[3]; }; -extern const u32 gTradePlatform_Tilemap[]; extern const u8 gText_HatchedFromEgg[]; extern const u8 gText_NicknameHatchPrompt[]; From 0ccf797cceddd45790153fd85c3e9c333d1aefda Mon Sep 17 00:00:00 2001 From: i0brendan0 <19826742+i0brendan0@users.noreply.github.com> Date: Mon, 23 Jun 2025 08:05:01 -0500 Subject: [PATCH 07/50] Fixes Roamers not saving shininess (#7185) --- include/global.h | 3 ++- src/roamer.c | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/global.h b/include/global.h index 057a53b498..b58ef3518b 100644 --- a/include/global.h +++ b/include/global.h @@ -680,7 +680,8 @@ struct Roamer /*0x12*/ u8 tough; /*0x13*/ bool8 active; /*0x14*/ u8 statusB; // Stores frostbite - /*0x14*/ u8 filler[0x7]; + /*0x15*/ bool8 shiny; + /*0x16*/ u8 filler[0x6]; }; struct RamScriptData diff --git a/src/roamer.c b/src/roamer.c index 9bca6fdc45..0fc86b6711 100644 --- a/src/roamer.c +++ b/src/roamer.c @@ -113,6 +113,7 @@ static void CreateInitialRoamerMon(u8 index, u16 species, u8 level) ROAMER(index)->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE); ROAMER(index)->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART); ROAMER(index)->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH); + ROAMER(index)->shiny = GetMonData(&gEnemyParty[0], MON_DATA_IS_SHINY); ROAMER(index)->active = TRUE; sRoamerLocation[index][MAP_GRP] = ROAMER_MAP_GROUP; sRoamerLocation[index][MAP_NUM] = sRoamerLocations[Random() % NUM_LOCATION_SETS][0]; @@ -243,8 +244,6 @@ void CreateRoamerMonInstance(u32 roamerIndex) struct Pokemon *mon = &gEnemyParty[0]; ZeroEnemyPartyMons(); CreateMonWithIVsPersonality(mon, ROAMER(roamerIndex)->species, ROAMER(roamerIndex)->level, ROAMER(roamerIndex)->ivs, ROAMER(roamerIndex)->personality); - // The roamer's status field is u16, but SetMonData expects status to be u32, so will set the roamer's status - // using the status field and the following 3 bytes (cool, beauty, and cute). SetMonData(mon, MON_DATA_STATUS, &status); SetMonData(mon, MON_DATA_HP, &ROAMER(roamerIndex)->hp); SetMonData(mon, MON_DATA_COOL, &ROAMER(roamerIndex)->cool); @@ -252,6 +251,7 @@ void CreateRoamerMonInstance(u32 roamerIndex) SetMonData(mon, MON_DATA_CUTE, &ROAMER(roamerIndex)->cute); SetMonData(mon, MON_DATA_SMART, &ROAMER(roamerIndex)->smart); SetMonData(mon, MON_DATA_TOUGH, &ROAMER(roamerIndex)->tough); + SetMonData(mon, MON_DATA_IS_SHINY, &ROAMER(roamerIndex)->shiny); } bool8 TryStartRoamerEncounter(void) From 456a8f6aa06d86475252d931bbb41250fd14dc9a Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Mon, 23 Jun 2025 06:40:13 -0700 Subject: [PATCH 08/50] Update the description of OW_OBJECT_VANILLA_SHADOWS (#7184) --- include/config/overworld.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config/overworld.h b/include/config/overworld.h index 50cad2f5fe..fa87da4d83 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -99,7 +99,7 @@ #define OW_ENABLE_DNS TRUE // If set to TRUE, the overworld will be tinted depending on time of day. // Object Event Shadows -#define OW_OBJECT_VANILLA_SHADOWS FALSE // In vanilla shadows in the overworld are only shown when jumping. +#define OW_OBJECT_VANILLA_SHADOWS FALSE // When FALSE, every object in the overworld has a shadow. WARNING: This means every object will take up two sprites instead of one. When TRUE, an object's shadow is only shown when jumping. // Overworld flags // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. From a75a49710fd4ab25fe9ac548c70f8b971ca21116 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 23 Jun 2025 09:46:49 -0400 Subject: [PATCH 09/50] Fixed debug flag menu sound (#7190) --- src/debug.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/debug.c b/src/debug.c index 5a585ef62d..6694266e08 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2527,6 +2527,7 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) { if (JOY_NEW(A_BUTTON)) { + PlaySE(SE_SELECT); FlagToggle(gTasks[taskId].tInput); } else if (JOY_NEW(B_BUTTON)) @@ -2536,7 +2537,6 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) return; } - PlaySE(SE_SELECT); Debug_HandleInput_Numeric(taskId, 1, FLAGS_COUNT - 1, DEBUG_NUMBER_DIGITS_FLAGS); if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) From e449a612f5c87ba45217aa9009e48621c6ca3b67 Mon Sep 17 00:00:00 2001 From: Pablo Pena Date: Tue, 24 Jun 2025 01:45:12 +0800 Subject: [PATCH 10/50] fix: use BackPickId to calculate player intro ball throw animation palette (#7193) --- src/battle_controller_player.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index f437d8ee13..a0b4e73ece 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2330,7 +2330,8 @@ static void PlayerHandleOneReturnValue_Duplicate(u32 battler) static void PlayerHandleIntroTrainerBallThrow(u32 battler) { - const u16 *trainerPal = gTrainerBacksprites[gSaveBlock2Ptr->playerGender].palette.data; + const u32 paletteIndex = PlayerGetTrainerBackPicId(); + const u16 *trainerPal = gTrainerBacksprites[paletteIndex].palette.data; BtlController_HandleIntroTrainerBallThrow(battler, 0xD6F8, trainerPal, 31, Intro_TryShinyAnimShowHealthbox); } From e1b83d605698f22bee4ebcb1717378a1a10f3717 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Mon, 23 Jun 2025 21:31:18 +0200 Subject: [PATCH 11/50] Match graphics declarations with externs (#2089) --- include/graphics.h | 88 ++++++++++++++++----------------- src/data/graphics/intro_scene.h | 2 +- src/graphics.c | 11 +++-- src/intro.c | 29 ++++++----- src/mail.c | 4 +- src/naming_screen.c | 2 +- 6 files changed, 70 insertions(+), 66 deletions(-) diff --git a/include/graphics.h b/include/graphics.h index 7f0eb7bda5..14f2f5e744 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -2,7 +2,7 @@ #define GUARD_GRAPHICS_H // overworld -extern const u32 gMessageBox_Gfx[]; +extern const u8 gMessageBox_Gfx[]; extern const u16 gMessageBox_Pal[]; // pokeballs @@ -3286,17 +3286,17 @@ extern const u32 gBattleEnvironmentPalette_StadiumWallace[]; extern const u32 gPokedexInterface_Gfx[]; extern const u16 gPokedexBgHoenn_Pal[]; extern const u32 gPokedexMenu_Gfx[]; -extern const u8 gPokedexList_Tilemap[]; -extern const u8 gPokedexListUnderlay_Tilemap[]; -extern const u8 gPokedexStartMenuMain_Tilemap[]; -extern const u8 gPokedexStartMenuSearchResults_Tilemap[]; +extern const u32 gPokedexList_Tilemap[]; +extern const u32 gPokedexListUnderlay_Tilemap[]; +extern const u32 gPokedexStartMenuMain_Tilemap[]; +extern const u32 gPokedexStartMenuSearchResults_Tilemap[]; extern const u16 gPokedexSearchResults_Pal[]; extern const u16 gPokedexBgNational_Pal[]; -extern const u8 gPokedexInfoScreen_Tilemap[]; -extern const u8 gPokedexCryScreen_Tilemap[]; -extern const u8 gPokedexSizeScreen_Tilemap[]; -extern const u8 gPokedexScreenSelectBarMain_Tilemap[]; -extern const u8 gPokedexScreenSelectBarSubmenu_Tilemap[]; +extern const u32 gPokedexInfoScreen_Tilemap[]; +extern const u32 gPokedexCryScreen_Tilemap[]; +extern const u32 gPokedexSizeScreen_Tilemap[]; +extern const u32 gPokedexScreenSelectBarMain_Tilemap[]; +extern const u32 gPokedexScreenSelectBarSubmenu_Tilemap[]; extern const u16 gPokedexCaughtScreen_Pal[]; extern const u32 gPokedexSearchMenu_Gfx[]; extern const u32 gPokedexSearchMenuHoenn_Tilemap[]; @@ -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 ALIGNED(2) gIntro3Bg_Pal[0x200]; +extern const u16 gIntro3Bg_Pal[16][16]; extern const u32 gIntroKyogre_Gfx[]; extern const u32 gIntroKyogre_Tilemap[]; extern const u32 gIntroKyogreBg_Tilemap[]; @@ -4066,9 +4066,9 @@ extern const u8 gHealthboxElementsGfxTable[][32]; extern const u16 gNamingScreenMenu_Pal[6][16]; extern const u32 gNamingScreenMenu_Gfx[]; extern const u32 gNamingScreenBackground_Tilemap[]; -extern const u8 gNamingScreenKeyboardUpper_Tilemap[]; -extern const u8 gNamingScreenKeyboardLower_Tilemap[]; -extern const u8 gNamingScreenKeyboardSymbols_Tilemap[]; +extern const u32 gNamingScreenKeyboardUpper_Tilemap[]; +extern const u32 gNamingScreenKeyboardLower_Tilemap[]; +extern const u32 gNamingScreenKeyboardSymbols_Tilemap[]; extern const u32 gNamingScreenPageSwapFrame_Gfx[]; extern const u32 gNamingScreenBackButton_Gfx[]; extern const u32 gNamingScreenOKButton_Gfx[]; @@ -4791,7 +4791,7 @@ extern const u32 gContestAudienceTilemap[]; extern const u32 gContestInterfaceAudiencePalette[]; extern const u32 gContestInterfaceTilemap[]; extern const u32 gContestCurtainTilemap[]; -extern const u32 gContestSliderHeart_Gfx[]; +extern const u8 gContestSliderHeart_Gfx[]; extern const u32 gContestNextTurnGfx[]; extern const u16 gContestPal[]; extern const u32 gContestFaces_Gfx[]; @@ -4817,11 +4817,11 @@ extern const u16 gUsePokeblockGraph_Pal[]; extern const u16 gUsePokeblockNatureWin_Pal[]; // Berry blender -extern const u32 gBerryBlenderPlayerArrow_Gfx[]; -extern const u32 gBerryBlenderStart_Gfx[]; -extern const u32 gBerryBlenderScoreSymbols_Gfx[]; -extern const u32 gBerryBlenderParticles_Gfx[]; -extern const u32 gBerryBlenderCountdownNumbers_Gfx[]; +extern const u8 gBerryBlenderPlayerArrow_Gfx[]; +extern const u8 gBerryBlenderStart_Gfx[]; +extern const u8 gBerryBlenderScoreSymbols_Gfx[]; +extern const u8 gBerryBlenderParticles_Gfx[]; +extern const u8 gBerryBlenderCountdownNumbers_Gfx[]; extern const u16 gBerryBlenderMiscPalette[]; extern const u16 gBerryBlenderArrowPalette[]; extern const u32 gBerryBlenderCenter_Gfx[]; @@ -5042,30 +5042,30 @@ extern const u16 gMailPalette_Tropic[]; extern const u16 gMailPalette_Dream[]; extern const u16 gMailPalette_Fab[]; extern const u16 gMailPalette_Retro[]; -extern const u8 gMailTiles_Orange[]; -extern const u8 gMailTilemap_Orange[]; -extern const u8 gMailTiles_Harbor[]; -extern const u8 gMailTilemap_Harbor[]; -extern const u8 gMailTiles_Glitter[]; -extern const u8 gMailTilemap_Glitter[]; -extern const u8 gMailTiles_Mech[]; -extern const u8 gMailTilemap_Mech[]; -extern const u8 gMailTiles_Wood[]; -extern const u8 gMailTilemap_Wood[]; -extern const u8 gMailTiles_Wave[]; -extern const u8 gMailTilemap_Wave[]; -extern const u8 gMailTiles_Bead[]; -extern const u8 gMailTilemap_Bead[]; -extern const u8 gMailTiles_Shadow[]; -extern const u8 gMailTilemap_Shadow[]; -extern const u8 gMailTiles_Tropic[]; -extern const u8 gMailTilemap_Tropic[]; -extern const u8 gMailTiles_Dream[]; -extern const u8 gMailTilemap_Dream[]; -extern const u8 gMailTiles_Fab[]; -extern const u8 gMailTilemap_Fab[]; -extern const u8 gMailTiles_Retro[]; -extern const u8 gMailTilemap_Retro[]; +extern const u32 gMailTiles_Orange[]; +extern const u32 gMailTilemap_Orange[]; +extern const u32 gMailTiles_Harbor[]; +extern const u32 gMailTilemap_Harbor[]; +extern const u32 gMailTiles_Glitter[]; +extern const u32 gMailTilemap_Glitter[]; +extern const u32 gMailTiles_Mech[]; +extern const u32 gMailTilemap_Mech[]; +extern const u32 gMailTiles_Wood[]; +extern const u32 gMailTilemap_Wood[]; +extern const u32 gMailTiles_Wave[]; +extern const u32 gMailTilemap_Wave[]; +extern const u32 gMailTiles_Bead[]; +extern const u32 gMailTilemap_Bead[]; +extern const u32 gMailTiles_Shadow[]; +extern const u32 gMailTilemap_Shadow[]; +extern const u32 gMailTiles_Tropic[]; +extern const u32 gMailTilemap_Tropic[]; +extern const u32 gMailTiles_Dream[]; +extern const u32 gMailTilemap_Dream[]; +extern const u32 gMailTiles_Fab[]; +extern const u32 gMailTilemap_Fab[]; +extern const u32 gMailTiles_Retro[]; +extern const u32 gMailTilemap_Retro[]; extern const u8 gMonMarkingsMenu_Gfx[]; extern const u16 gMonMarkingsMenu_Pal[]; diff --git a/src/data/graphics/intro_scene.h b/src/data/graphics/intro_scene.h index cb7706c9a3..8b17b00346 100644 --- a/src/data/graphics/intro_scene.h +++ b/src/data/graphics/intro_scene.h @@ -1,6 +1,6 @@ const u16 gIntroGameFreakTextFade_Pal[] = INCBIN_U16("graphics/intro/scene_1/text.gbapal"); // game freak text blue fade const u16 gIntroPlayer_Pal[] = INCBIN_U16("graphics/intro/scene_2/player.gbapal"); -const u16 gIntro3Bg_Pal[] = INCBIN_U16("graphics/intro/scene_3/bg.gbapal"); +const u16 gIntro3Bg_Pal[16][16] = INCBIN_U16("graphics/intro/scene_3/bg.gbapal"); const u16 gIntroVolbeat_Pal[] = INCBIN_U16("graphics/intro/scene_2/volbeat.gbapal"); const u16 gIntroTorchic_Pal[] = INCBIN_U16("graphics/intro/scene_2/torchic.gbapal"); const u16 gIntroManectric_Pal[] = INCBIN_U16("graphics/intro/scene_2/manectric.gbapal"); diff --git a/src/graphics.c b/src/graphics.c index 9179b0fd7d..3d7f2fa08b 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -1,4 +1,5 @@ #include "global.h" +#include "graphics.h" const u32 gBattleTextboxTiles[] = INCBIN_U32("graphics/battle_interface/textbox.4bpp.lz"); const u32 gBattleTextboxPalette[] = INCBIN_U32("graphics/battle_interface/textbox.gbapal.lz"); @@ -354,7 +355,7 @@ const u16 gBattleInterface_BallStatusBarPal[] = INCBIN_U16("graphics/battle_inte const u16 gBattleInterface_BallDisplayPal[] = INCBIN_U16("graphics/battle_interface/ball_display.gbapal"); -const u8 gHealthboxElementsGfxTable[] = INCBIN_U8("graphics/battle_interface/hpbar.4bpp", +const u8 gHealthboxElementsGfxTable[][32] = INCBIN_U8("graphics/battle_interface/hpbar.4bpp", "graphics/battle_interface/expbar.4bpp", "graphics/battle_interface/status.4bpp", "graphics/battle_interface/misc.4bpp", @@ -971,7 +972,7 @@ const u16 gTilesetAnims_BattleDomePals0_3[] = INCBIN_U16("graphics/battle_fronti static const u16 sUnused0[] = {0x13F, 0x119, 0x113, 0x10E}; -const u16 gBattlePyramidFloor_Pal[] = INCBIN_U16("graphics/battle_frontier/pyramid_floor.gbapal"); +const u16 gBattlePyramidFloor_Pal[][16] = INCBIN_U16("graphics/battle_frontier/pyramid_floor.gbapal"); const u32 gMultiBattleIntroBg_Opponent_Tilemap[] = INCBIN_U32("graphics/battle_frontier/multi_battle_intro_bg_opponent.bin.lz"); const u32 gMultiBattleIntroBg_Player_Tilemap[] = INCBIN_U32("graphics/battle_frontier/multi_battle_intro_bg_player.bin.lz"); @@ -1514,12 +1515,12 @@ const u16 gTitleScreenPressStartPal[] = INCBIN_U16("graphics/title_screen/p const u32 gTitleScreenPressStartGfx[] = INCBIN_U32("graphics/title_screen/press_start.4bpp.lz"); const u32 gTitleScreenPokemonLogoTilemap[] = INCBIN_U32("graphics/title_screen/pokemon_logo.bin.lz"); -const u16 gFrontierPassBg_Pal[] = INCBIN_U16("graphics/frontier_pass/bg.gbapal"); // 8 x 16 +const u16 gFrontierPassBg_Pal[][16] = INCBIN_U16("graphics/frontier_pass/bg.gbapal"); // 8 x 16 const u32 gFrontierPassBg_Gfx[] = INCBIN_U32("graphics/frontier_pass/bg.4bpp.lz"); const u32 gFrontierPassMapAndCard_Gfx[] = INCBIN_U32("graphics/frontier_pass/map_and_card.8bpp.lz"); const u32 gFrontierPassBg_Tilemap[] = INCBIN_U32("graphics/frontier_pass/bg.bin.lz"); -const u16 gFrontierPassCancelButton_Tilemap[] = INCBIN_U16("graphics/frontier_pass/cancel.bin"); -const u16 gFrontierPassCancelButtonHighlighted_Tilemap[] = INCBIN_U16("graphics/frontier_pass/cancel_highlighted.bin"); +const u32 gFrontierPassCancelButton_Tilemap[] = INCBIN_U32("graphics/frontier_pass/cancel.bin"); +const u32 gFrontierPassCancelButtonHighlighted_Tilemap[] = INCBIN_U32("graphics/frontier_pass/cancel_highlighted.bin"); // Berry Crush const u16 gBerryCrush_Crusher_Pal[] = INCBIN_U16("graphics/berry_crush/crusher.gbapal"); diff --git a/src/intro.c b/src/intro.c index 549acc4b7d..169ef002a6 100644 --- a/src/intro.c +++ b/src/intro.c @@ -1866,12 +1866,15 @@ static void Task_Scene3_StartGroudon(u8 taskId) #define tTrigIdx data[6] // Re-used #define tPalIdx data[7] +// Treats gIntro3Bg_Pal as u8* and iterates by 1 +#define INTRO3_RAW_PTR(palId)(((void *) &gIntro3Bg_Pal) + palId) + static void Task_Scene3_Groudon(u8 taskId) { s16 *data = gTasks[taskId].data; tTimer++; - if ((u16)(tState - 1) < 7 && tTimer % 2 == 0) + if ((tState >= 1 && tState <= 7) && tTimer % 2 == 0) tYShake ^= 3; PanFadeAndZoomScreen(tScreenX, tScreenY + tYShake, tZoom, 0); switch (tState) @@ -1890,7 +1893,7 @@ static void Task_Scene3_Groudon(u8 taskId) if (--tDelay == 0) { tDelay = 2; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); tPalIdx += 2; if (tPalIdx == 0x1EC) tState++; @@ -1907,7 +1910,7 @@ static void Task_Scene3_Groudon(u8 taskId) if (--tDelay == 0) { tDelay = 2; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(1) + 15], PLTT_SIZEOF(1)); tPalIdx -= 2; if (tPalIdx == 0x1E0) { @@ -2149,7 +2152,7 @@ static void Task_Scene3_Kyogre(u8 taskId) if (--tDelay == 0) { tDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); tPalIdx -= 2; if (tPalIdx == 0x1E0) tState++; @@ -2167,7 +2170,7 @@ static void Task_Scene3_Kyogre(u8 taskId) if (--tDelay == 0) { tDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[tPalIdx], &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(tPalIdx), &gPlttBufferFaded[BG_PLTT_ID(2) + 15], PLTT_SIZEOF(1)); tPalIdx += 2; if (tPalIdx == 0x1EE) { @@ -2498,7 +2501,7 @@ static void SpriteCB_Lightning(struct Sprite *sprite) sprite->sPalIdx = 0x1C2; sprite->sState++; case 1: - CpuCopy16(&gIntro3Bg_Pal[sprite->sPalIdx], &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(sprite->sPalIdx), &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); sprite->sPalIdx += 2; if (sprite->sPalIdx != 0x1CE) break; @@ -2509,7 +2512,7 @@ static void SpriteCB_Lightning(struct Sprite *sprite) if (--sprite->sDelay == 0) { sprite->sDelay = 4; - CpuCopy16(&gIntro3Bg_Pal[sprite->sPalIdx], &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(sprite->sPalIdx), &gPlttBufferFaded[BG_PLTT_ID(5) + 13], PLTT_SIZEOF(1)); sprite->sPalIdx -= 2; if (sprite->sPalIdx == 0x1C0) DestroySprite(sprite); @@ -2612,7 +2615,7 @@ static void Task_RayquazaAttack(u8 taskId) case 0: if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x1A2 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x1A2 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2627,7 +2630,7 @@ static void Task_RayquazaAttack(u8 taskId) { if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x1A2 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x1A2 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2646,7 +2649,7 @@ static void Task_RayquazaAttack(u8 taskId) { if ((data[2] & 1) != 0) { - CpuCopy16(&gIntro3Bg_Pal[0x182 + data[1] * 2], &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(0x182 + data[1] * 2), &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); data[1]++; } if (data[1] == 6) @@ -2670,9 +2673,9 @@ static void Task_RayquazaAttack(u8 taskId) if (--data[3] != 0) { BlendPalette(BG_PLTT_ID(5), 16, data[3], RGB(9, 10, 10)); - CpuCopy16(&gIntro3Bg_Pal[428], &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); - CpuCopy16(&gIntro3Bg_Pal[428], &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); - CpuCopy16(&gIntro3Bg_Pal[396], &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(428), &gPlttBufferFaded[BG_PLTT_ID(5) + 14], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(428), &gPlttBufferFaded[BG_PLTT_ID(5) + 8], PLTT_SIZEOF(1)); + CpuCopy16(INTRO3_RAW_PTR(396), &gPlttBufferFaded[BG_PLTT_ID(5) + 12], PLTT_SIZEOF(1)); } else { diff --git a/src/mail.c b/src/mail.c index 424a286f3f..e1aaa66873 100644 --- a/src/mail.c +++ b/src/mail.c @@ -48,8 +48,8 @@ struct MailLayout struct MailGraphics { const u16 *palette; - const u8 *tiles; - const u8 *tileMap; + const u32 *tiles; + const u32 *tileMap; u32 unused; u16 textColor; u16 textShadow; diff --git a/src/naming_screen.c b/src/naming_screen.c index d8ae7ccd4d..f7f599f5b9 100644 --- a/src/naming_screen.c +++ b/src/naming_screen.c @@ -1959,7 +1959,7 @@ static void PrintKeyboardKeys(u8 window, u8 page) PutWindowTilemap(window); } -static const u8 *const sNextKeyboardPageTilemaps[] = +static const u32 *const sNextKeyboardPageTilemaps[] = { [KBPAGE_SYMBOLS] = gNamingScreenKeyboardUpper_Tilemap, [KBPAGE_LETTERS_UPPER] = gNamingScreenKeyboardLower_Tilemap, // lower From 2e3e0889f9675bde7ae7ee6fc73c3185ba5f9b26 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Mon, 23 Jun 2025 19:13:50 -0700 Subject: [PATCH 12/50] add pablopenna as a contributor for code (#7202) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 11 ++++++++++- CREDITS.md | 1 + 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 5b6d38e32f..c8b79ba30e 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -321,7 +321,7 @@ "code" ] }, - { + { "login": "lordraindance2", "name": "lordraindance2", "avatar_url": "https://avatars.githubusercontent.com/u/47706100?v=4", @@ -329,6 +329,15 @@ "contributions": [ "code" ] + }, + { + "login": "pablopenna", + "name": "Pablo Pena", + "avatar_url": "https://avatars.githubusercontent.com/u/11214682?v=4", + "profile": "https://github.com/pablopenna", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 128f26df6f..ab5c596248 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -58,6 +58,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Zatsu
Zatsu

💻 poetahto
poetahto

💻 lordraindance2
lordraindance2

💻 + Pablo Pena
Pablo Pena

💻 From bc95824e8cfa4f15741f832a3ba810a4a303d1b1 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 24 Jun 2025 09:04:19 +0200 Subject: [PATCH 13/50] Fixes wrong Future Sight indexing (#7198) --- src/battle_util.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index ba63bf4fe9..226b041be0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9582,8 +9582,13 @@ bool32 IsFutureSightAttackerInParty(u32 battlerAtk, u32 battlerDef, u32 move) return FALSE; struct Pokemon *party = GetBattlerParty(battlerAtk); - return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]] - && &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[BATTLE_PARTNER(gBattlerPartyIndexes[battlerAtk])]; + if (IsDoubleBattle()) + { + return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]] + && &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[BATTLE_PARTNER(battlerAtk)]]; + } + + return &party[gWishFutureKnock.futureSightPartyIndex[battlerDef]] != &party[gBattlerPartyIndexes[battlerAtk]]; } s32 CalculateMoveDamage(struct DamageCalculationData *damageCalcData, u32 fixedBasePower) From 93511ceb054979508f3776df7e1443ffee691c9a Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Tue, 24 Jun 2025 09:28:26 +0200 Subject: [PATCH 14/50] Fix BtlController_EmitChosenMonReturnValue UB (#7197) --- src/battle_controllers.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 4faec49613..ec3dfa7426 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1415,8 +1415,11 @@ void BtlController_EmitChosenMonReturnValue(u32 battler, u32 bufferId, u8 partyI gBattleResources->transferBuffer[0] = CONTROLLER_CHOSENMONRETURNVALUE; gBattleResources->transferBuffer[1] = partyId; - for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++) - gBattleResources->transferBuffer[2 + i] = battlePartyOrder[i]; + if (battlePartyOrder != NULL) + { + for (i = 0; i < (int)ARRAY_COUNT(gBattlePartyCurrentOrder); i++) + gBattleResources->transferBuffer[2 + i] = battlePartyOrder[i]; + } PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 5); } From 74326023da8daf1c239a7658877f68539a48656c Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Tue, 24 Jun 2025 09:29:20 +0200 Subject: [PATCH 15/50] Backported Safari catch and add to party fix (#7192) Co-authored-by: Hedara --- src/battle_controller_safari.c | 66 +++++++++++++++++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 4a1fc3888c..9311c2f7a1 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -11,6 +11,7 @@ #include "main.h" #include "m4a.h" #include "palette.h" +#include "party_menu.h" #include "pokeball.h" #include "pokeblock.h" #include "pokemon.h" @@ -22,6 +23,7 @@ #include "window.h" #include "line_break.h" #include "constants/battle_anim.h" +#include "constants/party_menu.h" #include "constants/songs.h" #include "constants/trainers.h" #include "constants/rgb.h" @@ -33,6 +35,7 @@ static void SafariHandlePrintString(u32 battler); static void SafariHandlePrintSelectionString(u32 battler); static void SafariHandleChooseAction(u32 battler); static void SafariHandleChooseItem(u32 battler); +static void SafariHandleChoosePokemon(u32 battler); static void SafariHandleStatusIconUpdate(u32 battler); static void SafariHandleFaintingCry(u32 battler); static void SafariHandleIntroTrainerBallThrow(u32 battler); @@ -42,6 +45,7 @@ static void SafariHandleEndLinkBattle(u32 battler); static void SafariBufferRunCommand(u32 battler); static void SafariBufferExecCompleted(u32 battler); static void CompleteWhenChosePokeblock(u32 battler); +static void WaitForMonSelection(u32 battler); static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = { @@ -67,7 +71,7 @@ static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_YESNOBOX] = BtlController_Empty, [CONTROLLER_CHOOSEMOVE] = BtlController_Empty, [CONTROLLER_OPENBAG] = SafariHandleChooseItem, - [CONTROLLER_CHOOSEPOKEMON] = BtlController_Empty, + [CONTROLLER_CHOOSEPOKEMON] = SafariHandleChoosePokemon, [CONTROLLER_23] = BtlController_Empty, [CONTROLLER_HEALTHBARUPDATE] = BtlController_Empty, [CONTROLLER_EXPUPDATE] = BtlController_Empty, @@ -225,6 +229,41 @@ static void CompleteWhenChosePokeblock(u32 battler) } } +static void OpenPartyMenuToChooseMon(u32 battler) +{ + if (!gPaletteFade.active) + { + gBattlerControllerFuncs[battler] = WaitForMonSelection; + u8 caseId = gTasks[gBattleControllerData[battler]].data[0]; + DestroyTask(gBattleControllerData[battler]); + FreeAllWindowBuffers(); + OpenPartyMenuInBattle(caseId); + } +} + +static void WaitForMonSelection(u32 battler) +{ + if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active) + { + if (gPartyMenuUseExitCallback == TRUE) + BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, gSelectedMonPartyId, gBattlePartyCurrentOrder); + else + BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, PARTY_SIZE, NULL); + + if ((gBattleResources->bufferA[battler][1] & 0xF) == 1) + { + if (gBattleTypeFlags & BATTLE_TYPE_LINK) + { + gBattle_BG0_X = 0; + gBattle_BG0_Y = 0; + BattlePutTextOnWindow(gText_LinkStandby, B_WIN_MSG); + } + } + + SafariBufferExecCompleted(battler); + } +} + static void SafariBufferExecCompleted(u32 battler) { gBattlerControllerFuncs[battler] = SafariBufferRunCommand; @@ -305,6 +344,31 @@ static void SafariHandleChooseItem(u32 battler) gBattlerInMenuId = battler; } +static void SafariHandleChoosePokemon(u32 battler) +{ + for (s32 i = 0; i < ARRAY_COUNT(gBattlePartyCurrentOrder); i++) + gBattlePartyCurrentOrder[i] = gBattleResources->bufferA[battler][4 + i]; + + if (gBattleTypeFlags & BATTLE_TYPE_ARENA && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CANT_SWITCH + && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_CHOOSE_FAINTED_MON + && (gBattleResources->bufferA[battler][1] & 0xF) != PARTY_ACTION_SEND_MON_TO_BOX) + { + BtlController_EmitChosenMonReturnValue(battler, B_COMM_TO_ENGINE, gBattlerPartyIndexes[battler] + 1, gBattlePartyCurrentOrder); + SafariBufferExecCompleted(battler); + } + else + { + gBattleControllerData[battler] = CreateTask(TaskDummy, 0xFF); + gTasks[gBattleControllerData[battler]].data[0] = gBattleResources->bufferA[battler][1] & 0xF; + *(&gBattleStruct->battlerPreventingSwitchout) = gBattleResources->bufferA[battler][1] >> 4; + *(&gBattleStruct->prevSelectedPartySlot) = gBattleResources->bufferA[battler][2]; + *(&gBattleStruct->abilityPreventingSwitchout) = (gBattleResources->bufferA[battler][3] & 0xFF) | (gBattleResources->bufferA[battler][7] << 8); + BeginNormalPaletteFade(PALETTES_ALL, 0, 0, 0x10, RGB_BLACK); + gBattlerControllerFuncs[battler] = OpenPartyMenuToChooseMon; + gBattlerInMenuId = battler; + } +} + static void SafariHandleStatusIconUpdate(u32 battler) { UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], GetBattlerMon(battler), HEALTHBOX_SAFARI_BALLS_TEXT); From b372fa30b66d67cba459e33475d81d156f96ff93 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Tue, 24 Jun 2025 15:03:54 -0400 Subject: [PATCH 16/50] Fix AI party count calc being maintained between tests (#7200) --- src/battle_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/battle_main.c b/src/battle_main.c index cc5f281d4e..fec093d166 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -583,6 +583,12 @@ static void CB2_InitBattleInternal(void) TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BEGIN_BATTLE); } + if (TESTING) + { + gPlayerPartyCount = CalculatePartyCount(gPlayerParty); + gEnemyPartyCount = CalculatePartyCount(gEnemyParty); + } + gBattleCommunication[MULTIUSE_STATE] = 0; } From 07fd8a28fbd5b23a6828846e4606fc3ecd54c3d9 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sun, 30 Mar 2025 18:01:04 -0400 Subject: [PATCH 17/50] fix: hide followers when player enters Battle Pike curtains --- data/scripts/battle_pike.inc | 1 + 1 file changed, 1 insertion(+) diff --git a/data/scripts/battle_pike.inc b/data/scripts/battle_pike.inc index 3393f808d3..9262dc46e8 100644 --- a/data/scripts/battle_pike.inc +++ b/data/scripts/battle_pike.inc @@ -86,6 +86,7 @@ BattleFrontier_BattlePikeThreePathRoom_EventScript_RightRoomWarp:: end BattleFrontier_BattlePikeThreePathRoom_EventScript_RoomWarp:: + clearflag FLAG_SAFE_FOLLOWER_MOVEMENT pike_get PIKE_DATA_WIN_STREAK addvar VAR_RESULT, 1 pike_set PIKE_DATA_WIN_STREAK, VAR_RESULT From 1f2fe7396b68d82da356b93fca10cc5736d3159c Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sat, 3 May 2025 21:44:52 -0400 Subject: [PATCH 18/50] feat: added abnormal weather follower message Includes support for follower matching != species --- include/constants/flags.h | 1 + include/follower_helper.h | 4 +++- src/event_object_movement.c | 7 ++++++- src/follower_helper.c | 12 ++++++++++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/include/constants/flags.h b/include/constants/flags.h index b7388d6bd0..4863c0980a 100644 --- a/include/constants/flags.h +++ b/include/constants/flags.h @@ -1397,6 +1397,7 @@ #define FLAG_SYS_USE_FLASH (SYSTEM_FLAGS + 0x28) #define FLAG_SYS_USE_STRENGTH (SYSTEM_FLAGS + 0x29) +// Sets abnormal weather on maps that check for it #define FLAG_SYS_WEATHER_CTRL (SYSTEM_FLAGS + 0x2A) #define FLAG_SYS_CYCLING_ROAD (SYSTEM_FLAGS + 0x2B) #define FLAG_SYS_SAFARI_MODE (SYSTEM_FLAGS + 0x2C) diff --git a/include/follower_helper.h b/include/follower_helper.h index 4d316ba1a3..e5787de5c7 100644 --- a/include/follower_helper.h +++ b/include/follower_helper.h @@ -62,7 +62,8 @@ struct FollowerMsgInfoExtended { #define MATCH_U16(type, value1, value2) {type, {.split = {.hw = value1, .b = value2}}} #define MATCH_U8(type, v1, v2, v3) {type, {.bytes = {v1, v2, v3}}} -#define MATCH_SPECIES(species) MATCH_U24(MSG_COND_SPECIES, species) +#define MATCH_SPECIES(species) MATCH_U16(MSG_COND_SPECIES, species, 0) +#define MATCH_NOT_SPECIES(species) MATCH_U16(MSG_COND_SPECIES, species, 1) #define MATCH_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, 0) // Checks that follower has *neither* of the two types #define MATCH_NOT_TYPES(type1, type2) MATCH_U8(MSG_COND_TYPE, type1, type2, TYPE_NONE | 1) @@ -107,6 +108,7 @@ enum { COND_MSG_LEAVES, COND_MSG_ICE, COND_MSG_BURN, + COND_MSG_ABNORMAL_WEATHER, COND_MSG_COUNT, }; diff --git a/src/event_object_movement.c b/src/event_object_movement.c index e0bc0619ae..630e3dffb3 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -2125,7 +2125,12 @@ bool32 CheckMsgCondition(const struct MsgCondition *cond, struct Pokemon *mon, u switch (cond->type) { case MSG_COND_SPECIES: - return (cond->data.raw == species); + multi = cond->data.split.hw; + // if byte nonzero, invert; check != species! + if (cond->data.split.b) + return (cond->data.split.hw != species); + else + return (cond->data.split.hw == species); case MSG_COND_TYPE: multi = (SpeciesHasType(species, cond->data.bytes[0]) || SpeciesHasType(species, cond->data.bytes[1])); diff --git a/src/follower_helper.c b/src/follower_helper.c index be52877c5f..3df1cfa0a9 100644 --- a/src/follower_helper.c +++ b/src/follower_helper.c @@ -65,6 +65,7 @@ static const u8 sCondMsg40[] = _("{STR_VAR_1} is gnawing at the ice."); static const u8 sCondMsg41[] = _("{STR_VAR_1} is touching the ice."); static const u8* const sIceTexts[] = {sCondMsg26, sCondMsg40, sCondMsg41, NULL}; static const u8 sCondMsg42[] = _("{STR_VAR_1}'s burn looks painful!"); +static const u8 sCondMsg50[] = _("{STR_VAR_1} is disturbed by the\nabnormal weather!"); // See the struct definition in follower_helper.h for more info const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT] = { @@ -276,6 +277,17 @@ const struct FollowerMsgInfoExtended gFollowerConditionalMessages[COND_MSG_COUNT .emotion = FOLLOWER_EMOTION_SAD, .conditions = {MATCH_STATUS(STATUS1_BURN)}, }, + [COND_MSG_ABNORMAL_WEATHER] = + { + .text = sCondMsg50, + .emotion = FOLLOWER_EMOTION_SURPRISE, + .conditions = { + MATCH_MUSIC(MUS_ABNORMAL_WEATHER), + MATCH_NOT_SPECIES(SPECIES_KYOGRE), + MATCH_NOT_SPECIES(SPECIES_GROUDON), + MATCH_NOT_SPECIES(SPECIES_RAYQUAZA), + } + }, }; // Pool of "unconditional" follower messages From 143500a1f95bf5951c001ec88db8b9d3f55d43e7 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Tue, 20 May 2025 23:08:48 -0400 Subject: [PATCH 19/50] fix: capitalization in follower splash message --- src/follower_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/follower_helper.c b/src/follower_helper.c index 3df1cfa0a9..db24895a38 100644 --- a/src/follower_helper.c +++ b/src/follower_helper.c @@ -35,7 +35,7 @@ static const u8 sCondMsg16[] = _("{STR_VAR_1} doesn't want to get off\nthe boat static const u8* const sBoatTexts[] = {sCondMsg14, sCondMsg15, sCondMsg16, NULL}; static const u8 sCondMsg17[] = _("{STR_VAR_1} is listening to the\nsound of the machines."); static const u8* const sMachineTexts[] = {sCondMsg13, sCondMsg17, NULL}; -static const u8 sCondMsg18[] = _("Waah! your POKéMON suddenly splashed\nwater!"); +static const u8 sCondMsg18[] = _("Waah! Your POKéMON suddenly splashed\nwater!"); static const u8 sCondMsg19[] = _("Your POKéMON is blowing sand in the\nair!"); static const u8 sCondMsg20[] = _("{STR_VAR_1} is playing around,\nplucking bits of grass."); static const u8 sCondMsg21[] = _("Your POKéMON is happily looking at\nyour footprints!"); From 200ef41fce5071a2032ef34e4ba64b71368cfccd Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Fri, 30 May 2025 01:32:48 -0400 Subject: [PATCH 20/50] fix: mapjson missing cstdint --- tools/mapjson/json11.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/mapjson/json11.cpp b/tools/mapjson/json11.cpp index 3ac5f392a0..50c2209c57 100644 --- a/tools/mapjson/json11.cpp +++ b/tools/mapjson/json11.cpp @@ -20,6 +20,7 @@ #include "json11.h" #include #include +#include #include #include #include From cab7f8b24b0dfaa26de8d63938cc3c9737d127a6 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:52:45 -0400 Subject: [PATCH 21/50] fix: removed sweet scent field effect dependence on gPaletteDecompressionBuffer --- src/fldeff_sweetscent.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/src/fldeff_sweetscent.c b/src/fldeff_sweetscent.c index dd979c77a8..c7da9ddb68 100644 --- a/src/fldeff_sweetscent.c +++ b/src/fldeff_sweetscent.c @@ -6,6 +6,7 @@ #include "field_screen_effect.h" #include "field_weather.h" #include "fldeff.h" +#include "malloc.h" #include "mirage_tower.h" #include "palette.h" #include "party_menu.h" @@ -50,13 +51,19 @@ bool8 FldEff_SweetScent(void) static void StartSweetScentFieldEffect(void) { u8 taskId; + u32 palettes = ~(1 << (gSprites[GetPlayerAvatarSpriteId()].oam.paletteNum + 16) | (1 << 13) | (1 << 14) | (1 << 15)); + u32 *buffer = Alloc(PLTT_SIZE); PlaySE(SE_M_SWEET_SCENT); - CpuFastCopy(gPlttBufferUnfaded, gPaletteDecompressionBuffer, PLTT_SIZE); - CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); - BeginNormalPaletteFade(~(1 << (gSprites[GetPlayerAvatarSpriteId()].oam.paletteNum + 16)), 4, 0, 8, RGB_RED); + if (buffer) { + CpuFastCopy(gPlttBufferUnfaded, buffer, PLTT_SIZE); + CpuFastCopy(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); + } + BeginNormalPaletteFade(palettes, 4, 0, 8, RGB_RED); taskId = CreateTask(TrySweetScentEncounter, 0); gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = (u32) buffer >> 16; + gTasks[taskId].data[2] = (u32) buffer; FieldEffectActiveListRemove(FLDEFF_SWEET_SCENT); } @@ -71,6 +78,8 @@ static void TrySweetScentEncounter(u8 taskId) gTasks[taskId].data[0] = 0; if (SweetScentWildEncounter() == TRUE) { + u32 *buffer = (u32*)(((u16)gTasks[taskId].data[1] << 16) | (u16)gTasks[taskId].data[2]); + TRY_FREE_AND_SET_NULL(buffer); DestroyTask(taskId); } else @@ -91,7 +100,11 @@ static void FailSweetScentEncounter(u8 taskId) { if (!gPaletteFade.active) { - CpuFastCopy(gPaletteDecompressionBuffer, gPlttBufferUnfaded, PLTT_SIZE); + u32 *buffer = (u32*)(((u16)gTasks[taskId].data[1] << 16) | (u16)gTasks[taskId].data[2]); + if (buffer) { + CpuFastCopy(buffer, gPlttBufferUnfaded, PLTT_SIZE); + Free(buffer); + } SetWeatherPalStateIdle(); ScriptContext_SetupScript(EventScript_FailSweetScent); DestroyTask(taskId); From 1cc2c7f2a02c350c0d724ab661ea0b78d108df51 Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Tue, 24 Jun 2025 19:57:04 -0400 Subject: [PATCH 22/50] fix: destroy shadows during battle transition intro --- src/battle_transition.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/battle_transition.c b/src/battle_transition.c index 0d66dfbf01..dbee25968f 100644 --- a/src/battle_transition.c +++ b/src/battle_transition.c @@ -1068,6 +1068,9 @@ static void Task_BattleTransition(u8 taskId) static bool8 Transition_StartIntro(struct Task *task) { SetWeatherScreenFadeOut(); + // cause all shadow sprites to destroy themselves, + // freeing up sprite slots for the transition + gWeatherPtr->noShadows = TRUE; CpuCopy32(gPlttBufferFaded, gPlttBufferUnfaded, PLTT_SIZE); if (sTasks_Intro[task->tTransitionId] != NULL) { From f6efe480fa4363eacf59538e6e68ec34fa6f6a1d Mon Sep 17 00:00:00 2001 From: Ariel A <24759293+aarant@users.noreply.github.com> Date: Sun, 9 Mar 2025 19:41:16 -0400 Subject: [PATCH 23/50] fix: ignore trainerRange on OW templates when trainerType nonzero --- src/event_object_movement.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/event_object_movement.c b/src/event_object_movement.c index f63624e135..be4c5abfd8 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1738,7 +1738,7 @@ static u16 PackGraphicsId(const struct ObjectEventTemplate *template) { if (template->script && template->script[0] == 0x7d) { form = T1_READ_16(&template->script[2]); form = (form >> 10) & 0x1F; - } else if (template->trainerRange_berryTreeId) { + } else if (template->trainerRange_berryTreeId && !template->trainerType) { form = template->trainerRange_berryTreeId & 0x1F; } graphicsId |= form << OBJ_EVENT_GFX_SPECIES_BITS; From 8d81f603134a5030f47cd28633f5737e76112bf0 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 25 Jun 2025 08:01:31 -0400 Subject: [PATCH 24/50] Fix tests failing with `B_FRIENDSHIP_BOOST` being `TRUE` (#7194) Co-authored-by: hedara90 <90hedara@gmail.com> --- test/pokemon.c | 13 +++++++++++-- test/test_runner_battle.c | 7 +++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/test/pokemon.c b/test/pokemon.c index 4e8a1da7fa..ac57314f9c 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -82,10 +82,14 @@ TEST("Shininess independent from PID and OTID") TEST("Hyper Training increases stats without affecting IVs") { - u32 data, hp, atk, def, speed, spatk, spdef; + u32 data, hp, atk, def, speed, spatk, spdef, friendship = 0; struct Pokemon mon; CreateMon(&mon, SPECIES_WOBBUFFET, 100, 3, TRUE, 0, OT_ID_PRESET, 0); + // Consider B_FRIENDSHIP_BOOST. + SetMonData(&mon, MON_DATA_FRIENDSHIP, &friendship); + CalculateMonStats(&mon); + hp = GetMonData(&mon, MON_DATA_HP); atk = GetMonData(&mon, MON_DATA_ATK); def = GetMonData(&mon, MON_DATA_DEF); @@ -142,8 +146,13 @@ TEST("Status1 round-trips through BoxPokemon") TEST("canhypertrain/hypertrain affect MON_DATA_HYPER_TRAINED_* and recalculate stats") { - u32 atk; + u32 atk, friendship = 0; CreateMon(&gPlayerParty[0], SPECIES_WOBBUFFET, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + + // Consider B_FRIENDSHIP_BOOST. + SetMonData(&gPlayerParty[0], MON_DATA_FRIENDSHIP, &friendship); + CalculateMonStats(&gPlayerParty[0]); + atk = GetMonData(&gPlayerParty[0], MON_DATA_ATK); RUN_OVERWORLD_SCRIPT( diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 7884993a1c..20271a588d 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1563,6 +1563,13 @@ void OpenPokemon(u32 sourceLine, u32 side, u32 species) data = MOVE_NONE; for (i = 0; i < MAX_MON_MOVES; i++) SetMonData(DATA.currentMon, MON_DATA_MOVE1 + i, &data); + data = 0; + if (B_FRIENDSHIP_BOOST) + { + // This way, we avoid the boost affecting tests unless explicitly stated. + SetMonData(DATA.currentMon, MON_DATA_FRIENDSHIP, &data); + CalculateMonStats(DATA.currentMon); + } } // (sNaturePersonalities[i] % NUM_NATURES) == i From 9ca6562874d92d7dd9562fc10e5026d9ef64b7d4 Mon Sep 17 00:00:00 2001 From: Hedara Date: Wed, 25 Jun 2025 18:04:12 +0200 Subject: [PATCH 25/50] Cleanup of merrp merge --- tools/mapjson/json11.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/tools/mapjson/json11.cpp b/tools/mapjson/json11.cpp index 74f9272313..fcacdbeb39 100644 --- a/tools/mapjson/json11.cpp +++ b/tools/mapjson/json11.cpp @@ -20,7 +20,6 @@ #include "json11.h" #include #include -#include #include #include #include From 773ecd4c24aeaae1c49e86f30f93925ff53cc59e Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 25 Jun 2025 21:00:49 +0200 Subject: [PATCH 26/50] Fixes OOB for Teatime and Flower Shield (#7214) --- data/battle_scripts_1.s | 7 ++++++- src/battle_script_commands.c | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index a10dfaa40c..2b9f5e36e4 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1503,11 +1503,12 @@ BattleScript_EffectFlowerShield:: attackcanceler attackstring ppreduce + savetarget selectfirstvalidtarget BattleScript_FlowerShieldIsAnyGrass: jumpiftype BS_TARGET, TYPE_GRASS, BattleScript_FlowerShieldLoopStart jumpifnexttargetvalid BattleScript_FlowerShieldIsAnyGrass - goto BattleScript_ButItFailed + goto BattleScript_RestoreTargetButItFailed BattleScript_FlowerShieldLoopStart: selectfirstvalidtarget BattleScript_FlowerShieldLoop: @@ -1532,6 +1533,7 @@ BattleScript_FlowerShieldString: BattleScript_FlowerShieldMoveTargetEnd: moveendto MOVEEND_NEXT_TARGET jumpifnexttargetvalid BattleScript_FlowerShieldLoop + restoretarget end BattleScript_EffectRototiller:: @@ -4513,6 +4515,9 @@ BattleScript_ButItFailed:: BattleScript_RestoreAttackerButItFailed: restoreattacker goto BattleScript_ButItFailed +BattleScript_RestoreTargetButItFailed: + restoretarget + goto BattleScript_ButItFailed BattleScript_NotAffected:: pause B_WAIT_TIME_SHORT diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index bd2ef1509e..2b67c7116f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11751,9 +11751,14 @@ static void Cmd_jumpifnexttargetvalid(void) } if (gBattlerTarget >= gBattlersCount) + { + gBattlerTarget = gBattlersCount - 1; gBattlescriptCurrInstr = cmd->nextInstr; + } else + { gBattlescriptCurrInstr = jumpInstr; + } } static void Cmd_tryhealhalfhealth(void) From 4def635e1f4c796a72e45b0aa9993e49c922df0e Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:53:50 +0200 Subject: [PATCH 27/50] Fixes wrong assignment in TrySymbiosis (#7221) --- src/battle_script_commands.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2b67c7116f..41b473c5af 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9181,7 +9181,6 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId) BestowItem(BATTLE_PARTNER(battler), battler); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler); - gBattlerAttacker = battler; BattleScriptPush(gBattlescriptCurrInstr + 2); gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; return TRUE; From 565cf6f7ffa219ee11bc292264930265e52de9d1 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 26 Jun 2025 15:54:19 +0200 Subject: [PATCH 28/50] Adds missing healBlockTimer for Baton Pass (#7220) --- src/battle_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_main.c b/src/battle_main.c index fec093d166..fc7304b1a3 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3188,6 +3188,7 @@ void SwitchInClearSetData(u32 battler) gDisableStructs[battler].perishSongTimer = disableStructCopy.perishSongTimer; gDisableStructs[battler].battlerPreventingEscape = disableStructCopy.battlerPreventingEscape; gDisableStructs[battler].embargoTimer = disableStructCopy.embargoTimer; + gDisableStructs[battler].healBlockTimer = disableStructCopy.healBlockTimer; } else if (effect == EFFECT_SHED_TAIL) { From 9416a783d426962197d801511e44b14b451c5d43 Mon Sep 17 00:00:00 2001 From: Bivurnum <147376167+Bivurnum@users.noreply.github.com> Date: Thu, 26 Jun 2025 16:47:09 -0500 Subject: [PATCH 29/50] removed unnecessary fnpc underwater update --- src/follower_npc.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/follower_npc.c b/src/follower_npc.c index 0a8cde49c8..d9882b61bf 100644 --- a/src/follower_npc.c +++ b/src/follower_npc.c @@ -1179,10 +1179,6 @@ void FollowerNPC_HandleSprite(void) else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE) SetFollowerNPCSprite(FOLLOWER_NPC_SPRITE_INDEX_ACRO_BIKE); } - else if (gMapHeader.mapType == MAP_TYPE_UNDERWATER) - { - TryUpdateFollowerNPCSpriteUnderwater(); - } else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ON_FOOT) { SetFollowerNPCSprite(FOLLOWER_NPC_SPRITE_INDEX_NORMAL); From 3dda407bb092897c7064d1093fdaed1f88d3b6ba Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sat, 28 Jun 2025 02:43:50 -0400 Subject: [PATCH 30/50] Jaboca berry triggers instead of being stolen by bug bite (#7237) Co-authored-by: ghoulslash --- src/battle_script_commands.c | 7 ++++++- test/battle/hold_effect/jaboca_berry.c | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 41b473c5af..cdcb02d28f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3800,7 +3800,12 @@ void SetMoveEffect(bool32 primary, bool32 certain) } break; case MOVE_EFFECT_BUG_BITE: - if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES + if (GetBattlerHoldEffect(gEffectBattler, TRUE) == HOLD_EFFECT_JABOCA_BERRY) + { + // jaboca berry triggers instead of being stolen + gBattlescriptCurrInstr++; + } + else if (GetItemPocket(gBattleMons[gEffectBattler].item) == POCKET_BERRIES && battlerAbility != ABILITY_STICKY_HOLD) { // target loses their berry diff --git a/test/battle/hold_effect/jaboca_berry.c b/test/battle/hold_effect/jaboca_berry.c index 29658c7fe1..a23cd90bb9 100644 --- a/test/battle/hold_effect/jaboca_berry.c +++ b/test/battle/hold_effect/jaboca_berry.c @@ -42,7 +42,6 @@ SINGLE_BATTLE_TEST("Jaboca Berry causes the attacker to lose 1/8 of its max HP i SINGLE_BATTLE_TEST("Jaboca Berry triggers before Bug Bite can steal it") { - KNOWN_FAILING; GIVEN { ASSUME(GetMoveCategory(MOVE_BUG_BITE) == DAMAGE_CATEGORY_PHYSICAL); PLAYER(SPECIES_WYNAUT); From a96591dd4389596703a4560a7ca2167d667cf93b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 28 Jun 2025 10:14:55 +0200 Subject: [PATCH 31/50] Fixes Scald defrosting target while asleep (#7233) --- src/battle_script_commands.c | 1 + test/battle/defrost.c | 14 ++++++++++++++ 2 files changed, 15 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index cdcb02d28f..8787760e74 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6956,6 +6956,7 @@ static void Cmd_moveend(void) effect = TRUE; } if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && gBattlerAttacker != gBattlerTarget && MoveThawsUser(originallyUsedMove) diff --git a/test/battle/defrost.c b/test/battle/defrost.c index 3d456d6673..a226a49f1e 100644 --- a/test/battle/defrost.c +++ b/test/battle/defrost.c @@ -16,3 +16,17 @@ DOUBLE_BATTLE_TEST("Defrost: A fire type spread move will thaw both targets") STATUS_ICON(opponentRight, freeze: FALSE); } } + +SINGLE_BATTLE_TEST("Defrost: Scald does not thaw targets if user is asleep") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FROSTBITE); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP_TURN(3)); } + } WHEN { + TURN { MOVE(opponent, MOVE_SCALD); MOVE(player, MOVE_CELEBRATE); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SCALD, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, player); + HP_BAR(player); + } +} From 0c4b0c582ea84509ab11a58589a5bb40fe34293d Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sat, 28 Jun 2025 04:20:39 -0400 Subject: [PATCH 32/50] Add some tests (#7234) --- test/battle/hold_effect/life_orb.c | 17 +++++++++++++++++ test/battle/move_effect/assist.c | 25 +++++++++++++++++++++++++ 2 files changed, 42 insertions(+) diff --git a/test/battle/hold_effect/life_orb.c b/test/battle/hold_effect/life_orb.c index 7f4fcc2ccf..92c545dfad 100644 --- a/test/battle/hold_effect/life_orb.c +++ b/test/battle/hold_effect/life_orb.c @@ -31,6 +31,23 @@ SINGLE_BATTLE_TEST("Life Orb activates if it hits a Substitute") } } +SINGLE_BATTLE_TEST("Life Orb does not activate if using status move on a Substitute") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_GROWL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_GROWL, player); + NONE_OF { + HP_BAR(player); + MESSAGE("Wobbuffet was hurt by the Life Orb!"); + } + } +} + SINGLE_BATTLE_TEST("Life Orb does not activate if using a status move") { GIVEN { diff --git a/test/battle/move_effect/assist.c b/test/battle/move_effect/assist.c index 6036de8e8c..3a380ef125 100644 --- a/test/battle/move_effect/assist.c +++ b/test/battle/move_effect/assist.c @@ -17,6 +17,7 @@ TO_DO_BATTLE_TEST("Assist cannot call a Mimicked move (Gen4 only)"); TO_DO_BATTLE_TEST("Assist can call a Mimicked move but not the original Mimic (Gen5+)"); TO_DO_BATTLE_TEST("Assist can call moves in unhatched Eggs (Gen5 only)"); TO_DO_BATTLE_TEST("Assist can be used by wild Pokémon in Wild Double Battles, even if the partner faints"); +TO_DO_BATTLE_TEST("Assist called move does not get boosted by Normalize"); SINGLE_BATTLE_TEST("Assist fails if there are no valid moves to choose from") { @@ -32,3 +33,27 @@ SINGLE_BATTLE_TEST("Assist fails if there are no valid moves to choose from") MESSAGE("But it failed!"); } } + +SINGLE_BATTLE_TEST("Assisted move triggers correct weakness berry") +{ + u16 item; + PARAMETRIZE { item = ITEM_CHILAN_BERRY; } + PARAMETRIZE { item = ITEM_PASSHO_BERRY; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_ASSIST, MOVE_NONE, MOVE_NONE, MOVE_NONE); } + PLAYER(SPECIES_WOBBUFFET) { Moves(MOVE_SURF, MOVE_NONE, MOVE_NONE, MOVE_NONE); } + OPPONENT(SPECIES_ARON) { Item(item); } + } WHEN { + TURN { MOVE(player, MOVE_ASSIST); } + } SCENE { + MESSAGE("Wobbuffet used Assist!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ASSIST, player); + MESSAGE("Wobbuffet used Surf!"); + if (item == ITEM_PASSHO_BERRY) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } else { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_SURF, player); + } +} From 8973006273ec1102c7f3382e69309e078bb5a2ff Mon Sep 17 00:00:00 2001 From: Juanjo <64270307+J2M2@users.noreply.github.com> Date: Sat, 28 Jun 2025 10:36:37 +0200 Subject: [PATCH 33/50] =?UTF-8?q?[FIX]=20=20Prevent=20caught=20Pok=C3=A9mo?= =?UTF-8?q?n=20loss=20in=20NPC=20partner=20battles=20(#7177)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/battle_script_commands.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 8787760e74..f0957241ca 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -66,6 +66,8 @@ #include "constants/pokemon.h" #include "config/battle.h" #include "data/battle_move_effects.h" +#include "follower_npc.h" +#include "load_save.h" // table to avoid ugly powing on gba (courtesy of doesnt) // this returns (i^2.5)/4 @@ -16034,6 +16036,9 @@ static void Cmd_givecaughtmon(void) { CMD_ARGS(const u8 *passInstr); enum GiveCaughtMonStates state = gBattleCommunication[MULTIUSE_STATE]; + // Restore players party in order to handle properly the case when a wild mon is caught. + if (IsNPCFollowerWildBattle()) + LoadPlayerParty(); switch (state) { @@ -16171,6 +16176,9 @@ static void Cmd_givecaughtmon(void) gBattlescriptCurrInstr = cmd->nextInstr; break; } + // Save the player's party again to not interferes with RestorePartyAfterFollowerNPCBattle() called after battle. + if (IsNPCFollowerWildBattle()) + SavePlayerParty(); } static void Cmd_trysetcaughtmondexflags(void) From 502c73dc9bd0bd87e593b907a874ccc4f3d3bc49 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 28 Jun 2025 22:24:24 +0200 Subject: [PATCH 34/50] Fix 01_battle_engine_bugs.yaml (#7242) --- .github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index da15109c8c..38414dc80f 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -7,6 +7,7 @@ body: value: | Please fill in all fields with as many details as possible. Once your bug is posted, make sure you and your collaborators are added to `CREDITS.md` by [tagging the bot on GitHub](https://github.com/rh-hideout/pokeemerald-expansion/wiki/CREDITS.md-Frequently-Asked-Questions). EVERY contribution matters, even reporting bugs! + - type: textarea id: description attributes: label: Description From 6ed4f73f6a9a78eb8f5eace26b1942d64a2f0d80 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Sat, 28 Jun 2025 22:20:40 +0100 Subject: [PATCH 35/50] Fixes Emergency Exit sometimes causing an unrelated battler to become invisible (#7241) --- data/battle_scripts_1.s | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2b9f5e36e4..52d91e8d3b 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -7441,7 +7441,7 @@ BattleScript_EmergencyExit:: switchoutabilities BS_SCRIPTING waitstate switchhandleorder BS_SCRIPTING, 2 - returntoball BS_TARGET, FALSE + returntoball BS_SCRIPTING, FALSE getswitchedmondata BS_SCRIPTING switchindataupdate BS_SCRIPTING hpthresholds BS_SCRIPTING @@ -7474,7 +7474,7 @@ BattleScript_EmergencyExitEnd2:: switchoutabilities BS_ATTACKER waitstate switchhandleorder BS_ATTACKER, 2 - returntoball BS_TARGET, FALSE + returntoball BS_ATTACKER, FALSE getswitchedmondata BS_ATTACKER switchindataupdate BS_ATTACKER hpthresholds BS_ATTACKER From ae123f0f3784ec11255a4eae18a88355e3ee9d99 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 29 Jun 2025 10:16:38 +0200 Subject: [PATCH 36/50] Added tests for Toxic Thread (#7244) Co-authored-by: Hedara --- .../move_effects_combined/toxic_thread.c | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 test/battle/move_effects_combined/toxic_thread.c diff --git a/test/battle/move_effects_combined/toxic_thread.c b/test/battle/move_effects_combined/toxic_thread.c new file mode 100644 index 0000000000..c946619cd8 --- /dev/null +++ b/test/battle/move_effects_combined/toxic_thread.c @@ -0,0 +1,108 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_TOXIC_THREAD) == EFFECT_TOXIC_THREAD); +} + +SINGLE_BATTLE_TEST("Toxic Thread both reduces speed and inflicts Poison") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + } +} + +SINGLE_BATTLE_TEST("Toxic Thread still inflicts Poison if speed can't go lower") +{ + KNOWN_FAILING; // #7243 + GIVEN { + ASSUME(GetMoveEffect(MOVE_SCARY_FACE) == EFFECT_SPEED_DOWN_2); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 6); + } +} + +SINGLE_BATTLE_TEST("Toxic Thread still inflicts Poison if speed can't be lowered") +{ + KNOWN_FAILING; // #7243 + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_REGICE) { Ability(ABILITY_CLEAR_BODY); } + } WHEN { + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Toxic Thread still lowers speed if the target can't be Poisoned") +{ + GIVEN { + ASSUME(gSpeciesInfo[SPECIES_BRONZOR].types[0] == TYPE_STEEL || gSpeciesInfo[SPECIES_BRONZOR].types[1] == TYPE_STEEL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRONZOR); + } WHEN { + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + NOT ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + } +} + +SINGLE_BATTLE_TEST("Toxic Thread still lowers speed if the target is already Poisoned") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_POISON_POWDER); } + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_POWDER, player); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_PSN, opponent); + STATUS_ICON(opponent, poison: TRUE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + } THEN { + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); + } +} From 21ac62f781b988999e19a19b12252889df337eb3 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sun, 29 Jun 2025 15:38:52 -0400 Subject: [PATCH 37/50] Flush textbox for Truant Popup (#7252) Co-authored-by: ghoulslash --- data/battle_scripts_1.s | 1 + 1 file changed, 1 insertion(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 52d91e8d3b..7fcf186910 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8576,6 +8576,7 @@ BattleScript_MoveUsedLoafingAroundMsg:: moveendto MOVEEND_NEXT_TARGET end BattleScript_TruantLoafingAround:: + flushtextbox call BattleScript_AbilityPopUp goto BattleScript_MoveUsedLoafingAroundMsg From 1e281547ed50698d8b333103a4cd57866be6580e Mon Sep 17 00:00:00 2001 From: Hedara Date: Mon, 30 Jun 2025 11:01:13 +0200 Subject: [PATCH 38/50] 1.12.1 Release commit --- .../ISSUE_TEMPLATE/01_battle_engine_bugs.yaml | 3 +- .../ISSUE_TEMPLATE/02_battle_ai_issues.yaml | 3 +- .github/ISSUE_TEMPLATE/04_other_errors.yaml | 3 +- README.md | 2 +- docs/SUMMARY.md | 1 + docs/changelogs/1.12.x/1.12.1.md | 145 ++++++++++++++++++ include/constants/expansion.h | 4 +- 7 files changed, 155 insertions(+), 6 deletions(-) create mode 100644 docs/changelogs/1.12.x/1.12.1.md diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 38414dc80f..1ab103d6c7 100644 --- a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml +++ b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.0 (Latest release) + - 1.12.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.0 - 1.11.4 - 1.11.3 - 1.11.2 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 7b1a489cfb..49bf8a5525 100644 --- a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml +++ b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.0 (Latest release) + - 1.12.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.0 - 1.11.4 - 1.11.3 - 1.11.2 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index 197791a776..0d25f6a96a 100644 --- a/.github/ISSUE_TEMPLATE/04_other_errors.yaml +++ b/.github/ISSUE_TEMPLATE/04_other_errors.yaml @@ -43,9 +43,10 @@ body: label: Version description: What version of pokeemerald-expansion are you using? options: - - 1.12.0 (Latest release) + - 1.12.1 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.0 - 1.11.4 - 1.11.3 - 1.11.1 diff --git a/README.md b/README.md index 626eea5d7e..6d86c27a2a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you use **`pokeemerald-expansion`**, please credit **RHH (Rom Hacking Hideout)**. Optionally, include the version number for clarity. ``` -Based off RHH's pokeemerald-expansion 1.12.0 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.12.1 https://github.com/rh-hideout/pokeemerald-expansion/ ``` Please consider [crediting all contributors](CREDITS.md) involved in the project! diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index fa03ca20ee..258d078cdb 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -20,6 +20,7 @@ - [Day/Night System FAQ](tutorials/dns.md) - [Changelog](./CHANGELOG.md) - [1.12.x]() + - [Version 1.12.1](changelogs/1.12.x/1.12.1.md) - [Version 1.12.0](changelogs/1.12.x/1.12.0.md) - [1.11.x]() - [Version 1.11.4](changelogs/1.11.x/1.11.4.md) diff --git a/docs/changelogs/1.12.x/1.12.1.md b/docs/changelogs/1.12.x/1.12.1.md new file mode 100644 index 0000000000..ba1d24c934 --- /dev/null +++ b/docs/changelogs/1.12.x/1.12.1.md @@ -0,0 +1,145 @@ +```md +## How to update +- If you haven't set up a remote, run the command `git remote add RHH https://github.com/rh-hideout/pokeemerald-expansion`. +- Once you have your remote set up, run the command `git pull RHH expansion/1.12.1 +`. +``` + + +## 🧬 General 🧬 +### Changed +* Changed trainer tutorial to take into account removed palette compression by @hedara90 in [#7044](https://github.com/rh-hideout/pokeemerald-expansion/pull/7044) +* Update CI to ignore allcontributors commits by @pkmnsnfrn in [#7046](https://github.com/rh-hideout/pokeemerald-expansion/pull/7046) +* Fixed CI issue introduced 7046 by @pkmnsnfrn in [#7072](https://github.com/rh-hideout/pokeemerald-expansion/pull/7072) +* Added loop iterator style by @hedara90 in [#7092](https://github.com/rh-hideout/pokeemerald-expansion/pull/7092) +* Fix typo in INSTALL.md by @hedara90 in [#7116](https://github.com/rh-hideout/pokeemerald-expansion/pull/7116) +* Use RGB values for DEFAULT_LIGHT_COLOR by @hedara90 in [#7133](https://github.com/rh-hideout/pokeemerald-expansion/pull/7133) +* Applied Kasen's documentation improvements by @hedara90 in [#7104](https://github.com/rh-hideout/pokeemerald-expansion/pull/7104) +* Fixed description of `FORM_CHANGE_WITHDRAW` by @AsparagusEduardo in [#7152](https://github.com/rh-hideout/pokeemerald-expansion/pull/7152) +* Pret merge (19th of June, 2025) by @Bassoonian in [#7163](https://github.com/rh-hideout/pokeemerald-expansion/pull/7163) +* Update the description of OW_OBJECT_VANILLA_SHADOWS by @pkmnsnfrn in [#7184](https://github.com/rh-hideout/pokeemerald-expansion/pull/7184) +* fix: use BackPickId to calculate player intro ball throw animation palette by @pablopenna in [#7193](https://github.com/rh-hideout/pokeemerald-expansion/pull/7193) + +### Fixed +* Added line break between Trainer 1 name and Trainer 2 name in sText_TwoTrainersWantToBattle by @grintoul1 in [#7028](https://github.com/rh-hideout/pokeemerald-expansion/pull/7028) +* Fixed Battle Pyramid mon generation by @hedara90 in [#7146](https://github.com/rh-hideout/pokeemerald-expansion/pull/7146) +* force sGFRomHeader to always be present by @DizzyEggg in [#7186](https://github.com/rh-hideout/pokeemerald-expansion/pull/7186) +* force RHH Rom Header to always be present by @DizzyEggg in [#7187](https://github.com/rh-hideout/pokeemerald-expansion/pull/7187) +* Fixed debug flag menu sound by @AsparagusEduardo in [#7190](https://github.com/rh-hideout/pokeemerald-expansion/pull/7190) +* Fix BtlController_EmitChosenMonReturnValue UB by @DizzyEggg in [#7197](https://github.com/rh-hideout/pokeemerald-expansion/pull/7197) +* Backported Safari catch and add to party fix by @hedara90 in [#7192](https://github.com/rh-hideout/pokeemerald-expansion/pull/7192) +* Fix 01_battle_engine_bugs.yaml by @hedara90 in [#7242](https://github.com/rh-hideout/pokeemerald-expansion/pull/7242) + +## 🗺️ Overworld 🗺️ +### Fixed +* Bug fix: clear saved follower NPC door warp when doing dive warp by @Bivurnum in [#7065](https://github.com/rh-hideout/pokeemerald-expansion/pull/7065) +* Fix Contest Painting load palette error by @ExMingYan in [#7077](https://github.com/rh-hideout/pokeemerald-expansion/pull/7077) +* Bug fix: Follower NPC no longer retains bike sprite after white out by @Bivurnum in [#7120](https://github.com/rh-hideout/pokeemerald-expansion/pull/7120) +* Bug fix: clear follower npc surf blob on white out by @Bivurnum in [#7153](https://github.com/rh-hideout/pokeemerald-expansion/pull/7153) + +## 🐉 Pokémon 🐉 +### Changed +* Fixes Rapid Spin description (#7178) by @grintoul1 in [#7181](https://github.com/rh-hideout/pokeemerald-expansion/pull/7181) + +### Fixed +* Fixed text width for a lot of forms in HGSS Dex by @AsparagusEduardo in [#7035](https://github.com/rh-hideout/pokeemerald-expansion/pull/7035) +* Fixes Roamers not saving shininess by @i0brendan0 in [#7185](https://github.com/rh-hideout/pokeemerald-expansion/pull/7185) +* [FIX] Prevent caught Pokémon loss in NPC partner battles by @J2M2 in [#7177](https://github.com/rh-hideout/pokeemerald-expansion/pull/7177) + +## ⚔️ Battle General ⚔️ +### Changed +* Fixes large battle messages being cut off instead of being prompted to advance 2 by @PhallenTree in [#7036](https://github.com/rh-hideout/pokeemerald-expansion/pull/7036) +* Battle controller pret documentation by @AlexOn1ine in [#7029](https://github.com/rh-hideout/pokeemerald-expansion/pull/7029) +* Fix typos and some cleanup (mainly in battle files) by @PhallenTree in [#7107](https://github.com/rh-hideout/pokeemerald-expansion/pull/7107) + +### Fixed +* Fixes multi battle party re-order by @AlexOn1ine in [#7042](https://github.com/rh-hideout/pokeemerald-expansion/pull/7042) +* Fixes Aura Wheel + Normalize and Hunger Switch while Transformed/Terastallized by @PhallenTree in [#7061](https://github.com/rh-hideout/pokeemerald-expansion/pull/7061) +* Fixes speed calculation order by @AlexOn1ine in [#7064](https://github.com/rh-hideout/pokeemerald-expansion/pull/7064) +* Bug fix for Grassy Terrain incorrectly healing non-grounded Pokemon by @LinathanZel in [#7058](https://github.com/rh-hideout/pokeemerald-expansion/pull/7058) +* Fixes Wandering Spirit copied ability activation on fainted mon by @AlexOn1ine in [#7066](https://github.com/rh-hideout/pokeemerald-expansion/pull/7066) +* Chloroblast fix by @LinathanZel in [#7008](https://github.com/rh-hideout/pokeemerald-expansion/pull/7008) +* Fix Normalize not boosting Normal type moves if they were already Normal type by @i0brendan0 in [#7060](https://github.com/rh-hideout/pokeemerald-expansion/pull/7060) +* Fixes freeze during a 1v2 double battle by @AlexOn1ine in [#7075](https://github.com/rh-hideout/pokeemerald-expansion/pull/7075) +* Fixes Pursuit potentially causing both battlers to switch into the same mon by @PhallenTree in [#7084](https://github.com/rh-hideout/pokeemerald-expansion/pull/7084) +* Fixed potential mismatch between players and battlers in tests by @AsparagusEduardo in [#7101](https://github.com/rh-hideout/pokeemerald-expansion/pull/7101) +* Fixes Ally Switch in multi battles by @AlexOn1ine in [#7109](https://github.com/rh-hideout/pokeemerald-expansion/pull/7109) +* Add missing flag for Berserk Gene by @AlexOn1ine in [#7151](https://github.com/rh-hideout/pokeemerald-expansion/pull/7151) +* Fixes Neutralizing Gas leaving the field activating unsuppressable abilities again by @PhallenTree in [#7170](https://github.com/rh-hideout/pokeemerald-expansion/pull/7170) +* Fixes Enigma, Kee and Maranga Berry activation timing by @AlexOn1ine in [#7171](https://github.com/rh-hideout/pokeemerald-expansion/pull/7171) +* Fixes wrong Future Sight indexing by @AlexOn1ine in [#7198](https://github.com/rh-hideout/pokeemerald-expansion/pull/7198) +* Fixes OOB for Teatime and Flower Shield by @AlexOn1ine in [#7214](https://github.com/rh-hideout/pokeemerald-expansion/pull/7214) +* Fixes wrong assignment in TrySymbiosis by @AlexOn1ine in [#7221](https://github.com/rh-hideout/pokeemerald-expansion/pull/7221) +* Adds missing healBlockTimer for Baton Pass by @AlexOn1ine in [#7220](https://github.com/rh-hideout/pokeemerald-expansion/pull/7220) +* Jaboca berry triggers instead of being stolen by bug bite by @ghoulslash in [#7237](https://github.com/rh-hideout/pokeemerald-expansion/pull/7237) +* Fixes Scald defrosting target while asleep by @AlexOn1ine in [#7233](https://github.com/rh-hideout/pokeemerald-expansion/pull/7233) +* Fixes Emergency Exit sometimes causing an unrelated battler to become invisible by @PhallenTree in [#7241](https://github.com/rh-hideout/pokeemerald-expansion/pull/7241) + +## 🤹 Moves 🤹 +### Changed +* Fix ScaryFace anim for Bitter Malice by @TLM-PsIQ in [#6476](https://github.com/rh-hideout/pokeemerald-expansion/pull/6476) + +### Fixed +* Fix savage spin out spider web template by @ghoulslash in [#7137](https://github.com/rh-hideout/pokeemerald-expansion/pull/7137) + +## 🎭 Abilities 🎭 +### Changed +* Flush textbox for Truant Popup by @ghoulslash in [#7252](https://github.com/rh-hideout/pokeemerald-expansion/pull/7252) + +## 🧶 Items 🧶 +### Fixed +* Fix sell price display by @cawtds in [#7123](https://github.com/rh-hideout/pokeemerald-expansion/pull/7123) + +## 🤖 Battle AI 🤖 +### Fixed +* Added AI_FLAG_PP_STALL_PREVENTION to AI_FLAG_SMART_TRAINER by @AlexOn1ine in [#7112](https://github.com/rh-hideout/pokeemerald-expansion/pull/7112) +* Fix incorrect function parameters used in AI damage calc by @Pawkkie in [#7130](https://github.com/rh-hideout/pokeemerald-expansion/pull/7130) + +## 🧹 Other Cleanup 🧹 +* Fix typos and some cleanup (mainly in battle files) by @PhallenTree in [#7107](https://github.com/rh-hideout/pokeemerald-expansion/pull/7107) +* Fix typo in INSTALL.md by @hedara90 in [#7116](https://github.com/rh-hideout/pokeemerald-expansion/pull/7116) +* Fixed description of `FORM_CHANGE_WITHDRAW` by @AsparagusEduardo in [#7152](https://github.com/rh-hideout/pokeemerald-expansion/pull/7152) +* Spruce up `FEATURES.md` by @AsparagusEduardo in [#7159](https://github.com/rh-hideout/pokeemerald-expansion/pull/7159) +* Fixes Rapid Spin description (#7178) by @grintoul1 in [#7181](https://github.com/rh-hideout/pokeemerald-expansion/pull/7181) + +## 🧪 Test Runner 🧪 +### Changed +* Wrote some missing tests by @AsparagusEduardo in [#7094](https://github.com/rh-hideout/pokeemerald-expansion/pull/7094) +* Fixed KNOWN_FAILING Tera test by @AsparagusEduardo in [#6949](https://github.com/rh-hideout/pokeemerald-expansion/pull/6949) +* Add some tests by @ghoulslash in [#7234](https://github.com/rh-hideout/pokeemerald-expansion/pull/7234) +* Added tests for Toxic Thread by @hedara90 in [#7244](https://github.com/rh-hideout/pokeemerald-expansion/pull/7244) + +### Fixed +* Test runner fixes by @hedara90 in [#7100](https://github.com/rh-hideout/pokeemerald-expansion/pull/7100) +* Fixed Aura Wheel `KNOWN_FAILING` test by @AsparagusEduardo in [#7135](https://github.com/rh-hideout/pokeemerald-expansion/pull/7135) +* Fix AI party count calc being maintained between tests by @AsparagusEduardo in [#7200](https://github.com/rh-hideout/pokeemerald-expansion/pull/7200) +* Fix tests failing with `B_FRIENDSHIP_BOOST` being `TRUE` by @AsparagusEduardo in [#7194](https://github.com/rh-hideout/pokeemerald-expansion/pull/7194) +* Jaboca berry triggers instead of being stolen by bug bite by @ghoulslash in [#7237](https://github.com/rh-hideout/pokeemerald-expansion/pull/7237) + +## 📚 Documentation 📚 +* Changed trainer tutorial to take into account removed palette compression by @hedara90 in [#7044](https://github.com/rh-hideout/pokeemerald-expansion/pull/7044) +* Battle controller pret documentation by @AlexOn1ine in [#7029](https://github.com/rh-hideout/pokeemerald-expansion/pull/7029) +* Added loop iterator style by @hedara90 in [#7092](https://github.com/rh-hideout/pokeemerald-expansion/pull/7092) +* Use RGB values for DEFAULT_LIGHT_COLOR by @hedara90 in [#7133](https://github.com/rh-hideout/pokeemerald-expansion/pull/7133) +* Applied Kasen's documentation improvements by @hedara90 in [#7104](https://github.com/rh-hideout/pokeemerald-expansion/pull/7104) +* Spruce up `FEATURES.md` by @AsparagusEduardo in [#7159](https://github.com/rh-hideout/pokeemerald-expansion/pull/7159) +* Update the description of OW_OBJECT_VANILLA_SHADOWS by @pkmnsnfrn in [#7184](https://github.com/rh-hideout/pokeemerald-expansion/pull/7184) + +## 📦 Branch Synchronisation 📦 +### pret +* 24th of June, 2025 in [#7206](https://github.com/rh-hideout/pokeemerald-expansion/pull/7206) + * Move gTradePlatform_Tilemap to header and change to u32 by @DizzyEggg in [pret#2088](https://github.com/pret/pokeemerald/pull/2088) + * Fix wrong keep temps files directory in makefile by @DizzyEggg in [pret#2156](https://github.com/pret/pokeemerald/pull/2156) + * Fix collision comparison in PlayerNotOnBikeMoving by @GriffinRichards in [pret#2104](https://github.com/pret/pokeemerald/pull/2104) + * Match graphics declarations with externs in graphics.h by @DizzyEggg in [pret#2089](https://github.com/pret/pokeemerald/pull/2089) + +## New Contributors +* @TLM-PsIQ made their first contribution in [#6476](https://github.com/rh-hideout/pokeemerald-expansion/pull/6476) +* @pablopenna made their first contribution in [#7193](https://github.com/rh-hideout/pokeemerald-expansion/pull/7193) +* @J2M2 made their first contribution in [#7177](https://github.com/rh-hideout/pokeemerald-expansion/pull/7177) + +**Full Changelog**: https://github.com/rh-hideout/pokeemerald-expansion/compare/expansion/1.12.0...expansion/1.12.1 + + + + diff --git a/include/constants/expansion.h b/include/constants/expansion.h index b0e7397b56..037ae57703 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -1,13 +1,13 @@ #ifndef GUARD_CONSTANTS_EXPANSION_H #define GUARD_CONSTANTS_EXPANSION_H -// Last version: 1.12.0 +// Last version: 1.12.1 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 12 #define EXPANSION_VERSION_PATCH 1 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. -#define EXPANSION_TAGGED_RELEASE FALSE +#define EXPANSION_TAGGED_RELEASE TRUE #endif From 947faa97d3ec35a53814673c0de7f66fcb5ca677 Mon Sep 17 00:00:00 2001 From: Hedara Date: Mon, 30 Jun 2025 11:01:46 +0200 Subject: [PATCH 39/50] Start of 1.12.2 cycle --- include/constants/expansion.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/constants/expansion.h b/include/constants/expansion.h index 037ae57703..11822f8510 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -4,10 +4,10 @@ // Last version: 1.12.1 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 12 -#define EXPANSION_VERSION_PATCH 1 +#define EXPANSION_VERSION_PATCH 2 // FALSE if this this version of Expansion is not a tagged commit, i.e. // it contains unreleased changes. -#define EXPANSION_TAGGED_RELEASE TRUE +#define EXPANSION_TAGGED_RELEASE FALSE #endif From 5451e40830ed9c8a65d797eabfb04e10566e3275 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 30 Jun 2025 21:41:29 +0200 Subject: [PATCH 40/50] Fixes Toxic Thread animation not being played at the right time (#7247) Co-authored-by: hedara90 <90hedara@gmail.com> --- asm/macros/battle_script.inc | 4 +- data/battle_scripts_1.s | 9 +-- src/battle_script_commands.c | 33 +++++++--- src/data/moves_info.h | 10 +-- .../move_effects_combined/toxic_thread.c | 61 ++++++++++++++++++- 5 files changed, 96 insertions(+), 21 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index b524104a36..673f3ef963 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -834,8 +834,10 @@ .4byte \failInstr .endm - .macro unused_0x94 + .macro checknonvolatiletrigger nonVolatile:req, failInstr:req .byte 0x94 + .2byte \nonVolatile + .4byte \failInstr .endm .macro copybidedmg diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 7fcf186910..56bb8fb63e 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -1836,20 +1836,20 @@ BattleScript_EffectToxicThread:: setstatchanger STAT_SPEED, 1, TRUE attackcanceler jumpifsubstituteblocks BattleScript_FailedFromAtkString - jumpifstat BS_TARGET, CMP_NOT_EQUAL, STAT_SPEED, MIN_STAT_STAGE, BattleScript_ToxicThreadWorks - jumpifstatus BS_TARGET, STATUS1_PSN_ANY, BattleScript_FailedFromAtkString + checknonvolatiletrigger MOVE_EFFECT_POISON, BattleScript_EffectStatDownFromAccCheck BattleScript_ToxicThreadWorks: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce + attackanimation + waitanimation + setstatchanger STAT_SPEED, 1, TRUE statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_ToxicThreadTryPsn jumpifbyte CMP_LESS_THAN, cMULTISTRING_CHOOSER, B_MSG_STAT_WONT_DECREASE, BattleScript_ToxicThreadDoAnim jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_STAT_FELL_EMPTY, BattleScript_ToxicThreadTryPsn pause B_WAIT_TIME_SHORT goto BattleScript_ToxicThreadPrintString BattleScript_ToxicThreadDoAnim:: - attackanimation - waitanimation setgraphicalstatchangevalues playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 BattleScript_ToxicThreadPrintString:: @@ -3144,6 +3144,7 @@ BattleScript_EffectEvasionDown:: BattleScript_EffectStatDown: attackcanceler jumpifsubstituteblocks BattleScript_FailedFromAtkString +BattleScript_EffectStatDownFromAccCheck: accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE BattleScript_StatDownFromAttackString: attackstring diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f0957241ca..caafa7f303 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -496,7 +496,7 @@ static void Cmd_tryconversiontypechange(void); static void Cmd_givepaydaymoney(void); static void Cmd_setlightscreen(void); static void Cmd_tryKO(void); -static void Cmd_unused_0x94(void); +static void Cmd_checknonvolatiletrigger(void); static void Cmd_copybidedmg(void); static void Cmd_unused_96(void); static void Cmd_tryinfatuating(void); @@ -755,7 +755,7 @@ void (*const gBattleScriptingCommandsTable[])(void) = Cmd_givepaydaymoney, //0x91 Cmd_setlightscreen, //0x92 Cmd_tryKO, //0x93 - Cmd_unused_0x94, //0x94 + Cmd_checknonvolatiletrigger, //0x94 Cmd_copybidedmg, //0x95 Cmd_unused_96, //0x96 Cmd_tryinfatuating, //0x97 @@ -12594,12 +12594,13 @@ static void Cmd_trynonvolatilestatus(void) CMD_ARGS(); bool32 canInflictStatus = TRUE; - if (!CanSetNonVolatileStatus(gBattlerAttacker, - gBattlerTarget, - GetBattlerAbility(gBattlerAttacker), - GetBattlerAbility(gBattlerTarget), - GetMoveNonVolatileStatus(gCurrentMove), - STATUS_RUN_SCRIPT)) + if (!CanSetNonVolatileStatus( + gBattlerAttacker, + gBattlerTarget, + GetBattlerAbility(gBattlerAttacker), + GetBattlerAbility(gBattlerTarget), + GetMoveNonVolatileStatus(gCurrentMove), + STATUS_RUN_SCRIPT)) canInflictStatus = FALSE; if (canInflictStatus && DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) @@ -13048,8 +13049,22 @@ static void Cmd_tryKO(void) #undef FOCUS_BANDED #undef AFFECTION_ENDURED -static void Cmd_unused_0x94(void) +static void Cmd_checknonvolatiletrigger(void) { + CMD_ARGS(u16 nonVolatile, const u8 *failInstr); + + if (!CanSetNonVolatileStatus( + gBattlerAttacker, + gBattlerTarget, + GetBattlerAbility(gBattlerAttacker), + GetBattlerAbility(gBattlerTarget), + cmd->nonVolatile, + STATUS_CHECK_TRIGGER)) + gBattlescriptCurrInstr = cmd->failInstr; + else if (DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)) + gBattlescriptCurrInstr = cmd->failInstr; + else + gBattlescriptCurrInstr = cmd->nextInstr; } static void Cmd_copybidedmg(void) diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 51f3438952..1e13d62eb8 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -2866,7 +2866,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "Minimizes the user's size to\n" #if B_MINIMIZE_EVASION >= GEN_5 "sharply raise evasiveness."), - #else + #else "raise evasiveness."), #endif .effect = EFFECT_MINIMIZE, @@ -3704,7 +3704,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( #if B_UPDATED_MOVE_DATA >= GEN_5 "Envelops the foes in a toxic\n" - #else + #else "Envelops the foe in a toxic\n" #endif "gas that may poison."), @@ -6053,7 +6053,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "User spins and removes some\n" #if B_SPEED_BUFFING_RAPID_SPIN >= GEN_8 "effects, while upping speed."), - #else + #else "effects."), #endif .effect = EFFECT_RAPID_SPIN, @@ -6280,7 +6280,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = #else "The type and effectiveness\n" "vary with the user."), - #endif + #endif .power = B_HIDDEN_POWER_DMG >= GEN_6 ? 60 : 1, .effect = EFFECT_HIDDEN_POWER, .type = TYPE_NORMAL, @@ -9621,7 +9621,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = "Whips up a breeze, doubling\n" #if B_TAILWIND_TURNS >= GEN_5 "ally Speed for 4 turns."), - #else + #else "ally Speed for 3 turns."), #endif .effect = EFFECT_TAILWIND, diff --git a/test/battle/move_effects_combined/toxic_thread.c b/test/battle/move_effects_combined/toxic_thread.c index c946619cd8..ec27f46365 100644 --- a/test/battle/move_effects_combined/toxic_thread.c +++ b/test/battle/move_effects_combined/toxic_thread.c @@ -25,7 +25,6 @@ SINGLE_BATTLE_TEST("Toxic Thread both reduces speed and inflicts Poison") SINGLE_BATTLE_TEST("Toxic Thread still inflicts Poison if speed can't go lower") { - KNOWN_FAILING; // #7243 GIVEN { ASSUME(GetMoveEffect(MOVE_SCARY_FACE) == EFFECT_SPEED_DOWN_2); PLAYER(SPECIES_WOBBUFFET); @@ -53,7 +52,6 @@ SINGLE_BATTLE_TEST("Toxic Thread still inflicts Poison if speed can't go lower") SINGLE_BATTLE_TEST("Toxic Thread still inflicts Poison if speed can't be lowered") { - KNOWN_FAILING; // #7243 GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_REGICE) { Ability(ABILITY_CLEAR_BODY); } @@ -106,3 +104,62 @@ SINGLE_BATTLE_TEST("Toxic Thread still lowers speed if the target is already Poi EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE - 1); } } + +SINGLE_BATTLE_TEST("Toxic Thread fails if speed can't be lowered and status can't be inflicted") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_POISON_POWDER); } + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_POWDER, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + } +} + +SINGLE_BATTLE_TEST("Toxic Thread fails if speed can't be lowered due to Clear Body and status can't be inflicted") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_REGICE) { Ability(ABILITY_CLEAR_BODY); } + } WHEN { + TURN { MOVE(player, MOVE_POISON_POWDER); } + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_POWDER, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + } +} + +SINGLE_BATTLE_TEST("Toxic Thread fails if speed can't be lowered and target is a poison type") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_POISON_POWDER) == EFFECT_NON_VOLATILE_STATUS); + ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_POWDER) == MOVE_EFFECT_POISON); + ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_POISON || gSpeciesInfo[SPECIES_ODDISH].types[1] == TYPE_POISON); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ODDISH); + } WHEN { + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_SCARY_FACE); } + TURN { MOVE(player, MOVE_TOXIC_THREAD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCARY_FACE, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC_THREAD, player); + } +} From 89b1a45536936f7abe1b897b3e05a221eb5bd381 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 1 Jul 2025 16:39:22 +0200 Subject: [PATCH 41/50] Fixes Ice Spinner and Steel Roller (#7259) --- asm/macros/battle_script.inc | 10 +- data/battle_scripts_1.s | 34 ++--- include/battle_scripts.h | 4 +- include/constants/battle_move_effects.h | 4 +- include/constants/battle_script_commands.h | 8 +- include/move.h | 5 + remove_terrain.log | 0 src/battle_ai_util.c | 6 +- src/battle_script_commands.c | 75 ++++------- src/data/battle_move_effects.h | 16 ++- src/data/moves_info.h | 13 +- test/battle/gimmick/zmove.c | 4 +- test/battle/move_animations/all_anims.c | 4 +- .../move_effect/hit_set_remove_terrain.c | 126 ------------------ test/battle/move_effect/ice_spinner.c | 122 +++++++++++++++++ test/battle/move_effect/steel_roller.c | 75 +++++++++++ 16 files changed, 275 insertions(+), 231 deletions(-) create mode 100644 remove_terrain.log create mode 100644 test/battle/move_effect/ice_spinner.c create mode 100644 test/battle/move_effect/steel_roller.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 673f3ef963..02546d2f8a 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1529,14 +1529,8 @@ .4byte \jumpInstr .endm - .macro jumpifmovepropertyargument argument:req, jumpInstr:req - callnative BS_JumpIfMovePropertyArgument - .byte \argument - .4byte \jumpInstr - .endm - - .macro setremoveterrain failInstr:req - callnative BS_SetRemoveTerrain + .macro setterrain failInstr:req + callnative BS_SetTerrain .4byte \failInstr .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 56bb8fb63e..e32dfd2859 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2248,7 +2248,7 @@ BattleScript_EffectPsychicTerrain:: attackcanceler attackstring ppreduce - setremoveterrain BattleScript_ButItFailed + setterrain BattleScript_ButItFailed attackanimation waitanimation printfromtable gTerrainStringIds @@ -9303,12 +9303,11 @@ BattleScript_ExtremeEvoboostSpDef:: BattleScript_ExtremeEvoboostEnd:: goto BattleScript_MoveEnd -BattleScript_EffectHitSetRemoveTerrain:: +BattleScript_EffectHitSetTerrain:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE attackstring ppreduce - jumpifmovepropertyargument ARG_TRY_REMOVE_TERRAIN_FAIL, BattleScript_RemoveTerrain critcalc damagecalc adjustdamage @@ -9323,7 +9322,7 @@ BattleScript_EffectHitSetRemoveTerrain:: waitmessage B_WAIT_TIME_LONG resultmessage waitmessage B_WAIT_TIME_LONG - setremoveterrain BattleScript_TryFaint + setterrain BattleScript_TryFaint playanimation BS_ATTACKER, B_ANIM_RESTORE_BG printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG @@ -9331,30 +9330,17 @@ BattleScript_TryFaint: tryfaintmon BS_TARGET goto BattleScript_MoveEnd -BattleScript_RemoveTerrain: - jumpifterrainaffected BS_TARGET, STATUS_FIELD_TERRAIN_ANY, BattleScript_RemoveTerrain_Cont - goto BattleScript_ButItFailed -BattleScript_RemoveTerrain_Cont: - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG +BattleScript_EffectSteelRoller:: + attackcanceler + jumpifhalfword CMP_NO_COMMON_BITS, gFieldStatuses, STATUS_FIELD_TERRAIN_ANY, BattleScript_FailedFromAtkString + goto BattleScript_HitFromAccCheck + +BattleScript_RemoveTerrain:: removeterrain playanimation BS_ATTACKER, B_ANIM_RESTORE_BG printfromtable gTerrainStringIds waitmessage B_WAIT_TIME_LONG - tryfaintmon BS_TARGET - goto BattleScript_MoveEnd + return BattleScript_Pickpocket:: call BattleScript_AbilityPopUp diff --git a/include/battle_scripts.h b/include/battle_scripts.h index de3e876aa2..cd88a120a5 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -292,6 +292,7 @@ extern const u8 BattleScript_CursedBodyActivates[]; extern const u8 BattleScript_MummyActivates[]; extern const u8 BattleScript_WeakArmorActivates[]; extern const u8 BattleScript_FellStingerRaisesStat[]; +extern const u8 BattleScript_RemoveTerrain[]; extern const u8 BattleScript_SnowWarningActivatesHail[]; extern const u8 BattleScript_SnowWarningActivatesSnow[]; extern const u8 BattleScript_PickupActivates[]; @@ -339,6 +340,7 @@ extern const u8 BattleScript_GrassySurgeActivates[]; extern const u8 BattleScript_MistySurgeActivates[]; extern const u8 BattleScript_ElectricSurgeActivates[]; extern const u8 BattleScript_EffectSpectralThief[]; +extern const u8 BattleScript_EffectSteelRoller[]; extern const u8 BattleScript_StatUpMsg[]; extern const u8 BattleScript_AbilityRaisesDefenderStat[]; extern const u8 BattleScript_PowderMoveNoEffect[]; @@ -842,7 +844,7 @@ extern const u8 BattleScript_EffectSkyDrop[]; extern const u8 BattleScript_EffectMeteorBeam[]; extern const u8 BattleScript_EffectCourtChange[]; extern const u8 BattleScript_EffectExtremeEvoboost[]; -extern const u8 BattleScript_EffectHitSetRemoveTerrain[]; +extern const u8 BattleScript_EffectHitSetTerrain[]; extern const u8 BattleScript_EffectDarkVoid[]; extern const u8 BattleScript_EffectVictoryDance[]; extern const u8 BattleScript_EffectTeatime[]; diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index d081d3a163..e21387c2af 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -310,7 +310,7 @@ enum BattleMoveEffects EFFECT_MIND_BLOWN, // Same as EFFECT_MAX_HP_50_RECOIL but is cancelled by Damp EFFECT_CHLOROBLAST, // Same effect as EFFECT_MAX_HP_50_RECOIL but follows the same rules as EFFECT_RECOIL EFFECT_EXTREME_EVOBOOST, - EFFECT_HIT_SET_REMOVE_TERRAIN, + EFFECT_HIT_SET_TERRAIN, EFFECT_DARK_VOID, EFFECT_VICTORY_DANCE, EFFECT_TEATIME, @@ -349,6 +349,8 @@ enum BattleMoveEffects EFFECT_SPECTRAL_THIEF, EFFECT_RECOIL, EFFECT_SMACK_DOWN, + EFFECT_ICE_SPINNER, // Removes terrain unless attacker is removed from field either by fainting or ejected out + EFFECT_STEEL_ROLLER, // Will fail if there is no terrain up but removes it regardless if attacker is removed from field or not NUM_BATTLE_MOVE_EFFECTS, }; diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 2b0287be40..1da5f3b134 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -243,7 +243,7 @@ enum CmdVarious #define PARTY_SCREEN_OPTIONAL (1 << 7) // Flag for first argument to openpartyscreen -// cases for Cmd_moveend +// cases for Cmd_moveend - Order matters! enum MoveEndEffects { MOVEEND_SUM_DAMAGE, @@ -283,6 +283,7 @@ enum MoveEndEffects MOVEEND_HIT_ESCAPE, MOVEEND_OPPORTUNIST, // Occurs after other stat change items/abilities to try and copy the boosts MOVEEND_PICKPOCKET, + MOVEEND_REMOVE_TERRAIN, MOVEEND_WHITE_HERB, MOVEEND_CHANGED_ITEMS, MOVEEND_SAME_MOVE_TURNS, @@ -297,9 +298,4 @@ enum MoveEndEffects #define B_SWITCH_HIT 1 // dragon tail, circle throw #define B_SWITCH_RED_CARD 2 -// Argument labels for EFFECT_HIT_SET_REMOVE_TERRAIN -#define ARG_SET_PSYCHIC_TERRAIN 0 -#define ARG_TRY_REMOVE_TERRAIN_HIT 1 -#define ARG_TRY_REMOVE_TERRAIN_FAIL 2 - #endif // GUARD_CONSTANTS_BATTLE_SCRIPT_COMMANDS_H diff --git a/include/move.h b/include/move.h index 16ede9d809..52d4d0f072 100644 --- a/include/move.h +++ b/include/move.h @@ -498,6 +498,11 @@ static inline u32 GetMoveProtectMethod(u32 moveId) return gMovesInfo[SanitizeMoveId(moveId)].argument.protectMethod; } +static inline u32 GetMoveTerrainFlag(u32 moveId) +{ + return gMovesInfo[SanitizeMoveId(moveId)].argument.moveProperty; +} + static inline u32 GetMoveEffectArg_Status(u32 moveId) { return gMovesInfo[SanitizeMoveId(moveId)].argument.status; diff --git a/remove_terrain.log b/remove_terrain.log new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 93801927bd..2d7136eefc 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -548,8 +548,8 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy if (!IS_BATTLER_OF_TYPE(battlerAtk, GetMoveArgType(move))) return TRUE; break; - case EFFECT_HIT_SET_REMOVE_TERRAIN: - if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY) && GetMoveEffectArg_MoveProperty(move) == ARG_TRY_REMOVE_TERRAIN_FAIL) + case EFFECT_STEEL_ROLLER: + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) return TRUE; break; case EFFECT_POLTERGEIST: @@ -827,7 +827,7 @@ struct SimulatedDamage AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u simDamage.median = ApplyModifiersAfterDmgRoll(simDamage.median, &damageCalcData, effectivenessMultiplier, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], aiData->holdEffects[battlerAtk], aiData->holdEffects[battlerDef]); - + simDamage.maximum = GetDamageByRollType(damage, DMG_ROLL_HIGHEST); simDamage.maximum = ApplyModifiersAfterDmgRoll(simDamage.maximum, &damageCalcData, effectivenessMultiplier, aiData->abilities[battlerAtk], aiData->abilities[battlerDef], diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index caafa7f303..a1d29bc696 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7363,6 +7363,24 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_REMOVE_TERRAIN: + if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER // Steel Roller has to check the chosen move, Otherwise it would fail in certain cases + && IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RemoveTerrain; + effect = TRUE; + } + else if (moveEffect == EFFECT_ICE_SPINNER + && IsBattlerAlive(gBattlerAttacker) + && IsBattlerTurnDamaged(gBattlerTarget)) + { + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_RemoveTerrain; + effect = TRUE; + } + gBattleScripting.moveendState++; + break; case MOVEEND_SYMBIOSIS: for (i = 0; i < gBattlersCount; i++) { @@ -17281,17 +17299,7 @@ void BS_ApplySaltCure(void) gBattlescriptCurrInstr = cmd->nextInstr; } -void BS_JumpIfMovePropertyArgument(void) -{ - NATIVE_ARGS(u8 argument, const u8 *jumpInstr); - - if (GetMoveEffectArg_MoveProperty(gCurrentMove) == cmd->argument) - gBattlescriptCurrInstr = cmd->jumpInstr; - else - gBattlescriptCurrInstr = cmd->nextInstr; -} - -void BS_SetRemoveTerrain(void) +void BS_SetTerrain(void) { NATIVE_ARGS(const u8 *jumpInstr); u32 statusFlag = 0; @@ -17314,48 +17322,19 @@ void BS_SetRemoveTerrain(void) statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; break; - case EFFECT_HIT_SET_REMOVE_TERRAIN: - switch (GetMoveEffectArg_MoveProperty(gCurrentMove)) - { - case ARG_SET_PSYCHIC_TERRAIN: // Genesis Supernova - statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; - break; - case ARG_TRY_REMOVE_TERRAIN_HIT: // Splintered Stormshards - case ARG_TRY_REMOVE_TERRAIN_FAIL: // Steel Roller - if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) - { - // No terrain to remove, jump to battle script pointer. - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - // Remove all terrains. - RemoveAllTerrains(); - gBattlescriptCurrInstr = cmd->nextInstr; - } - return; - default: - break; - } + case EFFECT_HIT_SET_TERRAIN: + statusFlag = GetMoveTerrainFlag(gCurrentMove); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_TERRAIN_SET_PSYCHIC; break; default: break; } + enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - if (gFieldStatuses & statusFlag || statusFlag == 0) - { - gBattlescriptCurrInstr = cmd->jumpInstr; - } - else - { - enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(gBattlerAttacker, TRUE); - - gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; - gFieldStatuses |= statusFlag; - gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5; - gBattlescriptCurrInstr = cmd->nextInstr; - } + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; + gFieldStatuses |= statusFlag; + gFieldTimers.terrainTimer = gBattleTurnCounter + (atkHoldEffect == HOLD_EFFECT_TERRAIN_EXTENDER) ? 8 : 5; + gBattlescriptCurrInstr = cmd->nextInstr; } void BS_JumpIfTerrainAffected(void) diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index dfca0c5232..08d8123296 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -1978,9 +1978,9 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, - [EFFECT_HIT_SET_REMOVE_TERRAIN] = + [EFFECT_HIT_SET_TERRAIN] = { - .battleScript = BattleScript_EffectHitSetRemoveTerrain, + .battleScript = BattleScript_EffectHitSetTerrain, .battleTvScore = 0, // TODO: Assign points }, @@ -2218,4 +2218,16 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleScript = BattleScript_EffectHit, .battleTvScore = 0, // TODO: Assign points }, + + [EFFECT_ICE_SPINNER] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, + + [EFFECT_STEEL_ROLLER] = + { + .battleScript = BattleScript_EffectSteelRoller, + .battleTvScore = 0, // TODO: Assign points + }, }; diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 1e13d62eb8..c0e44cf4df 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -18444,7 +18444,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "Destroys terrain. Fails if\n" "ground isn't terrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + .effect = EFFECT_STEEL_ROLLER, .power = 130, .type = TYPE_STEEL, .accuracy = 100, @@ -18453,7 +18453,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_FAIL }, // Remove a field terrain if there is one and hit, otherwise fail. .skyBattleBanned = TRUE, .contestEffect = CONTEST_EFFECT_WORSEN_CONDITION_OF_PREV_MONS, .contestCategory = CONTEST_CATEGORY_TOUGH, @@ -19879,7 +19878,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "Ice-covered feet hit a foe\n" "and destroy the terrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + .effect = EFFECT_ICE_SPINNER, .power = 80, .type = TYPE_ICE, .accuracy = 100, @@ -19888,7 +19887,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, .makesContact = TRUE, - .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one. .skyBattleBanned = B_EXTRAPOLATED_MOVE_FLAGS, .battleAnimScript = gBattleAnimMove_IceSpinner, }, @@ -21520,7 +21518,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "Mew attacks with full force.\n" "Psychically charges terrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + .effect = EFFECT_HIT_SET_TERRAIN, .power = 185, .type = TYPE_PSYCHIC, .accuracy = 0, @@ -21528,7 +21526,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_SPECIAL, - .argument = { .moveProperty = ARG_SET_PSYCHIC_TERRAIN }, // Set Psychic Terrain. If there's a different field terrain active, overwrite it. + .argument = { .moveProperty = STATUS_FIELD_PSYCHIC_TERRAIN }, .battleAnimScript = gBattleAnimMove_GenesisSupernova, }, [MOVE_SINISTER_ARROW_RAID] = @@ -21585,7 +21583,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "Lycanroc attacks with full\n" "force. Removes all terrain."), - .effect = EFFECT_HIT_SET_REMOVE_TERRAIN, + .effect = EFFECT_ICE_SPINNER, .power = 190, .type = TYPE_ROCK, .accuracy = 0, @@ -21593,7 +21591,6 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = DAMAGE_CATEGORY_PHYSICAL, - .argument = { .moveProperty = ARG_TRY_REMOVE_TERRAIN_HIT }, // Remove the active field terrain if there is one. .battleAnimScript = gBattleAnimMove_SplinteredStormshards, }, [MOVE_LETS_SNUGGLE_FOREVER] = diff --git a/test/battle/gimmick/zmove.c b/test/battle/gimmick/zmove.c index fd5635d3fc..058d59c620 100644 --- a/test/battle/gimmick/zmove.c +++ b/test/battle/gimmick/zmove.c @@ -578,7 +578,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Extreme Evoboost boosts all the user's stats by two SINGLE_BATTLE_TEST("(Z-MOVE) Genesis Supernova sets up psychic terrain") { GIVEN { - ASSUME(GetMoveEffect(MOVE_GENESIS_SUPERNOVA) == EFFECT_HIT_SET_REMOVE_TERRAIN); + ASSUME(GetMoveEffect(MOVE_GENESIS_SUPERNOVA) == EFFECT_HIT_SET_TERRAIN); PLAYER(SPECIES_MEW) { Item(ITEM_MEWNIUM_Z); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -595,7 +595,7 @@ SINGLE_BATTLE_TEST("(Z-MOVE) Genesis Supernova sets up psychic terrain") SINGLE_BATTLE_TEST("(Z-MOVE) Splintered Stormshards removes terrain") { GIVEN { - ASSUME(GetMoveEffect(MOVE_SPLINTERED_STORMSHARDS) == EFFECT_HIT_SET_REMOVE_TERRAIN); + ASSUME(GetMoveEffect(MOVE_SPLINTERED_STORMSHARDS) == EFFECT_ICE_SPINNER); PLAYER(SPECIES_LYCANROC_DUSK) { Item(ITEM_LYCANIUM_Z); } OPPONENT(SPECIES_TAPU_LELE) { Ability(ABILITY_PSYCHIC_SURGE); HP(1000); MaxHP(1000); } } WHEN { diff --git a/test/battle/move_animations/all_anims.c b/test/battle/move_animations/all_anims.c index 778b407937..a994bab63f 100644 --- a/test/battle/move_animations/all_anims.c +++ b/test/battle/move_animations/all_anims.c @@ -152,7 +152,7 @@ static void WhenSingles(u32 move, struct BattlePokemon *attacker, struct BattleP { // Has to be hailing TURN { MOVE(attacker, MOVE_HAIL); } } - else if (gMovesInfo[move].effect == EFFECT_HIT_SET_REMOVE_TERRAIN && gMovesInfo[move].argument.moveProperty == ARG_TRY_REMOVE_TERRAIN_FAIL) + else if (gMovesInfo[move].effect == EFFECT_STEEL_ROLLER) { // Needs a terrain TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } } @@ -281,7 +281,7 @@ static void DoublesWhen(u32 move, struct BattlePokemon *attacker, struct BattleP { // Has to be hailing TURN { MOVE(attacker, MOVE_HAIL); } } - else if (gMovesInfo[move].effect == EFFECT_HIT_SET_REMOVE_TERRAIN && gMovesInfo[move].argument.moveProperty == ARG_TRY_REMOVE_TERRAIN_FAIL) + else if (gMovesInfo[move].effect == EFFECT_STEEL_ROLLER) { // Needs a terrain TURN { MOVE(attacker, MOVE_ELECTRIC_TERRAIN); } } diff --git a/test/battle/move_effect/hit_set_remove_terrain.c b/test/battle/move_effect/hit_set_remove_terrain.c index 9b9180d6e4..e69de29bb2 100644 --- a/test/battle/move_effect/hit_set_remove_terrain.c +++ b/test/battle/move_effect/hit_set_remove_terrain.c @@ -1,126 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -ASSUMPTIONS -{ - ASSUME(GetMoveEffect(MOVE_ELECTRIC_TERRAIN) == EFFECT_ELECTRIC_TERRAIN); - ASSUME(GetMoveEffect(MOVE_PSYCHIC_TERRAIN) == EFFECT_PSYCHIC_TERRAIN); - ASSUME(GetMoveEffect(MOVE_GRASSY_TERRAIN) == EFFECT_GRASSY_TERRAIN); - ASSUME(GetMoveEffect(MOVE_MISTY_TERRAIN) == EFFECT_MISTY_TERRAIN); - ASSUME(GetMoveEffect(MOVE_STEEL_ROLLER) == EFFECT_HIT_SET_REMOVE_TERRAIN); - ASSUME(GetMoveEffect(MOVE_ICE_SPINNER) == EFFECT_HIT_SET_REMOVE_TERRAIN); -} - -SINGLE_BATTLE_TEST("Steel Roller and Ice Spinner can remove a terrain from the field") -{ - u32 j; - static const u16 terrainMoves[] = - { - MOVE_ELECTRIC_TERRAIN, - MOVE_PSYCHIC_TERRAIN, - MOVE_GRASSY_TERRAIN, - MOVE_MISTY_TERRAIN, - }; - - u16 terrainMove = MOVE_NONE; - u16 removeTerrainMove = MOVE_NONE; - - for (j = 0; j < ARRAY_COUNT(terrainMoves); j++) - { - PARAMETRIZE { removeTerrainMove = MOVE_STEEL_ROLLER; terrainMove = terrainMoves[j]; } - PARAMETRIZE { removeTerrainMove = MOVE_ICE_SPINNER; terrainMove = terrainMoves[j]; } - } - - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(opponent, terrainMove); MOVE(player, removeTerrainMove); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, terrainMove, opponent); - ANIMATION(ANIM_TYPE_MOVE, removeTerrainMove, player); - switch (terrainMove) - { - case MOVE_ELECTRIC_TERRAIN: - MESSAGE("The electricity disappeared from the battlefield."); - break; - case MOVE_PSYCHIC_TERRAIN: - MESSAGE("The weirdness disappeared from the battlefield!"); - break; - case MOVE_GRASSY_TERRAIN: - MESSAGE("The grass disappeared from the battlefield."); - break; - case MOVE_MISTY_TERRAIN: - MESSAGE("The mist disappeared from the battlefield."); - break; - } - } -} - -SINGLE_BATTLE_TEST("Steel Roller fails if there is no terrain on the field") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_STEEL_ROLLER); } - } SCENE { - NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, player); - MESSAGE("But it failed!"); - } -} - -SINGLE_BATTLE_TEST("Ice Spinner doesn't fail if there is no terrain on the field") -{ - GIVEN { - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET); - } WHEN { - TURN { MOVE(player, MOVE_ICE_SPINNER); } - } SCENE { - ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, player); - NOT MESSAGE("But it failed!"); - } -} - -AI_SINGLE_BATTLE_TEST("AI will not choose Steel Roller if it might fail") -{ - u32 move; - - PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; } - PARAMETRIZE { move = MOVE_NONE; } - - GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_STEEL_ROLLER, MOVE_ICE_SHARD); } - } WHEN { - if (move == MOVE_ELECTRIC_TERRAIN) { - TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SHARD); } - TURN { EXPECT_MOVE(opponent, MOVE_STEEL_ROLLER); } - } else { - TURN { EXPECT_MOVE(opponent, MOVE_ICE_SHARD); } - } - } -} - -AI_SINGLE_BATTLE_TEST("AI will can choose Ice Spinner regardless if there is a terrain or not") -{ - u32 move; - - PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; } - PARAMETRIZE { move = MOVE_NONE; } - - GIVEN { - AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); - PLAYER(SPECIES_WOBBUFFET); - OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_ICE_SPINNER, MOVE_ICE_SHARD); } - } WHEN { - if (move == MOVE_ELECTRIC_TERRAIN) { - TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); } - TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); } - } else { - TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); } - } - } -} diff --git a/test/battle/move_effect/ice_spinner.c b/test/battle/move_effect/ice_spinner.c new file mode 100644 index 0000000000..44ce21eb4f --- /dev/null +++ b/test/battle/move_effect/ice_spinner.c @@ -0,0 +1,122 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_ICE_SPINNER) == EFFECT_ICE_SPINNER); +} + +SINGLE_BATTLE_TEST("Ice Spinner and Steel Roller remove a terrain from field") +{ + u32 j; + static const u16 terrainMoves[] = + { + MOVE_ELECTRIC_TERRAIN, + MOVE_PSYCHIC_TERRAIN, + MOVE_GRASSY_TERRAIN, + MOVE_MISTY_TERRAIN, + }; + + u16 terrainMove = MOVE_NONE; + u16 removeTerrainMove = MOVE_NONE; + + for (j = 0; j < ARRAY_COUNT(terrainMoves); j++) + { + PARAMETRIZE { removeTerrainMove = MOVE_STEEL_ROLLER; terrainMove = terrainMoves[j]; } + PARAMETRIZE { removeTerrainMove = MOVE_ICE_SPINNER; terrainMove = terrainMoves[j]; } + } + + GIVEN { + ASSUME(GetMoveEffect(MOVE_ELECTRIC_TERRAIN) == EFFECT_ELECTRIC_TERRAIN); + ASSUME(GetMoveEffect(MOVE_PSYCHIC_TERRAIN) == EFFECT_PSYCHIC_TERRAIN); + ASSUME(GetMoveEffect(MOVE_GRASSY_TERRAIN) == EFFECT_GRASSY_TERRAIN); + ASSUME(GetMoveEffect(MOVE_MISTY_TERRAIN) == EFFECT_MISTY_TERRAIN); + ASSUME(GetMoveEffect(MOVE_STEEL_ROLLER) == EFFECT_STEEL_ROLLER); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, terrainMove); MOVE(player, removeTerrainMove); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, terrainMove, opponent); + ANIMATION(ANIM_TYPE_MOVE, removeTerrainMove, player); + switch (terrainMove) + { + case MOVE_ELECTRIC_TERRAIN: + MESSAGE("The electricity disappeared from the battlefield."); + break; + case MOVE_PSYCHIC_TERRAIN: + MESSAGE("The weirdness disappeared from the battlefield!"); + break; + case MOVE_GRASSY_TERRAIN: + MESSAGE("The grass disappeared from the battlefield."); + break; + case MOVE_MISTY_TERRAIN: + MESSAGE("The mist disappeared from the battlefield."); + break; + } + } +} + +SINGLE_BATTLE_TEST("Ice Spinner fails to remove terrain if user faints during attack execution") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_ICE_SPINNER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, opponent); + NOT MESSAGE("The electricity disappeared from the battlefield."); + } +} + +SINGLE_BATTLE_TEST("Ice Spinner will not be remove Terrain if user is switched out due to Red Card") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_ICE_SPINNER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + NOT MESSAGE("The electricity disappeared from the battlefield."); + } +} + +SINGLE_BATTLE_TEST("Ice Spinner doesn't fail if there is no terrain on the field") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ICE_SPINNER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICE_SPINNER, player); + NOT MESSAGE("But it failed!"); + } +} + +AI_SINGLE_BATTLE_TEST("Ice Spinner can be chosen by AI regardless if there is a terrain or not") +{ + u32 move; + + PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; } + PARAMETRIZE { move = MOVE_NONE; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_ICE_SPINNER, MOVE_ICE_SHARD); } + } WHEN { + if (move == MOVE_ELECTRIC_TERRAIN) { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); } + TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); } + } else { + TURN { EXPECT_MOVE(opponent, MOVE_ICE_SPINNER); } + } + } +} diff --git a/test/battle/move_effect/steel_roller.c b/test/battle/move_effect/steel_roller.c new file mode 100644 index 0000000000..4b658a6124 --- /dev/null +++ b/test/battle/move_effect/steel_roller.c @@ -0,0 +1,75 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_STEEL_ROLLER) == EFFECT_STEEL_ROLLER); +} + +// Covered in ice_spinner.c +// SINGLE_BATTLE_TEST("Ice Spinner and Steel Roller remove a terrain from field") + +SINGLE_BATTLE_TEST("Steel Roller removes Terrain even if user faints during attack execution") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_LIFE_ORB); HP(1); } + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_STEEL_ROLLER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, opponent); + MESSAGE("The electricity disappeared from the battlefield."); + } +} + +SINGLE_BATTLE_TEST("Steel Roller removes Terrain if user is switched out due to Red Card") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_RED_CARD); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); MOVE(opponent, MOVE_STEEL_ROLLER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIC_TERRAIN, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, opponent); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("The electricity disappeared from the battlefield."); + } +} + +SINGLE_BATTLE_TEST("Steel Roller will fail if there is no Terrain") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_STEEL_ROLLER); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_STEEL_ROLLER, opponent); + MESSAGE("The opposing Wobbuffet used Steel Roller!"); + MESSAGE("But it failed!"); + } +} + +AI_SINGLE_BATTLE_TEST("Steel Roller wont be chosen by AI if there is no terrain on the field") +{ + u32 move; + + PARAMETRIZE { move = MOVE_ELECTRIC_TERRAIN; } + PARAMETRIZE { move = MOVE_NONE; } + + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_STEEL_ROLLER, MOVE_ICE_SHARD); } + } WHEN { + if (move == MOVE_ELECTRIC_TERRAIN) { + TURN { MOVE(player, MOVE_ELECTRIC_TERRAIN); EXPECT_MOVE(opponent, MOVE_ICE_SHARD); } + TURN { EXPECT_MOVE(opponent, MOVE_STEEL_ROLLER); } + } else { + TURN { EXPECT_MOVE(opponent, MOVE_ICE_SHARD); } + } + } +} From f8fc86275ccb8c259eecf8cb46e2bd2fb16c5ae0 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 1 Jul 2025 17:48:57 +0200 Subject: [PATCH 42/50] Fixes protective pads not protecting from secondary protect effects (#7229) --- include/battle_util.h | 3 +- src/battle_script_commands.c | 6 +-- src/battle_util.c | 90 +++++++++++++++---------------- test/battle/ability/fluffy.c | 42 +++++++++++++-- test/battle/move_effect/protect.c | 17 ++++++ 5 files changed, 104 insertions(+), 54 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 2ce91c3f25..57327176a8 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -263,7 +263,8 @@ enum ItemHoldEffect GetBattlerHoldEffect(u32 battler, bool32 checkNegating); enum ItemHoldEffect GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating); enum ItemHoldEffect GetBattlerHoldEffectInternal(u32 battler, bool32 checkNegating, bool32 checkAbility); u32 GetBattlerHoldEffectParam(u32 battler); -bool32 IsMoveMakingContact(u32 move, u32 battlerAtk); +bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move); +bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move); bool32 IsBattlerGrounded(u32 battler); u32 GetMoveSlot(u16 *moves, u32 move); u32 GetBattlerWeight(u32 battler); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a1d29bc696..386d636e77 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1422,7 +1422,7 @@ static void Cmd_attackcanceler(void) && effect != EFFECT_COUNTER && effect != EFFECT_UPPER_HAND) { - if (IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) + if (!CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)) gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; CancelMultiTurnMoves(gBattlerAttacker, SKY_DROP_ATTACKCANCELLER_CHECK); gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; @@ -1438,7 +1438,7 @@ static void Cmd_attackcanceler(void) gBattleCommunication[MISS_TYPE] = B_MSG_PROTECTED; gBattlescriptCurrInstr = cmd->nextInstr; } - else if (gProtectStructs[gBattlerTarget].beakBlastCharge && IsMoveMakingContact(gCurrentMove, gBattlerAttacker)) + else if (gProtectStructs[gBattlerTarget].beakBlastCharge && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove)) { gProtectStructs[gBattlerAttacker].touchedProtectLike = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; @@ -7262,7 +7262,7 @@ static void Cmd_moveend(void) if (IsBattlerAlive(gBattlerAttacker) && gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerAttacker)] & (1u << gBattlerPartyIndexes[gBattlerAttacker])) // But not knocked off - && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) // Pickpocket requires contact + && IsMoveMakingContact(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove) // Pickpocket requires contact && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) // Obviously attack needs to have worked { u8 battlers[4] = {0, 1, 2, 3}; diff --git a/src/battle_util.c b/src/battle_util.c index 226b041be0..e4d43d7766 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4465,8 +4465,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) && IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) && gDisableStructs[gBattlerAttacker].overwrittenAbility != GetBattlerAbility(gBattlerTarget) && gBattleMons[gBattlerAttacker].ability != ABILITY_MUMMY && gBattleMons[gBattlerAttacker].ability != ABILITY_LINGERING_AROMA @@ -4490,8 +4489,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_NO_EFFECT) && IsBattlerAlive(gBattlerAttacker) && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) && !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSwapped) { @@ -4547,8 +4545,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { SET_STATCHANGER(STAT_SPEED, 1, TRUE); PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); @@ -4564,8 +4561,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / (B_ROUGH_SKIN_DMG >= GEN_4 ? 8 : 16); if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) @@ -4580,8 +4576,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) && !IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { if ((battler = IsAbilityOnField(ABILITY_DAMP))) { @@ -4650,8 +4645,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && CanBeSlept(gBattlerAttacker, gBattlerTarget, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { if (IsSleepClauseEnabled()) gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; @@ -4674,8 +4668,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_POISON; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); @@ -4695,8 +4688,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && CanBeParalyzed(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_PARALYSIS; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); @@ -4711,8 +4703,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && (IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) && IsBattlerTurnDamaged(gBattlerTarget) && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3))) @@ -4735,8 +4726,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) && AreBattlersOfOppositeGender(gBattlerAttacker, gBattlerTarget) && GetBattlerAbility(gBattlerAttacker) != ABILITY_OBLIVIOUS - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) && !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL)) { gBattleMons[gBattlerAttacker].status2 |= STATUS2_INFATUATED_WITH(gBattlerTarget); @@ -4806,8 +4796,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && (IsMoveMakingContact(move, gBattlerAttacker)) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) && !(gStatuses3[gBattlerAttacker] & STATUS3_PERISH_SONG)) { if (!(gStatuses3[battler] & STATUS3_PERISH_SONG)) @@ -4932,8 +4921,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && CanBePoisoned(gBattlerAttacker, gBattlerTarget, gLastUsedAbility, GetBattlerAbility(gBattlerTarget)) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(move, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move) && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target && RandomPercentage(RNG_POISON_TOUCH, 30)) { @@ -7191,8 +7179,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_ROCKY_HELMET: if (IsBattlerTurnDamaged(gBattlerTarget) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove) && IsBattlerAlive(gBattlerAttacker) && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) { @@ -7324,8 +7311,7 @@ u32 ItemBattleEffects(enum ItemCaseId caseID, u32 battler, bool32 moveTurn) case HOLD_EFFECT_STICKY_BARB: if (IsBattlerTurnDamaged(gBattlerTarget) && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) - && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS - && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) + && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), gCurrentMove) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && IsBattlerAlive(gBattlerAttacker) && CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) @@ -7691,26 +7677,35 @@ u32 GetBattlerHoldEffectParam(u32 battler) return GetItemHoldEffectParam(gBattleMons[battler].item); } -bool32 IsMoveMakingContact(u32 move, u32 battlerAtk) +bool32 CanBattlerAvoidContactEffects(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move) { - enum ItemHoldEffect atkHoldEffect = GetBattlerHoldEffect(battlerAtk, TRUE); - - if (!MoveMakesContact(move)) + if (holdEffectAtk == HOLD_EFFECT_PROTECTIVE_PADS) { - if (GetMoveEffect(move) == EFFECT_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][gBattlerTarget] == DAMAGE_CATEGORY_PHYSICAL) - return TRUE; - else - return FALSE; + RecordItemEffectBattle(battlerAtk, HOLD_EFFECT_PROTECTIVE_PADS); + return TRUE; } - else if ((atkHoldEffect == HOLD_EFFECT_PUNCHING_GLOVE && IsPunchingMove(move)) - || GetBattlerAbility(battlerAtk) == ABILITY_LONG_REACH) + + return !IsMoveMakingContact(battlerAtk, battlerDef, abilityAtk, holdEffectAtk, move); +} + +bool32 IsMoveMakingContact(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, enum ItemHoldEffect holdEffectAtk, u32 move) +{ + if (!(MoveMakesContact(move) || (GetMoveEffect(move) == EFFECT_SHELL_SIDE_ARM + && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_PHYSICAL))) { return FALSE; } - else + else if (holdEffectAtk == HOLD_EFFECT_PUNCHING_GLOVE && IsPunchingMove(move)) { - return TRUE; + RecordItemEffectBattle(battlerAtk, HOLD_EFFECT_PUNCHING_GLOVE); + return FALSE; } + else if (abilityAtk == ABILITY_LONG_REACH) + { + RecordAbilityBattle(battlerAtk, ABILITY_LONG_REACH); + return FALSE; + } + return TRUE; } static inline bool32 IsSideProtected(u32 battler, enum ProtectMethod method) @@ -7729,7 +7724,8 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) { if (IsZMove(move) || IsMaxMove(move)) return FALSE; // Z-Moves and Max Moves bypass protection (except Max Guard). - if (IsMoveMakingContact(move, battlerAtk) && GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST) + if (GetBattlerAbility(battlerAtk) == ABILITY_UNSEEN_FIST + && IsMoveMakingContact(battlerAtk, battlerDef, ABILITY_UNSEEN_FIST, GetBattlerHoldEffect(battlerAtk, TRUE), move)) return FALSE; } @@ -8431,7 +8427,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_TOUGH_CLAWS: - if (IsMoveMakingContact(move, battlerAtk)) + if (IsMoveMakingContact(battlerAtk, battlerDef, atkAbility, holdEffectAtk, move)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); break; case ABILITY_STRONG_JAW: @@ -9242,7 +9238,7 @@ static inline uq4_12_t GetAttackerAbilitiesModifier(u32 battlerAtk, uq4_12_t typ return UQ_4_12(1.0); } -static inline uq4_12_t GetDefenderAbilitiesModifier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t typeEffectivenessModifier, u32 abilityDef) +static inline uq4_12_t GetDefenderAbilitiesModifier(u32 move, u32 moveType, u32 battlerAtk, u32 battlerDef, uq4_12_t typeEffectivenessModifier, u32 abilityDef, enum ItemHoldEffect holdEffectAtk) { switch (abilityDef) { @@ -9258,9 +9254,9 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(u32 move, u32 moveType, u32 return UQ_4_12(0.75); break; case ABILITY_FLUFFY: - if (!IsMoveMakingContact(move, battlerAtk) && moveType == TYPE_FIRE) + if (moveType == TYPE_FIRE && !IsMoveMakingContact(battlerAtk, battlerDef, ABILITY_NONE, holdEffectAtk, move)) return UQ_4_12(2.0); - if (IsMoveMakingContact(move, battlerAtk) && moveType != TYPE_FIRE) + if (moveType != TYPE_FIRE && IsMoveMakingContact(battlerAtk, battlerDef, ABILITY_NONE, holdEffectAtk, move)) return UQ_4_12(0.5); break; case ABILITY_PUNK_ROCK: @@ -9375,14 +9371,14 @@ static inline uq4_12_t GetOtherModifiers(struct DamageCalculationData *damageCal if (unmodifiedAttackerSpeed >= unmodifiedDefenderSpeed) { DAMAGE_MULTIPLY_MODIFIER(GetAttackerAbilitiesModifier(battlerAtk, typeEffectivenessModifier, isCrit, abilityAtk)); - DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier, abilityDef)); + DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier, abilityDef, holdEffectAtk)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderPartnerAbilitiesModifier(battlerDefPartner)); DAMAGE_MULTIPLY_MODIFIER(GetAttackerItemsModifier(battlerAtk, typeEffectivenessModifier, holdEffectAtk)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderItemsModifier(damageCalcData, typeEffectivenessModifier, abilityDef, holdEffectDef)); } else { - DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier, abilityDef)); + DAMAGE_MULTIPLY_MODIFIER(GetDefenderAbilitiesModifier(move, moveType, battlerAtk, battlerDef, typeEffectivenessModifier, abilityDef, holdEffectAtk)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderPartnerAbilitiesModifier(battlerDefPartner)); DAMAGE_MULTIPLY_MODIFIER(GetAttackerAbilitiesModifier(battlerAtk, typeEffectivenessModifier, isCrit, abilityAtk)); DAMAGE_MULTIPLY_MODIFIER(GetDefenderItemsModifier(damageCalcData, typeEffectivenessModifier, abilityDef, holdEffectDef)); diff --git a/test/battle/ability/fluffy.c b/test/battle/ability/fluffy.c index 4b8ef60396..6525c73212 100644 --- a/test/battle/ability/fluffy.c +++ b/test/battle/ability/fluffy.c @@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct conta } WHEN { TURN { MOVE(player, MOVE_SCRATCH); } } SCENE { - MESSAGE("Wobbuffet used Scratch!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage); @@ -39,7 +39,7 @@ SINGLE_BATTLE_TEST("Fluffy doubles damage taken from fire type moves", s16 damag } WHEN { TURN { MOVE(player, MOVE_EMBER); } } SCENE { - MESSAGE("Wobbuffet used Ember!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { EXPECT_MUL_EQ(results[0].damage, UQ_4_12(2.0), results[1].damage); @@ -57,7 +57,43 @@ SINGLE_BATTLE_TEST("Fluffy does not alter damage of fire-type moves that make di } WHEN { TURN { MOVE(player, MOVE_FIRE_PUNCH); } } SCENE { - MESSAGE("Wobbuffet used Fire Punch!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_FIRE_PUNCH, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Fluffy halves damage taken from moves that make direct contact even if protected by Protective Pads", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_KLUTZ; } + PARAMETRIZE { ability = ABILITY_FLUFFY; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PROTECTIVE_PADS); } + OPPONENT(SPECIES_STUFFUL) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, UQ_4_12(0.5), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Fluffy does not halve damage taken from moves that make direct contact but are ignored by Punching Glove", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_KLUTZ; } + PARAMETRIZE { ability = ABILITY_FLUFFY; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PUNCHING_GLOVE); } + OPPONENT(SPECIES_STUFFUL) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_THUNDER_PUNCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_PUNCH, player); HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { EXPECT_EQ(results[0].damage, results[1].damage); diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index e0c32e5267..09fc4c12bf 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -618,3 +618,20 @@ SINGLE_BATTLE_TEST("Protect: Quick Guard, Wide Guard and Crafty Shield don't red EXPECT_EQ(results[4].damage, results[5].damage); } } + +SINGLE_BATTLE_TEST("Protect: Protective Pads protects from secondary effects") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_PROTECTIVE_PADS); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_BURNING_BULWARK); MOVE(player, MOVE_SCRATCH); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BURNING_BULWARK, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent); + STATUS_ICON(player, STATUS1_BURN); + } + } +} From bdb09890306455561c96ac71d0b38bfbec437114 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 2 Jul 2025 10:57:56 +0200 Subject: [PATCH 43/50] Remove remove_terrain.log (#7268) Co-authored-by: Hedara --- remove_terrain.log | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 remove_terrain.log diff --git a/remove_terrain.log b/remove_terrain.log deleted file mode 100644 index e69de29bb2..0000000000 From 734a15478c499bcd5d2236ec5e92635a12867c1d Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Wed, 2 Jul 2025 17:25:03 +0200 Subject: [PATCH 44/50] Clean up for Moveend --- src/battle_script_commands.c | 388 +++++++++++++-------------- tools/compresSmol/compresSmol | Bin 0 -> 100384 bytes tools/compresSmol/compresSmolTilemap | Bin 0 -> 104416 bytes 3 files changed, 194 insertions(+), 194 deletions(-) create mode 100755 tools/compresSmol/compresSmol create mode 100755 tools/compresSmol/compresSmolTilemap diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 386d636e77..10c81993e8 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6568,6 +6568,24 @@ static void Cmd_moveend(void) effect = TRUE; gBattleScripting.moveendState++; break; + case MOVEEND_SYMBIOSIS: + for (i = 0; i < gBattlersCount; i++) + { + if ((gSpecialStatuses[i].berryReduced + || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) + && TryTriggerSymbiosis(i, BATTLE_PARTNER(i))) + { + BestowItem(BATTLE_PARTNER(i), i); + gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; + gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); + gBattlerAttacker = i; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; + effect = TRUE; + } + } + gBattleScripting.moveendState++; + break; case MOVEEND_FIRST_MOVE_BLOCK: if ((gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget)) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT @@ -6640,12 +6658,6 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_KINGSROCK: // King's rock - // These effects will occur at each hit in a multi-strike move - if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) - effect = TRUE; - gBattleScripting.moveendState++; - break; case MOVEEND_ATTACKER_INVISIBLE: // make attacker sprite invisible if (gStatuses3[gBattlerAttacker] & (STATUS3_SEMI_INVULNERABLE) && gHitMarker & (HITMARKER_NO_ANIMATIONS | HITMARKER_DISABLE_ANIMATION)) @@ -6683,6 +6695,12 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_KINGSROCK: // King's rock + // These effects will occur at each hit in a multi-strike move + if (ItemBattleEffects(ITEMEFFECT_KINGSROCK, 0, FALSE)) + effect = TRUE; + gBattleScripting.moveendState++; + break; case MOVEEND_SUBSTITUTE: for (i = 0; i < gBattlersCount; i++) { @@ -6819,6 +6837,37 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; + case MOVEEND_DEFROST: + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattlerAttacker != gBattlerTarget + && (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove)) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove; + effect = TRUE; + } + if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerTarget) + && gBattlerAttacker != gBattlerTarget + && MoveThawsUser(originallyUsedMove) + && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) + { + gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; + BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); + MarkBattlerForControllerExec(gBattlerTarget); + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove; + effect = TRUE; + } + gBattleScripting.moveendState++; + break; case MOVEEND_NEXT_TARGET: // For moves hitting two opposing Pokemon. { u16 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); @@ -6942,37 +6991,6 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; } - case MOVEEND_DEFROST: - if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattlerAttacker != gBattlerTarget - && (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove)) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - { - gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FREEZE; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_DefrostedViaFireMove; - effect = TRUE; - } - if (gBattleMons[gBattlerTarget].status1 & STATUS1_FROSTBITE - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerTarget) - && gBattlerAttacker != gBattlerTarget - && MoveThawsUser(originallyUsedMove) - && !(gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) - { - gBattleMons[gBattlerTarget].status1 &= ~STATUS1_FROSTBITE; - BtlController_EmitSetMonData(gBattlerTarget, B_COMM_TO_CONTROLLER, REQUEST_STATUS_BATTLE, 0, sizeof(gBattleMons[gBattlerTarget].status1), &gBattleMons[gBattlerTarget].status1); - MarkBattlerForControllerExec(gBattlerTarget); - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_FrostbiteHealedViaFireMove; - effect = TRUE; - } - gBattleScripting.moveendState++; - break; case MOVEEND_SECOND_MOVE_BLOCK: if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) { @@ -7083,6 +7101,57 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_RED_CARD: + { + u32 redCardBattlers = 0, i; + for (i = 0; i < gBattlersCount; i++) + { + if (i == gBattlerAttacker) + continue; + if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_RED_CARD) + redCardBattlers |= (1u << i); + } + if (redCardBattlers && IsBattlerAlive(gBattlerAttacker)) + { + // Since we check if battler was damaged, we don't need to check move result. + // In fact, doing so actually prevents multi-target moves from activating red card properly + u8 battlers[4] = {0, 1, 2, 3}; + SortBattlersBySpeed(battlers, FALSE); + for (i = 0; i < gBattlersCount; i++) + { + u32 battler = battlers[i]; + // Search for fastest hit pokemon with a red card + // Attacker is the one to be switched out, battler is one with red card + if (redCardBattlers & (1u << battler) + && IsBattlerAlive(battler) + && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) + && IsBattlerTurnDamaged(battler) + && CanBattlerSwitch(gBattlerAttacker) + && !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battler))) + { + effect = TRUE; + gLastUsedItem = gBattleMons[battler].item; + SaveBattlerTarget(battler); // save battler with red card + SaveBattlerAttacker(gBattlerAttacker); + gBattleScripting.battler = battler; + gEffectBattler = gBattlerAttacker; + BattleScriptPushCursor(); + if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE + || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG + || GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) + gBattlescriptCurrInstr = BattleScript_RedCardActivationNoSwitch; + else + gBattlescriptCurrInstr = BattleScript_RedCardActivates; + break; // Only fastest red card activates + } + } + } + } + if (effect) + gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + else + gBattleScripting.moveendState++; + break; case MOVEEND_EJECT_BUTTON: { // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. @@ -7130,6 +7199,61 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; + case MOVEEND_LIFEORB_SHELLBELL: + if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0, FALSE)) + effect = TRUE; + gBattleScripting.moveendState++; + break; + case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out + { + // Because sorting the battlers by speed takes lots of cycles, + // we check if EE can be activated and cound how many. + u32 numEmergencyExitBattlers = 0; + u32 emergencyExitBattlers = 0; + + for (i = 0; i < gBattlersCount; i++) + { + if (EmergencyExitCanBeTriggered(i)) + { + emergencyExitBattlers |= 1u << i; + numEmergencyExitBattlers++; + } + } + + if (numEmergencyExitBattlers == 0) + { + gBattleScripting.moveendState++; + break; + } + + u8 battlers[4] = {0, 1, 2, 3}; + if (numEmergencyExitBattlers > 1) + SortBattlersBySpeed(battlers, FALSE); + + for (i = 0; i < gBattlersCount; i++) + { + u32 battler = battlers[i]; + + if (!(emergencyExitBattlers & 1u << battler)) + continue; + + effect = TRUE; + gBattleScripting.battler = battler; + BattleScriptPushCursor(); + + if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || IsOnPlayerSide(battler)) + gBattlescriptCurrInstr = BattleScript_EmergencyExit; + else + gBattlescriptCurrInstr = BattleScript_EmergencyExitWild; + + break; // Only the fastest Emergency Exit / Wimp Out activates + } + } + if (effect) + gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + else + gBattleScripting.moveendState++; + break; case MOVEEND_EJECT_PACK: { // Because sorting the battlers by speed takes lots of cycles, it's better to just check if any of the battlers has the Eject items. @@ -7184,80 +7308,25 @@ static void Cmd_moveend(void) else gBattleScripting.moveendState++; break; - case MOVEEND_WHITE_HERB: - for (i = 0; i < gBattlersCount; i++) + case MOVEEND_HIT_ESCAPE: + if (moveEffect == EFFECT_HIT_ESCAPE + && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) + && IsBattlerTurnDamaged(gBattlerTarget) + && IsBattlerAlive(gBattlerAttacker) + && !NoAliveMonsForBattlerSide(gBattlerTarget)) { - if (!IsBattlerAlive(i)) - continue; - - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_WHITE_HERB - && RestoreWhiteHerbStats(i)) - { - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_WhiteHerbRet; - effect = TRUE; - break; - } + effect = TRUE; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_EffectHitEscape; } - if (!effect) - gBattleScripting.moveendState++; + gBattleScripting.moveendState++; break; - case MOVEEND_RED_CARD: - { - u32 redCardBattlers = 0, i; - for (i = 0; i < gBattlersCount; i++) - { - if (i == gBattlerAttacker) - continue; - if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_RED_CARD) - redCardBattlers |= (1u << i); - } - if (redCardBattlers && IsBattlerAlive(gBattlerAttacker)) - { - // Since we check if battler was damaged, we don't need to check move result. - // In fact, doing so actually prevents multi-target moves from activating red card properly - u8 battlers[4] = {0, 1, 2, 3}; - SortBattlersBySpeed(battlers, FALSE); - for (i = 0; i < gBattlersCount; i++) - { - u32 battler = battlers[i]; - // Search for fastest hit pokemon with a red card - // Attacker is the one to be switched out, battler is one with red card - if (redCardBattlers & (1u << battler) - && IsBattlerAlive(battler) - && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && IsBattlerTurnDamaged(battler) - && CanBattlerSwitch(gBattlerAttacker) - && !(moveEffect == EFFECT_HIT_SWITCH_TARGET && CanBattlerSwitch(battler))) - { - effect = TRUE; - gLastUsedItem = gBattleMons[battler].item; - SaveBattlerTarget(battler); // save battler with red card - SaveBattlerAttacker(gBattlerAttacker); - gBattleScripting.battler = battler; - gEffectBattler = gBattlerAttacker; - BattleScriptPushCursor(); - if (gBattleStruct->commanderActive[gBattlerAttacker] != SPECIES_NONE - || GetBattlerAbility(gBattlerAttacker) == ABILITY_GUARD_DOG - || GetActiveGimmick(gBattlerAttacker) == GIMMICK_DYNAMAX) - gBattlescriptCurrInstr = BattleScript_RedCardActivationNoSwitch; - else - gBattlescriptCurrInstr = BattleScript_RedCardActivates; - break; // Only fastest red card activates - } - } - } - } - if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; + case MOVEEND_OPPORTUNIST: + if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) + effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers else gBattleScripting.moveendState++; break; - case MOVEEND_LIFEORB_SHELLBELL: - if (ItemBattleEffects(ITEMEFFECT_LIFEORB_SHELLBELL, 0, FALSE)) - effect = TRUE; - gBattleScripting.moveendState++; - break; case MOVEEND_PICKPOCKET: if (IsBattlerAlive(gBattlerAttacker) && gBattleMons[gBattlerAttacker].item != ITEM_NONE // Attacker must be holding an item @@ -7294,75 +7363,6 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_EMERGENCY_EXIT: // Special case, because moves hitting multiple opponents stop after switching out - { - // Because sorting the battlers by speed takes lots of cycles, - // we check if EE can be activated and cound how many. - u32 numEmergencyExitBattlers = 0; - u32 emergencyExitBattlers = 0; - - for (i = 0; i < gBattlersCount; i++) - { - if (EmergencyExitCanBeTriggered(i)) - { - emergencyExitBattlers |= 1u << i; - numEmergencyExitBattlers++; - } - } - - if (numEmergencyExitBattlers == 0) - { - gBattleScripting.moveendState++; - break; - } - - u8 battlers[4] = {0, 1, 2, 3}; - if (numEmergencyExitBattlers > 1) - SortBattlersBySpeed(battlers, FALSE); - - for (i = 0; i < gBattlersCount; i++) - { - u32 battler = battlers[i]; - - if (!(emergencyExitBattlers & 1u << battler)) - continue; - - effect = TRUE; - gBattleScripting.battler = battler; - BattleScriptPushCursor(); - - if (gBattleTypeFlags & BATTLE_TYPE_TRAINER || IsOnPlayerSide(battler)) - gBattlescriptCurrInstr = BattleScript_EmergencyExit; - else - gBattlescriptCurrInstr = BattleScript_EmergencyExitWild; - - break; // Only the fastest Emergency Exit / Wimp Out activates - } - } - if (effect) - gBattleScripting.moveendState = MOVEEND_OPPORTUNIST; - else - gBattleScripting.moveendState++; - break; - case MOVEEND_HIT_ESCAPE: - if (moveEffect == EFFECT_HIT_ESCAPE - && !(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) - && IsBattlerTurnDamaged(gBattlerTarget) - && IsBattlerAlive(gBattlerAttacker) - && !NoAliveMonsForBattlerSide(gBattlerTarget)) - { - effect = TRUE; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_EffectHitEscape; - } - gBattleScripting.moveendState++; - break; - case MOVEEND_OPPORTUNIST: - if (AbilityBattleEffects(ABILITYEFFECT_OPPORTUNIST, 0, 0, 0, 0)) - effect = TRUE; // it loops through all battlers, so we increment after its done with all battlers - else - gBattleScripting.moveendState++; - break; case MOVEEND_REMOVE_TERRAIN: if (GetMoveEffect(gChosenMove) == EFFECT_STEEL_ROLLER // Steel Roller has to check the chosen move, Otherwise it would fail in certain cases && IsBattlerTurnDamaged(gBattlerTarget)) @@ -7381,20 +7381,31 @@ static void Cmd_moveend(void) } gBattleScripting.moveendState++; break; - case MOVEEND_SYMBIOSIS: + case MOVEEND_WHITE_HERB: for (i = 0; i < gBattlersCount; i++) { - if ((gSpecialStatuses[i].berryReduced - || (B_SYMBIOSIS_GEMS >= GEN_7 && gSpecialStatuses[i].gemBoost)) - && TryTriggerSymbiosis(i, BATTLE_PARTNER(i))) + if (!IsBattlerAlive(i)) + continue; + + if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_WHITE_HERB + && RestoreWhiteHerbStats(i)) { - BestowItem(BATTLE_PARTNER(i), i); - gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; - gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); - gBattlerAttacker = i; BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_SymbiosisActivates; + gBattlescriptCurrInstr = BattleScript_WhiteHerbRet; effect = TRUE; + break; + } + } + if (!effect) + gBattleScripting.moveendState++; + break; + case MOVEEND_CHANGED_ITEMS: + for (i = 0; i < gBattlersCount; i++) + { + if (gBattleStruct->changedItems[i] != ITEM_NONE) + { + gBattleMons[i].item = gBattleStruct->changedItems[i]; + gBattleStruct->changedItems[i] = ITEM_NONE; } } gBattleScripting.moveendState++; @@ -7408,17 +7419,6 @@ static void Cmd_moveend(void) gBattleStruct->sameMoveTurns[gBattlerAttacker]++; gBattleScripting.moveendState++; break; - case MOVEEND_CHANGED_ITEMS: - for (i = 0; i < gBattlersCount; i++) - { - if (gBattleStruct->changedItems[i] != ITEM_NONE) - { - gBattleMons[i].item = gBattleStruct->changedItems[i]; - gBattleStruct->changedItems[i] = ITEM_NONE; - } - } - gBattleScripting.moveendState++; - break; case MOVEEND_CLEAR_BITS: // Clear/Set bits for things like using a move for all targets and all hits. if (gSpecialStatuses[gBattlerAttacker].instructedChosenTarget) gBattleStruct->moveTarget[gBattlerAttacker] = gSpecialStatuses[gBattlerAttacker].instructedChosenTarget & 0x3; diff --git a/tools/compresSmol/compresSmol b/tools/compresSmol/compresSmol new file mode 100755 index 0000000000000000000000000000000000000000..c518f8381b4a471181752509730a92c1967e738b GIT binary patch literal 100384 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 U+!xtb{JXA`At%Q~i22n1KkGoT8vp Date: Wed, 2 Jul 2025 17:25:34 +0200 Subject: [PATCH 45/50] remove leftover --- tools/compresSmol/compresSmol | Bin 100384 -> 0 bytes tools/compresSmol/compresSmolTilemap | Bin 104416 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 tools/compresSmol/compresSmol delete mode 100755 tools/compresSmol/compresSmolTilemap diff --git a/tools/compresSmol/compresSmol b/tools/compresSmol/compresSmol deleted file mode 100755 index c518f8381b4a471181752509730a92c1967e738b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 100384 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 U+!xtb{JXA`At%Q~i22n1KkGoT8vp Date: Thu, 3 Jul 2025 13:19:18 -0400 Subject: [PATCH 46/50] Fix redirection abilities triggering on self (#7276) Co-authored-by: ghoulslash --- src/battle_util.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index e4d43d7766..8adee1946f 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -7469,7 +7469,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) else battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_LIGHTNING_ROD); - if (battlerAbilityOnField > 0) + if (battlerAbilityOnField > 0 && (battlerAbilityOnField - 1) != gBattlerAttacker) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); @@ -7483,7 +7483,7 @@ u32 GetBattleMoveTarget(u16 move, u8 setTarget) else battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_STORM_DRAIN); - if (battlerAbilityOnField > 0) + if (battlerAbilityOnField > 0 && (battlerAbilityOnField - 1) != gBattlerAttacker) { targetBattler = battlerAbilityOnField - 1; RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); From 31fc32ada8e511200e83252d2c8ac98b21514a07 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Thu, 3 Jul 2025 17:16:40 -0400 Subject: [PATCH 47/50] Prevent AI Recursion (#7279) Co-authored-by: ghoulslash --- src/battle_ai_main.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 18c140c2d2..1b8520fa5d 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2047,7 +2047,11 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_COPYCAT: case EFFECT_MIRROR_MOVE: - return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); + if (predictedMove && GetMoveEffect(predictedMove) != GetMoveEffect(move)) + return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); + else + ADJUST_SCORE(-10); + break; case EFFECT_FLOWER_SHIELD: if (!IS_BATTLER_OF_TYPE(battlerAtk, TYPE_GRASS) && !(isDoubleBattle && IS_BATTLER_OF_TYPE(BATTLE_PARTNER(battlerAtk), TYPE_GRASS))) @@ -2312,7 +2316,10 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_NATURE_POWER: - return AI_CheckBadMove(battlerAtk, battlerDef, GetNaturePowerMove(battlerAtk), score); + predictedMove = GetNaturePowerMove(battlerAtk); + if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) + return AI_CheckBadMove(battlerAtk, battlerDef, GetNaturePowerMove(battlerAtk), score); + break; case EFFECT_TAUNT: if (gDisableStructs[battlerDef].tauntTimer > 0 || DoesPartnerHaveSameMoveEffect(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove)) @@ -2492,7 +2499,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (AI_IsSlower(battlerAtk, battlerDef, move)) ADJUST_SCORE(-10); // Target is predicted to go first, Me First will fail - else + else if (GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckBadMove(battlerAtk, battlerDef, predictedMove, score); } else @@ -3852,7 +3859,7 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) ADJUST_SCORE(DECENT_EFFECT); break; case EFFECT_MIRROR_MOVE: - if (predictedMove != MOVE_NONE) + if (predictedMove && GetMoveEffect(predictedMove) != GetMoveEffect(move)) return AI_CheckViability(battlerAtk, battlerDef, predictedMove, score); break; case EFFECT_ATTACK_UP: @@ -4116,7 +4123,8 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) case EFFECT_MIMIC: if (AI_IsFaster(battlerAtk, battlerDef, move)) { - if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF) + if (gLastMoves[battlerDef] != MOVE_NONE && gLastMoves[battlerDef] != 0xFFFF + && (GetMoveEffect(gLastMoves[battlerDef]) != GetMoveEffect(move))) return AI_CheckViability(battlerAtk, battlerDef, gLastMoves[battlerDef], score); } break; From f74a23f44d1ccdf7f911608d6a9452dbd2bb8630 Mon Sep 17 00:00:00 2001 From: bassforte123 <130828119+bassforte123@users.noreply.github.com> Date: Fri, 4 Jul 2025 05:04:29 -0400 Subject: [PATCH 48/50] Typo fixes (#7280) --- test/battle/ability/liquid_ooze.c | 2 +- test/battle/status1/poison.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c index 0e5a0c6cf7..fa8ca8e3b2 100644 --- a/test/battle/ability/liquid_ooze.c +++ b/test/battle/ability/liquid_ooze.c @@ -138,7 +138,7 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes leech seed victim to faint before seeder" } } -SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+") +SINGLE_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+)") { s16 damage; GIVEN { diff --git a/test/battle/status1/poison.c b/test/battle/status1/poison.c index 0a749ea96d..97b8782590 100644 --- a/test/battle/status1/poison.c +++ b/test/battle/status1/poison.c @@ -27,7 +27,6 @@ SINGLE_BATTLE_TEST("Poison can't bad poison a poison or steel type") GIVEN { ASSUME(GetMoveEffect(MOVE_POISON_GAS) == EFFECT_NON_VOLATILE_STATUS); ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_GAS) == MOVE_EFFECT_POISON); - ASSUME(GetMoveNonVolatileStatus(MOVE_POISON_GAS) == MOVE_EFFECT_POISON); PLAYER(SPECIES_WOBBUFFET); OPPONENT(species); } WHEN { From beb576f4c5b9dcac3d8ff1e4eb9e7bfe20837162 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Fri, 4 Jul 2025 11:11:21 +0200 Subject: [PATCH 49/50] Set BP of Gyro Ball for attackers with 0 speed to 1 (#7270) Co-authored-by: Hedara --- src/battle_util.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 8adee1946f..4f0ffcf962 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8183,10 +8183,20 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData basePower = sSpeedDiffPowerTable[speed]; break; case EFFECT_GYRO_BALL: - basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / GetBattlerTotalSpeedStat(battlerAtk)) + 1; - if (basePower > 150) - basePower = 150; - break; + { + u32 attackerSpeed = GetBattlerTotalSpeedStat(battlerAtk); + if (attackerSpeed == 0) + { + basePower = 1; + } + else + { + basePower = ((25 * GetBattlerTotalSpeedStat(battlerDef)) / attackerSpeed) + 1; + if (basePower > 150) + basePower = 150; + } + break; + } case EFFECT_ECHOED_VOICE: // gBattleStruct->sameMoveTurns incremented in ppreduce if (gBattleStruct->sameMoveTurns[battlerAtk] != 0) From 5cfab59209b695c3eb3f0bc5f77adbd745b190f0 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 4 Jul 2025 18:11:32 +0200 Subject: [PATCH 50/50] Fix OOB in Cmd_selectfirstvalidtarget (#7269) --- src/battle_script_commands.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 10c81993e8..25edc5d759 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -14530,6 +14530,8 @@ static void Cmd_selectfirstvalidtarget(void) if (IsBattlerAlive(gBattlerTarget)) break; } + if (gBattlerTarget >= gBattlersCount) + gBattlerTarget = 0; gBattlescriptCurrInstr = cmd->nextInstr; }