From 3255f232397161d976b74f7fd353c615aa92d2c7 Mon Sep 17 00:00:00 2001 From: grintoul <166724814+grintoul1@users.noreply.github.com> Date: Sat, 31 May 2025 08:50:41 +0100 Subject: [PATCH 01/25] Added line break between Trainer 1 name and Trainer 2 name in sText_TwoTrainersWantToBattle (#7028) --- src/battle_message.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_message.c b/src/battle_message.c index d46ead7669..4f19a79c2a 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1470,7 +1470,7 @@ const u8 gText_Body[] = _("Body"); const u8 gText_Judgment[] = _("{B_BUFF1}{CLEAR 13}Judgment{CLEAR 13}{B_BUFF2}"); static const u8 sText_TwoTrainersSentPkmn[] = _("{B_TRAINER1_NAME_WITH_CLASS} sent out {B_OPPONENT_MON1_NAME}!\p{B_TRAINER2_NAME_WITH_CLASS} sent out {B_OPPONENT_MON2_NAME}!"); static const u8 sText_Trainer2SentOutPkmn[] = _("{B_TRAINER2_NAME_WITH_CLASS} sent out {B_BUFF1}!"); -static const u8 sText_TwoTrainersWantToBattle[] = _("You are challenged by {B_TRAINER1_NAME_WITH_CLASS} and {B_TRAINER2_NAME_WITH_CLASS}!\p"); +static const u8 sText_TwoTrainersWantToBattle[] = _("You are challenged by\n{B_TRAINER1_NAME_WITH_CLASS} and\l{B_TRAINER2_NAME_WITH_CLASS}!\p"); static const u8 sText_InGamePartnerSentOutZGoN[] = _("{B_PARTNER_NAME_WITH_CLASS} sent out {B_PLAYER_MON2_NAME}! Go, {B_PLAYER_MON1_NAME}!"); const u16 gBattlePalaceFlavorTextTable[] = From 585793131f47429c43f45aa7735c38c43a1d1a1a Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Sat, 31 May 2025 19:25:25 +0100 Subject: [PATCH 02/25] Fixes large battle messages being cut off instead of being prompted to advance 2 (#7036) --- src/battle_message.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_message.c b/src/battle_message.c index 4f19a79c2a..71ec2b305a 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1470,7 +1470,7 @@ const u8 gText_Body[] = _("Body"); const u8 gText_Judgment[] = _("{B_BUFF1}{CLEAR 13}Judgment{CLEAR 13}{B_BUFF2}"); static const u8 sText_TwoTrainersSentPkmn[] = _("{B_TRAINER1_NAME_WITH_CLASS} sent out {B_OPPONENT_MON1_NAME}!\p{B_TRAINER2_NAME_WITH_CLASS} sent out {B_OPPONENT_MON2_NAME}!"); static const u8 sText_Trainer2SentOutPkmn[] = _("{B_TRAINER2_NAME_WITH_CLASS} sent out {B_BUFF1}!"); -static const u8 sText_TwoTrainersWantToBattle[] = _("You are challenged by\n{B_TRAINER1_NAME_WITH_CLASS} and\l{B_TRAINER2_NAME_WITH_CLASS}!\p"); +static const u8 sText_TwoTrainersWantToBattle[] = _("You are challenged by\n{B_TRAINER1_NAME_WITH_CLASS} and {B_TRAINER2_NAME_WITH_CLASS}!\p"); static const u8 sText_InGamePartnerSentOutZGoN[] = _("{B_PARTNER_NAME_WITH_CLASS} sent out {B_PLAYER_MON2_NAME}! Go, {B_PLAYER_MON1_NAME}!"); const u16 gBattlePalaceFlavorTextTable[] = @@ -3169,7 +3169,7 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) dst[dstID] = *src; dstID++; - BreakStringAutomatic(dst, BATTLE_MSG_MAX_WIDTH, BATTLE_MSG_MAX_LINES, fontId, TRUE); + BreakStringAutomatic(dst, BATTLE_MSG_MAX_WIDTH, BATTLE_MSG_MAX_LINES, fontId, SHOW_SCROLL_PROMPT); return dstID; } From a93a17d490b93a43f9859e8d6c4f3ebe2e66b161 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 31 May 2025 14:28:24 -0400 Subject: [PATCH 03/25] Fixed text width for a lot of forms in HGSS Dex (#7035) --- src/pokedex_plus_hgss.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index 955c8f9b17..6541e9d3a7 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -6431,7 +6431,7 @@ u32 GetSpeciesNameWidthInChars(const u8 *speciesName) bool32 IsSpeciesAlcremie(u32 targetSpecies) { - return targetSpecies >= SPECIES_ALCREMIE_STRAWBERRY_VANILLA_CREAM && targetSpecies <= SPECIES_ALCREMIE_RIBBON_RAINBOW_SWIRL; + return GET_BASE_SPECIES_ID(targetSpecies) == SPECIES_ALCREMIE; } bool32 IsItemSweet(u32 item) @@ -6628,10 +6628,10 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept case IF_PID_UPPER_MODULO_10_EQ: case IF_PID_UPPER_MODULO_10_LT: arg = evolutions[i].params[j].arg1; - if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_GT + if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_GT && arg < 10 && arg >= 0) arg = 9 - arg; - else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_EQ + else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_UPPER_MODULO_10_EQ && arg < 10 && arg >= 0) arg = 1; ConvertIntToDecimalStringN(gStringVar2, arg * 10, STR_CONV_MODE_LEFT_ALIGN, 3); @@ -6741,10 +6741,10 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept case IF_PID_MODULO_100_EQ: case IF_PID_MODULO_100_LT: arg = evolutions[i].params[j].arg1; - if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_GT + if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_GT && arg < 100 && arg >= 0) arg = 99 - arg; - else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_EQ + else if ((enum EvolutionConditions)evolutions[i].params[j].condition == IF_PID_MODULO_100_EQ && arg < 100 && arg >= 0) arg = 1; ConvertIntToDecimalStringN(gStringVar2, arg, STR_CONV_MODE_LEFT_ALIGN, 3); @@ -6776,7 +6776,7 @@ static void PrintEvolutionTargetSpeciesAndMethod(u8 taskId, u16 species, u8 dept } if (isAlcremie) - fontId = FONT_NARROWER; + fontId = FONT_SMALL_NARROWER; else fontId = GetFontIdToFit(gStringVar4, FONT_SMALL, 0, maxScreenWidth); From 661a418960bda7e2da8f1d48cbc58d6727b8cc1b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 1 Jun 2025 13:08:37 +0200 Subject: [PATCH 04/25] Fixes multi battle party re-order (#7042) --- src/battle_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_main.c b/src/battle_main.c index 5bdf3fb8ec..d1bc8ed0c8 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4651,7 +4651,7 @@ static void HandleTurnActionSelectionState(void) for (i = 0; i < gBattlersCount; i++) { if (gChosenActionByBattler[i] == B_ACTION_SWITCH) - SwitchPartyOrderInGameMulti(i, gBattleStruct->monToSwitchIntoId[battler]); + SwitchPartyOrderInGameMulti(i, gBattleStruct->monToSwitchIntoId[i]); } } } From 46e09a9e46c1ea35588a2c2a37131470d0683deb Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 1 Jun 2025 21:02:52 +0200 Subject: [PATCH 05/25] Changed trainer tutorial to take into account removed palette compression (#7044) Co-authored-by: Hedara --- docs/tutorials/how_to_trainer_pic.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/how_to_trainer_pic.md b/docs/tutorials/how_to_trainer_pic.md index 78f8a717e4..beddb641e4 100644 --- a/docs/tutorials/how_to_trainer_pic.md +++ b/docs/tutorials/how_to_trainer_pic.md @@ -31,13 +31,13 @@ Export the palette and place into the same folder. Sadly, just putting the image files into the graphics folder is not enough. To use the sprites we have to register them by linking the graphic files. [src/data/graphics/trainers](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/src/data/graphics/trainers.h): ```diff -const u32 gTrainerPalette_RubySapphireBrendan[] = INCBIN_U32("graphics/trainers/palettes/ruby_sapphire_brendan.gbapal.lz"); +const u16 gTrainerPalette_RubySapphireBrendan[] = INCBIN_U16("graphics/trainers/palettes/ruby_sapphire_brendan.gbapal"); const u32 gTrainerFrontPic_RubySapphireMay[] = INCBIN_U32("graphics/trainers/front_pics/ruby_sapphire.4bpp.lz"); -const u32 gTrainerPalette_RubySapphireMay[] = INCBIN_U32("graphics/trainers/palettes/ruby_sapphire_may.gbapal.lz"); +const u16 gTrainerPalette_RubySapphireMay[] = INCBIN_U16("graphics/trainers/palettes/ruby_sapphire_may.gbapal"); + const u32 gTrainerFrontPic_myTrainerClass[] = INCBIN_U32("graphics/trainers/front_pics/myTrainerClass.4bpp.lz"); -+ const u32 gTrainerPalette_myTrainerClass[] = INCBIN_U32("graphics/trainers/palettes/myTrainerClass.gbapal.lz"); ++ const u16 gTrainerPalette_myTrainerClass[] = INCBIN_U16("graphics/trainers/palettes/myTrainerClass.gbapal"); const u8 gTrainerBackPic_Brendan[] = INCBIN_U8("graphics/trainers/back_pics/brendan.4bpp"); ``` From d33651bfd0e16bbeb8084dfa8cd84178386c5f9b Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 2 Jun 2025 14:22:11 +0200 Subject: [PATCH 06/25] Battle controller pret documentation (#7029) --- include/battle_controllers.h | 70 +++++++++++++++-------- src/battle_controller_link_opponent.c | 4 +- src/battle_controller_link_partner.c | 4 +- src/battle_controller_opponent.c | 4 +- src/battle_controller_player.c | 4 +- src/battle_controller_player_partner.c | 4 +- src/battle_controller_recorded_opponent.c | 4 +- src/battle_controller_recorded_player.c | 4 +- src/battle_controller_safari.c | 4 +- src/battle_controller_wally.c | 4 +- src/battle_controllers.c | 4 +- src/battle_main.c | 18 +++--- src/battle_util.c | 16 +++--- 13 files changed, 81 insertions(+), 63 deletions(-) diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 8f2d78ed41..2ce28ca609 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -72,41 +72,63 @@ enum { // (e.g. MarkBattlerForControllerExec) instead of using these macros // directly. -#define MARK_BATTLE_CONTROLLER_ACTIVE_ON_LOCAL(battler) \ - gBattleControllerExecFlags |= (1u << battler) +static inline void MarkBattleControllerActiveOnLocal(u32 battler) +{ + gBattleControllerExecFlags |= (1u << battler); +} -#define MARK_BATTLE_CONTROLLER_IDLE_ON_LOCAL(battler) \ - gBattleControllerExecFlags &= ~(1u << battler) +static inline void MarkBattleControllerIdleOnLocal(u32 battler) +{ + gBattleControllerExecFlags &= ~(1u << battler); +} -#define IS_BATTLE_CONTROLLER_ACTIVE_ON_LOCAL(battler) \ - (gBattleControllerExecFlags & (1u << battler)) +static inline bool32 IsBattleControllerActiveOnLocal(u32 battler) +{ + return gBattleControllerExecFlags & (1u << battler); +} -#define MARK_BATTLE_CONTROLLER_MESSAGE_OUTBOUND_OVER_LINK(battler) \ - gBattleControllerExecFlags |= ((1u << battler) << (32 - MAX_BATTLERS_COUNT)) +static inline void MarkBattleControllerMessageOutboundOverLink(u32 battler) +{ + gBattleControllerExecFlags |= ((1u << battler) << (32 - MAX_BATTLERS_COUNT)); +} -#define MARK_BATTLE_CONTROLLER_MESSAGE_SYNCHRONIZED_OVER_LINK(battler) \ - gBattleControllerExecFlags &= ~((1 << 28) << (battler)) +static inline void MarkBattleControllerMessageSynchronizedOverLink(u32 battler) +{ + gBattleControllerExecFlags &= ~((1 << 28) << (battler)); +} -#define MARK_BATTLE_CONTROLLER_ACTIVE_FOR_PLAYER(battler, playerId) \ - gBattleControllerExecFlags |= ((1u << battler) << ((playerId) << 2)) +static inline bool32 IsBattleControllerMessageSynchronizedOverLink(u32 battler) +{ + return gBattleControllerExecFlags & (1u << (battler + 28)); +} -#define MARK_BATTLE_CONTROLLER_IDLE_FOR_PLAYER(battler, playerId) \ - gBattleControllerExecFlags &= ~((1u << battler) << ((playerId) * 4)) +static inline void MarkBattleControllerActiveForPlayer(u32 battler, u32 playerId) +{ + gBattleControllerExecFlags |= ((1u << battler) << ((playerId) << 2)); +} -#define IS_BATTLE_CONTROLLER_ACTIVE_FOR_PLAYER(battler, playerId) \ - (gBattleControllerExecFlags & ((1u << battler) << ((playerId) * 4))) +static inline void MarkBattleControllerIdleForPlayer(u32 battler, u32 playerId) +{ + gBattleControllerExecFlags &= ~((1u << battler) << ((playerId) * 4)); +} + +static inline bool32 IsBattleControllerActiveForPlayer(u32 battler, u32 playerId) +{ + return gBattleControllerExecFlags & ((1u << battler) << ((playerId) * 4)); +} // This actually checks if a specific controller is active on any player or if // *any* controller is pending sync over link communications, but the macro name // can only be so specific before it just gets ridiculous. -#define IS_BATTLE_CONTROLLER_ACTIVE_OR_PENDING_SYNC_ANYWHERE(battler) \ - (gBattleControllerExecFlags & ( \ - (1u << battler) \ - | (0xF << 28) \ - | (1u << battler << 4) \ - | (1u << battler << 8) \ - | (1u << battler << 12) \ - )) +static inline bool32 IsBattleControllerActiveOrPendingSyncAnywhere(u32 battler) +{ + return gBattleControllerExecFlags & ( + (1u << battler) + | (0xF << 28) + | (1u << battler << 4) + | (1u << battler << 8) + | (1u << battler << 12)); +} // Special arguments for Battle Controller functions. diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index c79588695d..a039a5b522 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -114,7 +114,7 @@ void SetControllerToLinkOpponent(u32 battler) static void LinkOpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkOpponentBufferCommands)) sLinkOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -320,7 +320,7 @@ static void LinkOpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index f54ee0d220..9b27309bf6 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -113,7 +113,7 @@ void SetControllerToLinkPartner(u32 battler) static void LinkPartnerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sLinkPartnerBufferCommands)) sLinkPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -164,7 +164,7 @@ static void LinkPartnerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 03c78fb9e9..f6fae5ae57 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -127,7 +127,7 @@ void SetControllerToOpponent(u32 battler) static void OpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sOpponentBufferCommands)) sOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -364,7 +364,7 @@ static void OpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index f374345206..f437d8ee13 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -182,13 +182,13 @@ static void PlayerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } static void PlayerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerBufferCommands)) sPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler); diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index ad5aa15312..9929f421cc 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -117,7 +117,7 @@ void SetControllerToPlayerPartner(u32 battler) static void PlayerPartnerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sPlayerPartnerBufferCommands)) sPlayerPartnerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -236,7 +236,7 @@ static void PlayerPartnerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index 1e471044d5..944cf6e072 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -120,7 +120,7 @@ void SetControllerToRecordedOpponent(u32 battler) static void RecordedOpponentBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedOpponentBufferCommands)) sRecordedOpponentBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -141,7 +141,7 @@ static void RecordedOpponentBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 2476929282..a3032db1a8 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -117,7 +117,7 @@ void SetControllerToRecordedPlayer(u32 battler) static void RecordedPlayerBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sRecordedPlayerBufferCommands)) sRecordedPlayerBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -313,7 +313,7 @@ static void RecordedPlayerBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 560a95cc5f..4a1fc3888c 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -109,7 +109,7 @@ void SetControllerToSafari(u32 battler) static void SafariBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sSafariBufferCommands)) sSafariBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -237,7 +237,7 @@ static void SafariBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index 3381e5a5bd..6cba0fc3e7 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -125,7 +125,7 @@ void SetControllerToWally(u32 battler) static void WallyBufferRunCommand(u32 battler) { - if (gBattleControllerExecFlags & (1u << battler)) + if (IsBattleControllerActiveOnLocal(battler)) { if (gBattleResources->bufferA[battler][0] < ARRAY_COUNT(sWallyBufferCommands)) sWallyBufferCommands[gBattleResources->bufferA[battler][0]](battler); @@ -284,7 +284,7 @@ static void WallyBufferExecCompleted(u32 battler) } else { - gBattleControllerExecFlags &= ~(1u << battler); + MarkBattleControllerIdleOnLocal(battler); } } diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 9b6a74fc6e..4faec49613 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -956,7 +956,7 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) switch (BYTE_TO_RECEIVE(0)) { case B_COMM_TO_CONTROLLER: - if (IS_BATTLE_CONTROLLER_ACTIVE_ON_LOCAL(battler)) + if (IsBattleControllerActiveOnLocal(battler)) return; memcpy(gBattleResources->bufferA[battler], &BYTE_TO_RECEIVE(LINK_BUFF_DATA), blockSize); @@ -975,7 +975,7 @@ static void Task_HandleCopyReceivedLinkBuffersData(u8 taskId) break; case B_COMM_CONTROLLER_IS_DONE: playerId = BYTE_TO_RECEIVE(LINK_BUFF_DATA); - MARK_BATTLE_CONTROLLER_IDLE_FOR_PLAYER(battler, playerId); + MarkBattleControllerIdleForPlayer(battler, playerId); break; } diff --git a/src/battle_main.c b/src/battle_main.c index d1bc8ed0c8..8ea21a023d 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4210,7 +4210,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CHOSEN: // Try to perform an action. - if (!(gBattleControllerExecFlags & (((1u << battler)) | (0xF << 28) | ((1u << battler) << 4) | ((1u << battler) << 8) | ((1u << battler) << 12)))) + if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler)) { RecordedBattle_SetBattlerAction(battler, gBattleResources->bufferB[battler][1]); gChosenActionByBattler[battler] = gBattleResources->bufferB[battler][1]; @@ -4414,7 +4414,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CASE_CHOSEN: - if (!(gBattleControllerExecFlags & (((1u << battler)) | (0xF << 28) | ((1u << battler) << 4) | ((1u << battler) << 8) | ((1u << battler) << 12)))) + if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler)) { switch (gChosenActionByBattler[battler]) { @@ -4544,11 +4544,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CONFIRMED_STANDBY: - if (!(gBattleControllerExecFlags & ((1u << battler) - | (0xF << 28) - | (1u << (battler + 4)) - | (1u << (battler + 8)) - | (1u << (battler + 12))))) + if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler)) { if (AllAtActionConfirmed()) i = TRUE; @@ -4570,7 +4566,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_ACTION_CONFIRMED: - if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) + if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler)) { gBattleCommunication[ACTIONS_CONFIRMED_COUNT]++; } @@ -4584,7 +4580,7 @@ static void HandleTurnActionSelectionState(void) { gBattlerAttacker = battler; gBattlescriptCurrInstr = gSelectionBattleScripts[battler]; - if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) + if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler)) { gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); } @@ -4592,7 +4588,7 @@ static void HandleTurnActionSelectionState(void) } break; case STATE_WAIT_SET_BEFORE_ACTION: - if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) + if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler)) { gBattleCommunication[battler] = STATE_BEFORE_ACTION_CHOSEN; } @@ -4616,7 +4612,7 @@ static void HandleTurnActionSelectionState(void) { gBattlerAttacker = battler; gBattlescriptCurrInstr = gSelectionBattleScripts[battler]; - if (!(gBattleControllerExecFlags & ((1u << battler) | (0xF << 28) | (1u << (battler + 4)) | (1u << (battler + 8)) | (1u << (battler + 12))))) + if (!IsBattleControllerActiveOrPendingSyncAnywhere(battler)) { gBattleScriptingCommandsTable[gBattlescriptCurrInstr[0]](); } diff --git a/src/battle_util.c b/src/battle_util.c index 6d256dc998..3bf809d530 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -988,29 +988,29 @@ static void UNUSED MarkAllBattlersForControllerExec(void) if (gBattleTypeFlags & BATTLE_TYPE_LINK) { for (i = 0; i < gBattlersCount; i++) - gBattleControllerExecFlags |= 1u << (i + 32 - MAX_BATTLERS_COUNT); + MarkBattleControllerMessageOutboundOverLink(i); } else { for (i = 0; i < gBattlersCount; i++) - gBattleControllerExecFlags |= 1u << i; + MarkBattleControllerActiveOnLocal(i); } } bool32 IsBattlerMarkedForControllerExec(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) - return (gBattleControllerExecFlags & (1u << (battler + 28))) != 0; + return IsBattleControllerMessageSynchronizedOverLink(battler); else - return (gBattleControllerExecFlags & (1u << battler)) != 0; + return IsBattleControllerActiveOnLocal(battler); } void MarkBattlerForControllerExec(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) - gBattleControllerExecFlags |= 1u << (battler + 32 - MAX_BATTLERS_COUNT); + MarkBattleControllerMessageOutboundOverLink(battler); else - gBattleControllerExecFlags |= 1u << battler; + MarkBattleControllerActiveOnLocal(battler); } void MarkBattlerReceivedLinkData(u32 battler) @@ -1018,9 +1018,9 @@ void MarkBattlerReceivedLinkData(u32 battler) s32 i; for (i = 0; i < GetLinkPlayerCount(); i++) - gBattleControllerExecFlags |= 1u << (battler + (i << 2)); + MarkBattleControllerActiveForPlayer(battler, i); - gBattleControllerExecFlags &= ~(1u << (28 + battler)); + MarkBattleControllerMessageSynchronizedOverLink(battler); } const u8 *CheckSkyDropState(u32 battler, enum SkyDropState skyDropState) From 7263bb188600411d20bc8fca1e5c3aa1315fc69c Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Mon, 2 Jun 2025 06:41:05 -0700 Subject: [PATCH 07/25] Update CI to ignore allcontributors commits (#7046) --- .all-contributorsrc | 3 +-- .github/workflows/build.yml | 9 +++++++++ .github/workflows/labels.yml | 9 +++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index e5ecce9602..540d534f0b 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -259,6 +259,5 @@ ], "contributorsPerLine": 7, "linkToUsage": true, - "commitType": "docs", - "skipCi": true + "commitType": "docs" } diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c3040f55c7..3304101d4f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,6 +9,7 @@ on: jobs: build: + if: github.actor != 'allcontributors' runs-on: ubuntu-latest env: GAME_VERSION: EMERALD @@ -36,3 +37,11 @@ jobs: TEST: 1 run: | make -j${nproc} check + allcontributors: + if: github.actor == 'allcontributors' + runs-on: ubuntu-latest + needs: [] + steps: + - name: Automatically pass for allcontributors + run: echo "CI automatically passes for allcontributors" && exit 0 + diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 85800211ef..7315082cb6 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -6,6 +6,7 @@ on: jobs: label: + if: github.actor != 'allcontributors' runs-on: ubuntu-latest steps: - name: check labels @@ -27,3 +28,11 @@ jobs: category: pokemon category: sprite-issue type: documentation + allcontributors: + if: github.actor == 'allcontributors' + runs-on: ubuntu-latest + needs: [] + steps: + - name: Automatically pass for allcontributors + run: echo "CI automatically passes for allcontributors" && exit 0 + From 8b52e100b9e733ae3c01f973c16e5497013091a7 Mon Sep 17 00:00:00 2001 From: TLM-PsIQ <87483364+TLM-PsIQ@users.noreply.github.com> Date: Tue, 3 Jun 2025 22:25:29 +0200 Subject: [PATCH 08/25] Fix ScaryFace anim for Bitter Malice (#6476) --- src/battle_anim_effects_2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_anim_effects_2.c b/src/battle_anim_effects_2.c index e0583c7cf8..10080dc84b 100755 --- a/src/battle_anim_effects_2.c +++ b/src/battle_anim_effects_2.c @@ -3395,7 +3395,7 @@ void AnimTask_ScaryFace(u8 taskId) bool32 onPlayer; if (gAnimMoveIndex == MOVE_BITTER_MALICE) - onPlayer = IsOnPlayerSide(gBattleAnimAttacker); + onPlayer = !IsOnPlayerSide(gBattleAnimAttacker); else onPlayer = !IsOnPlayerSide(gBattleAnimTarget); From 48b88899d14035ad8b37ee41ee79d5122760ca19 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Tue, 3 Jun 2025 23:12:38 +0200 Subject: [PATCH 09/25] add bassforte123 as a contributor for code (#7003) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 11 ++++++++++- CREDITS.md | 11 ++++++----- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index 540d534f0b..e1db3fe48d 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -223,7 +223,7 @@ "name": "Ruby", "avatar_url": "https://avatars.githubusercontent.com/u/178652077?v=4", "profile": "https://github.com/RubyRaven6", - "contributions": [ + "contributions": [ "code", "doc" ] @@ -255,6 +255,15 @@ "contributions": [ "code" ] + }, + { + "login": "bassforte123", + "name": "bassforte123", + "avatar_url": "https://avatars.githubusercontent.com/u/130828119?v=4", + "profile": "https://github.com/bassforte123", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 6045f2301a..d928bad0a6 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -31,23 +31,24 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Philipp AUER
Philipp AUER

🚧 πŸ’» tertu
tertu

🚧 πŸ’» psf
psf

🚧 πŸ’» + wiz1989
wiz1989

πŸ’» PCG
PCG

πŸ’» kittenchilly
kittenchilly

πŸ’» πŸ”¬ πŸ”£ - ExpoSeed
ExpoSeed

πŸ’» 🚧 πŸ‘€ + ExpoSeed
ExpoSeed

πŸ’» 🚧 πŸ‘€ Linathan
Linathan

πŸ’» Eduardo Quezada
Eduardo Quezada

πŸ’» πŸ”£ πŸ“– πŸš‡ 🚧 πŸ“† πŸ“£ πŸ”¬ πŸ‘€ ⚠️ βœ… πŸ““ khbsd
khbsd

πŸ“– πŸ’» Cafe
Cafe

🎨 agsmgmaster64
agsmgmaster64

πŸ’» - mudskipper13
mudskipper13

πŸ’» πŸ“– - Ruby
Ruby

πŸ’» πŸ“– + Ruby
Ruby

πŸ’» πŸ“– - surskitty
surskitty

πŸ’» - wiz1989
wiz1989

πŸ’» + mudskipper13
mudskipper13

πŸ’» πŸ“– + surskitty
surskitty

πŸ’» grintoul
grintoul

πŸ’» + bassforte123
bassforte123

πŸ’» From 2358f9a871f123b9ac9344b98f5c06a5765028ee Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 4 Jun 2025 07:50:34 +0200 Subject: [PATCH 10/25] add iriv24 as a contributor for code (#7059) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ CREDITS.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index e1db3fe48d..72bf225826 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -264,6 +264,15 @@ "contributions": [ "code" ] + }, + { + "login": "iriv24", + "name": "iriv24", + "avatar_url": "https://avatars.githubusercontent.com/u/40581123?v=4", + "profile": "https://github.com/iriv24", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index d928bad0a6..c93c1bcfd4 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -49,6 +49,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d surskitty
surskitty

πŸ’» grintoul
grintoul

πŸ’» bassforte123
bassforte123

πŸ’» + iriv24
iriv24

πŸ’» From b3752e13d8629d05642ae771a367db664f189455 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Wed, 4 Jun 2025 20:58:10 +0100 Subject: [PATCH 11/25] Fixes Aura Wheel + Normalize and Hunger Switch while Transformed/Terastallized (#7061) --- src/battle_main.c | 4 ++- src/battle_message.c | 2 +- src/battle_util.c | 4 ++- test/battle/ability/hunger_switch.c | 49 ++++++++++++++++++++++++++++ test/battle/move_effect/aura_wheel.c | 39 +++++++++++++++++++++- 5 files changed, 94 insertions(+), 4 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 8ea21a023d..bb03b5dfde 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5998,7 +5998,9 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState { return TYPE_WATER; } - else if (moveEffect == EFFECT_AURA_WHEEL && species == SPECIES_MORPEKO_HANGRY) + else if (moveEffect == EFFECT_AURA_WHEEL + && species == SPECIES_MORPEKO_HANGRY + && ability != ABILITY_NORMALIZE) { return TYPE_DARK; } diff --git a/src/battle_message.c b/src/battle_message.c index 71ec2b305a..78708d47d6 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1470,7 +1470,7 @@ const u8 gText_Body[] = _("Body"); const u8 gText_Judgment[] = _("{B_BUFF1}{CLEAR 13}Judgment{CLEAR 13}{B_BUFF2}"); static const u8 sText_TwoTrainersSentPkmn[] = _("{B_TRAINER1_NAME_WITH_CLASS} sent out {B_OPPONENT_MON1_NAME}!\p{B_TRAINER2_NAME_WITH_CLASS} sent out {B_OPPONENT_MON2_NAME}!"); static const u8 sText_Trainer2SentOutPkmn[] = _("{B_TRAINER2_NAME_WITH_CLASS} sent out {B_BUFF1}!"); -static const u8 sText_TwoTrainersWantToBattle[] = _("You are challenged by\n{B_TRAINER1_NAME_WITH_CLASS} and {B_TRAINER2_NAME_WITH_CLASS}!\p"); +static const u8 sText_TwoTrainersWantToBattle[] = _("You are challenged by {B_TRAINER1_NAME_WITH_CLASS} and {B_TRAINER2_NAME_WITH_CLASS}!\p"); static const u8 sText_InGamePartnerSentOutZGoN[] = _("{B_PARTNER_NAME_WITH_CLASS} sent out {B_PLAYER_MON2_NAME}! Go, {B_PLAYER_MON1_NAME}!"); const u16 gBattlePalaceFlavorTextTable[] = diff --git a/src/battle_util.c b/src/battle_util.c index 3bf809d530..9e7405bb48 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4320,7 +4320,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_HUNGER_SWITCH: - if (TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) + if (!(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + && GetActiveGimmick(battler) != GIMMICK_TERA + && TryBattleFormChange(battler, FORM_CHANGE_BATTLE_TURN_END)) { gBattlerAttacker = battler; BattleScriptPushCursorAndCallback(BattleScript_AttackerFormChangeEnd3NoPopup); diff --git a/test/battle/ability/hunger_switch.c b/test/battle/ability/hunger_switch.c index 38c3d2527d..1892de4424 100644 --- a/test/battle/ability/hunger_switch.c +++ b/test/battle/ability/hunger_switch.c @@ -22,3 +22,52 @@ SINGLE_BATTLE_TEST("Hunger Switch switches Morpeko's forms at the end of the tur EXPECT_EQ(player->species, SPECIES_MORPEKO_FULL_BELLY); } } + +SINGLE_BATTLE_TEST("Hunger Switch does not switch a mon transformed into Morpeko's form") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_TRANSFORM) == EFFECT_TRANSFORM); + PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TRANSFORM); } + } SCENE { + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, opponent); + } +} + +SINGLE_BATTLE_TEST("Hunger Switch does not switch Morpeko's form when Terastallized") +{ + GIVEN { + PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); TeraType(TYPE_NORMAL); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { } + TURN { MOVE(player, MOVE_SCRATCH, gimmick: GIMMICK_TERA); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } +} + +SINGLE_BATTLE_TEST("Hunger Switch does not switch Morpeko's form after switching out while Terastallized") +{ + KNOWN_FAILING; // #7062 + GIVEN { + ASSUME(GetMoveEffect(MOVE_ROAR) == EFFECT_ROAR); + PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); TeraType(TYPE_NORMAL); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { } + TURN { MOVE(player, MOVE_SCRATCH, gimmick: GIMMICK_TERA); MOVE(opponent, MOVE_ROAR); } + TURN { SWITCH(player, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + EXPECT_EQ(player->species, SPECIES_MORPEKO_HANGRY); + } +} diff --git a/test/battle/move_effect/aura_wheel.c b/test/battle/move_effect/aura_wheel.c index dfd31c878f..18602b8bc9 100644 --- a/test/battle/move_effect/aura_wheel.c +++ b/test/battle/move_effect/aura_wheel.c @@ -50,4 +50,41 @@ SINGLE_BATTLE_TEST("Aura Wheel changes type depending on Morpeko's form") } } -TO_DO_BATTLE_TEST("Aura Wheel can be used by PokΓ©mon transformed into Morpeko"); +SINGLE_BATTLE_TEST("Aura Wheel can be used by PokΓ©mon transformed into Morpeko") +{ + KNOWN_FAILING; // Aura Wheel for some reason isn't used by the opponent? + GIVEN { + PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); } + OPPONENT(SPECIES_DITTO) { Ability(ABILITY_IMPOSTER); } + } WHEN { + TURN { MOVE(opponent, MOVE_AURA_WHEEL); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, opponent); + } +} + +SINGLE_BATTLE_TEST("Aura Wheel can be turned into a Normal-type move after Morpeko gains Normalize") +{ + bool32 hangryMode; + PARAMETRIZE { hangryMode = FALSE; } + PARAMETRIZE { hangryMode = TRUE; } + GIVEN { + ASSUME(GetMoveEffect(MOVE_ENTRAINMENT) == EFFECT_ENTRAINMENT); + ASSUME(gSpeciesInfo[SPECIES_DUSKULL].types[0] == TYPE_GHOST || gSpeciesInfo[SPECIES_DUSKULL].types[1] == TYPE_GHOST); + PLAYER(SPECIES_MORPEKO) { Ability(ABILITY_HUNGER_SWITCH); } + OPPONENT(SPECIES_DELCATTY) { Ability(ABILITY_NORMALIZE); } + OPPONENT(SPECIES_DUSKULL); + } WHEN { + if (hangryMode) + TURN { } + TURN { MOVE(opponent, MOVE_ENTRAINMENT); } + TURN { MOVE(player, MOVE_AURA_WHEEL); SWITCH(opponent, 1); } + } SCENE { + if (hangryMode) + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_AURA_WHEEL, player); + HP_BAR(opponent); + } + } +} From 99997c49fcd39510b7bd82c42b0eb01afeb909bf Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 4 Jun 2025 23:26:19 +0200 Subject: [PATCH 12/25] Fixes speed calculation order (#7064) --- src/battle_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index bb03b5dfde..662cf39791 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4699,6 +4699,10 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h { u32 speed = gBattleMons[battler].speed; + // stat stages + speed *= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][0]; + speed /= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][1]; + // weather abilities if (HasWeatherEffect()) { @@ -4726,10 +4730,6 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, enum ItemHoldEffect h else if (ability == ABILITY_UNBURDEN && gDisableStructs[battler].unburdenActive) speed *= 2; - // stat stages - speed *= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][0]; - speed /= gStatStageRatios[gBattleMons[battler].statStages[STAT_SPEED]][1]; - // player's badge boost if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_RECORDED_LINK | BATTLE_TYPE_FRONTIER)) && ShouldGetStatBadgeBoost(B_FLAG_BADGE_BOOST_SPEED, battler) From 25736c5628a5dc2ea128fdee1405268bb7c9ded7 Mon Sep 17 00:00:00 2001 From: Linathan <35115312+LinathanZel@users.noreply.github.com> Date: Thu, 5 Jun 2025 08:35:30 -0400 Subject: [PATCH 13/25] Bug fix for Grassy Terrain incorrectly healing non-grounded Pokemon (#7058) --- src/battle_end_turn.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_end_turn.c b/src/battle_end_turn.c index 7e9f8b15f5..6cf45ded4d 100644 --- a/src/battle_end_turn.c +++ b/src/battle_end_turn.c @@ -490,7 +490,7 @@ static bool32 HandleEndTurnFirstEventBlock(u32 battler) gBattleStruct->eventBlockCounter++; break; case FIRST_EVENT_BLOCK_GRASSY_TERRAIN_HEAL: - if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler)) + if (gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerAlive(battler) && !IsBattlerAtMaxHp(battler) && IsBattlerGrounded(battler)) { gBattlerAttacker = battler; gBattleStruct->moveDamage[battler] = -(GetNonDynamaxMaxHP(battler) / 16); From f374291f69a28133049ef2483b96445c6399fe1c Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 5 Jun 2025 22:47:32 +0200 Subject: [PATCH 14/25] Fixes Wandering Spirit copied ability activation on fainted mon (#7066) --- data/battle_scripts_1.s | 2 ++ test/battle/ability/wandering_spirit.c | 15 +++++++++++++++ 2 files changed, 17 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 9625033c81..5928ea1bb1 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8234,7 +8234,9 @@ BattleScript_WanderingSpiritActivates:: printstring STRINGID_SWAPPEDABILITIES waitmessage B_WAIT_TIME_LONG switchinabilities BS_ATTACKER + jumpiffainted BS_TARGET, TRUE, BattleScript_WanderingSpiritActivatesRet switchinabilities BS_TARGET +BattleScript_WanderingSpiritActivatesRet: return BattleScript_TargetsStatWasMaxedOut:: diff --git a/test/battle/ability/wandering_spirit.c b/test/battle/ability/wandering_spirit.c index d32fb7c7b2..9d8d7fad36 100644 --- a/test/battle/ability/wandering_spirit.c +++ b/test/battle/ability/wandering_spirit.c @@ -2,3 +2,18 @@ #include "test/battle.h" TO_DO_BATTLE_TEST("TODO: Write Wandering Spirit (Ability) test titles") + +SINGLE_BATTLE_TEST("Wandering Spirit copied ability should not trigger on fainted mon") +{ + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + PLAYER(SPECIES_WOBBUFFET) + OPPONENT(SPECIES_YAMASK_GALAR) { HP(1); Ability(ABILITY_WANDERING_SPIRIT); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_POISON_FANG); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_POISON_FANG, player); + NOT ABILITY_POPUP(opponent, ABILITY_INTIMIDATE); + } +} From 451cb91d5d1a9211033aa661a82a28decaf3eb32 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Fri, 6 Jun 2025 11:14:17 -0700 Subject: [PATCH 15/25] add Bivurnum as a contributor for code (#7067) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> Co-authored-by: psf <77138753+pkmnsnfrn@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ CREDITS.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index 72bf225826..b459747530 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -273,6 +273,15 @@ "contributions": [ "code" ] + }, + { + "login": "Bivurnum", + "name": "Bivurnum", + "avatar_url": "https://avatars.githubusercontent.com/u/147376167?v=4", + "profile": "https://github.com/Bivurnum", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index c93c1bcfd4..3ac869cefc 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -50,6 +50,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d grintoul
grintoul

πŸ’» bassforte123
bassforte123

πŸ’» iriv24
iriv24

πŸ’» + Bivurnum
Bivurnum

πŸ’» From dc279f14ba08208f42686b807152dfbedd9efe20 Mon Sep 17 00:00:00 2001 From: Linathan <35115312+LinathanZel@users.noreply.github.com> Date: Fri, 6 Jun 2025 15:33:56 -0400 Subject: [PATCH 16/25] Chloroblast fix (#7008) --- include/constants/battle_move_effects.h | 1 + src/battle_ai_main.c | 1 + src/battle_ai_util.c | 1 + src/battle_script_commands.c | 9 ++ src/data/battle_move_effects.h | 6 + src/data/moves_info.h | 2 +- test/battle/move_effect/chloroblast.c | 153 ++++++++++++++++++++++++ 7 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 test/battle/move_effect/chloroblast.c diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index eb0756bd40..d081d3a163 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -308,6 +308,7 @@ enum BattleMoveEffects EFFECT_COURT_CHANGE, EFFECT_MAX_HP_50_RECOIL, 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_DARK_VOID, diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 2805a10692..18c140c2d2 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -5510,6 +5510,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_MAX_HP_50_RECOIL: case EFFECT_MIND_BLOWN: + case EFFECT_CHLOROBLAST: case EFFECT_SWAGGER: case EFFECT_FLATTER: case EFFECT_ATTRACT: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index e71f11c70f..703335b326 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1014,6 +1014,7 @@ static bool32 AI_IsMoveEffectInMinus(u32 battlerAtk, u32 battlerDef, u32 move, s { case EFFECT_MAX_HP_50_RECOIL: case EFFECT_MIND_BLOWN: + case EFFECT_CHLOROBLAST: case EFFECT_EXPLOSION: case EFFECT_FINAL_GAMBIT: return TRUE; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 88f3cfba54..83e2622ed6 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7024,6 +7024,15 @@ static void Cmd_moveend(void) effect = TRUE; } break; + case EFFECT_CHLOROBLAST: + if (IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) + { + gBattleStruct->moveDamage[gBattlerAttacker] = (GetNonDynamaxMaxHP(gBattlerAttacker) + 1) / 2; // Half of Max HP Rounded UP + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil; + effect = TRUE; + } + break; case EFFECT_RAPID_SPIN: if (IsBattlerTurnDamaged(gBattlerTarget)) { diff --git a/src/data/battle_move_effects.h b/src/data/battle_move_effects.h index 06b1fb3fd6..3b3a8f8e2c 100644 --- a/src/data/battle_move_effects.h +++ b/src/data/battle_move_effects.h @@ -1966,6 +1966,12 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] = .battleTvScore = 0, // TODO: Assign points }, + [EFFECT_CHLOROBLAST] = + { + .battleScript = BattleScript_EffectHit, + .battleTvScore = 0, // TODO: Assign points + }, + [EFFECT_EXTREME_EVOBOOST] = { .battleScript = BattleScript_EffectExtremeEvoboost, diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 0b61900109..d2e80d787b 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -19319,7 +19319,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_ALL] = .description = COMPOUND_STRING( "A user-hurting blast of\n" "amassed chlorophyll."), - .effect = EFFECT_MAX_HP_50_RECOIL, + .effect = EFFECT_CHLOROBLAST, .power = B_UPDATED_MOVE_DATA >= GEN_9 ? 150 : 120, .type = TYPE_GRASS, .accuracy = 95, diff --git a/test/battle/move_effect/chloroblast.c b/test/battle/move_effect/chloroblast.c new file mode 100644 index 0000000000..6452736478 --- /dev/null +++ b/test/battle/move_effect/chloroblast.c @@ -0,0 +1,153 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_CHLOROBLAST) == EFFECT_CHLOROBLAST); +} + +SINGLE_BATTLE_TEST("Chloroblast makes the user lose 1/2 of its Max HP") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CHLOROBLAST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(player, damage: 200); + NOT MESSAGE("Wobbuffet fainted!"); // Wobb had more than 1/2 of its HP, so it can't faint. + } +} + +SINGLE_BATTLE_TEST("Chloroblast causes the user to faint when below 1/2 of its Max HP") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(200); MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CHLOROBLAST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(player, hp: 0); + MESSAGE("Wobbuffet fainted!"); + } +} + +SINGLE_BATTLE_TEST("Chloroblast causes the user & the target to faint when below 1/2 of its Max HP") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(200) ; MaxHP(400); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CHLOROBLAST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(opponent, hp: 0); + MESSAGE("The opposing Wobbuffet fainted!"); + HP_BAR(player, hp: 0); + MESSAGE("Wobbuffet fainted!"); + } +} + +SINGLE_BATTLE_TEST("Chloroblast hp loss is prevented by Magic Guard") +{ + GIVEN { + PLAYER(SPECIES_CLEFAIRY) { Ability(ABILITY_MAGIC_GUARD); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CHLOROBLAST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(opponent); + NOT HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Chloroblast does not cause recoil damage if the user has Rock Head") +{ + GIVEN { + PLAYER(SPECIES_AERODACTYL) { Ability(ABILITY_ROCK_HEAD); } + OPPONENT(SPECIES_WOBBUFFET) { HP(400); MaxHP(400); } + } WHEN { + TURN { MOVE(player, MOVE_CHLOROBLAST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(opponent); + NOT HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Chloroblast does not cause the user to lose HP even if the opposing mon protected") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_PROTECT); MOVE(player, MOVE_CHLOROBLAST); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(player); + } + } +} + +SINGLE_BATTLE_TEST("Chloroblast does not cause the user to lose HP even if it is absorbed by Sap Sipper") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_CHLOROBLAST) == TYPE_GRASS); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_GOGOAT) { Ability(ABILITY_SAP_SIPPER); } + } WHEN { + TURN { MOVE(player, MOVE_CHLOROBLAST); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_SAP_SIPPER); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(player); + } + } +} + +SINGLE_BATTLE_TEST("Chloroblast does not cause the user to lose HP if there is no target") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_MEMENTO); MOVE(player, MOVE_CHLOROBLAST); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MEMENTO, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_CHLOROBLAST, player); + HP_BAR(player); + } + MESSAGE("Wobbuffet used Chloroblast!"); + MESSAGE("But it failed!"); + MESSAGE("2 sent out Wobbuffet!"); + } +} + +SINGLE_BATTLE_TEST("Chloroblast is not affected by Reckless", s16 damage) +{ + u32 move; + + PARAMETRIZE { move = MOVE_CHLOROBLAST; } + PARAMETRIZE { move = MOVE_FRENZY_PLANT; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, move); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} From 67f7ad6b1e4e40760233331f49f4e4a5a421a801 Mon Sep 17 00:00:00 2001 From: i0brendan0 <19826742+i0brendan0@users.noreply.github.com> Date: Fri, 6 Jun 2025 15:00:33 -0500 Subject: [PATCH 17/25] [DRAFT] Fix Normalize not boosting Normal type moves if they were already Normal type (#7060) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_main.c | 4 +- test/battle/ability/normalize.c | 76 ++++++++++++++++++++++----------- 2 files changed, 55 insertions(+), 25 deletions(-) diff --git a/src/battle_main.c b/src/battle_main.c index 662cf39791..baed10a691 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -6014,7 +6014,9 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, enum MonState gBattleStruct->ateBoost[battler] = TRUE; return ateType; } - else if (moveType != TYPE_NORMAL + else if (moveEffect != EFFECT_CHANGE_TYPE_ON_ITEM + && moveEffect != EFFECT_TERRAIN_PULSE + && moveEffect != EFFECT_NATURAL_GIFT && moveEffect != EFFECT_HIDDEN_POWER && moveEffect != EFFECT_WEATHER_BALL && ability == ABILITY_NORMALIZE diff --git a/test/battle/ability/normalize.c b/test/battle/ability/normalize.c index 4858997421..2a449f74a5 100644 --- a/test/battle/ability/normalize.c +++ b/test/battle/ability/normalize.c @@ -80,40 +80,52 @@ SINGLE_BATTLE_TEST("Normalize still makes Freeze-Dry do super effective damage t } } -SINGLE_BATTLE_TEST("Normalize boosts power of unaffected moves by 20% (Gen7+)", s16 damage) +SINGLE_BATTLE_TEST("Normalize doesn't boost power of unaffected moves by 20% (< Gen7)", s16 damage) { - u32 ability, genConfig; - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_6; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_6; } + u32 ability; + PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } + PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); - PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_TACKLE); } + WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_6); + PLAYER(SPECIES_DELCATTY) { Ability(ability); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(player, MOVE_TACKLE); } + TURN { MOVE(player, MOVE_POUND); } } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { - if (genConfig >= GEN_7) - EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.2), results[2].damage); // Ate - else - EXPECT_EQ(results[1].damage, results[3].damage); // No boost + EXPECT_EQ(results[0].damage, results[1].damage); // No boost } } -SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s16 damage) +SINGLE_BATTLE_TEST("Normalize boosts power of unaffected moves by 20% (Gen7+)", s16 damage) { - u32 ability, genConfig; - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_CUTE_CHARM; genConfig = GEN_6; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_7; } - PARAMETRIZE { ability = ABILITY_NORMALIZE; genConfig = GEN_6; } + u32 ability; + PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } + PARAMETRIZE { ability = ABILITY_NORMALIZE; } GIVEN { - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); + WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_7); + PLAYER(SPECIES_DELCATTY) { Ability(ability); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_POUND); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, UQ_4_12(1.2), results[1].damage); // Ate + } +} + +SINGLE_BATTLE_TEST("Normalize doesn't boost power of affected moves by 20% (< Gen7)", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } + PARAMETRIZE { ability = ABILITY_NORMALIZE; } + + GIVEN { + WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_6); PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -121,10 +133,26 @@ SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s1 } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { - if (genConfig >= GEN_7) - EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.8), results[2].damage); // STAB + ate - else - EXPECT_MUL_EQ(results[1].damage, Q_4_12(1.5), results[3].damage); // STAB + no ate + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); // STAB + no ate + } +} + +SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s16 damage) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_CUTE_CHARM; } + PARAMETRIZE { ability = ABILITY_NORMALIZE; } + + GIVEN { + WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, GEN_7); + PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WATER_GUN); } + } SCENE { + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.8), results[1].damage); // STAB + ate } } From fd90802a37557d100fb4b0646fa3d05360483988 Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Sat, 7 Jun 2025 00:51:47 -0700 Subject: [PATCH 18/25] Fixed CI issue introduced 7046 (#7072) --- .github/workflows/build.yml | 4 ++-- .github/workflows/labels.yml | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3304101d4f..30231dbd0f 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -9,7 +9,7 @@ on: jobs: build: - if: github.actor != 'allcontributors' + if: github.actor != 'allcontributors[bot]' runs-on: ubuntu-latest env: GAME_VERSION: EMERALD @@ -38,7 +38,7 @@ jobs: run: | make -j${nproc} check allcontributors: - if: github.actor == 'allcontributors' + if: github.actor == 'allcontributors[bot]' runs-on: ubuntu-latest needs: [] steps: diff --git a/.github/workflows/labels.yml b/.github/workflows/labels.yml index 7315082cb6..325e72950d 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/labels.yml @@ -6,7 +6,7 @@ on: jobs: label: - if: github.actor != 'allcontributors' + if: github.actor != 'allcontributors[bot]' runs-on: ubuntu-latest steps: - name: check labels @@ -29,7 +29,7 @@ jobs: category: sprite-issue type: documentation allcontributors: - if: github.actor == 'allcontributors' + if: github.actor == 'allcontributors[bot]' runs-on: ubuntu-latest needs: [] steps: From ea75a09dac6a5cc2c1c0cfb0d4fe1a07bf4f4878 Mon Sep 17 00:00:00 2001 From: Bivurnum <147376167+Bivurnum@users.noreply.github.com> Date: Sat, 7 Jun 2025 02:54:07 -0500 Subject: [PATCH 19/25] Clear saved follower NPC door warp when doing dive warp (#7065) --- src/field_screen_effect.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/field_screen_effect.c b/src/field_screen_effect.c index 9ac99465ca..7b17f53666 100644 --- a/src/field_screen_effect.c +++ b/src/field_screen_effect.c @@ -528,6 +528,7 @@ void DoDiveWarp(void) TryFadeOutOldMapMusic(); WarpFadeOutScreen(); PlayRainStoppingSoundEffect(); + SetFollowerNPCData(FNPC_DATA_COME_OUT_DOOR, FNPC_DOOR_NONE); gFieldCallback = FieldCB_DefaultWarpExit; CreateTask(Task_WarpAndLoadMap, 10); } From 1692d641c47ddf8c697be963891ffdfbd8bb910b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=98=8E=E9=9B=85?= <56014327+ExMingYan@users.noreply.github.com> Date: Sat, 7 Jun 2025 16:05:24 +0800 Subject: [PATCH 20/25] Fix Contest Painting load palette error (#7077) --- src/contest_painting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/contest_painting.c b/src/contest_painting.c index 1911e70689..cb78caac26 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -363,7 +363,7 @@ static void VBlankCB_ContestPainting(void) static void InitContestMonPixels(u16 species, bool8 backPic) { const void *pal = GetMonSpritePalFromSpeciesAndPersonality(species, gContestPaintingWinner->isShiny, gContestPaintingWinner->personality); - LZDecompressVram(pal, gContestPaintingMonPalette); + memcpy(gContestPaintingMonPalette, pal, PLTT_SIZE_4BPP); if (!backPic) { HandleLoadSpecialPokePic(TRUE, From 9f1eb78737283b8e04aa36ba998503e298c66aad Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 7 Jun 2025 11:49:15 +0200 Subject: [PATCH 21/25] Fixes freeze during a 1v2 double battle (#7075) --- src/battle_script_commands.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 83e2622ed6..05a2563cd5 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2868,7 +2868,7 @@ static void Cmd_resultmessage(void) gDisableStructs[gBattlerTarget].iceFaceActivationPrevention = FALSE; u32 side = GetBattlerSide(gBattlerTarget); if (gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[gBattlerTarget]] == SPECIES_NONE) - gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; + gBattleStruct->changedSpecies[side][gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species; gBattleMons[gBattlerTarget].species = SPECIES_EISCUE_NOICE; gBattleScripting.battler = gBattlerTarget; // For STRINGID_PKMNTRANSFORMED BattleScriptPushCursor(); @@ -7934,7 +7934,16 @@ static void Cmd_openpartyscreen(void) { if (((1u << i) & hitmarkerFaintBits)) { - if (i > 1 && ((1u << BATTLE_PARTNER(i)) & hitmarkerFaintBits)) + u32 skipPartnerCheck = FALSE; + if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS + && GetBattlerSide(i) == B_SIDE_OPPONENT + && TRAINER_BATTLE_PARAM.opponentB != TRAINER_NONE) + skipPartnerCheck = TRUE; + + // In a 1v2 Double Battle if trainer A didn't have any more mons left + // the battler for trainer B wasn't being registered to be send out. + // Likely reason is because hitmarkerFaintBits was not set for battler 1 due to it being missing for a turn or cleared somewhere + if (!skipPartnerCheck && i > 1 && ((1u << BATTLE_PARTNER(i)) & hitmarkerFaintBits)) continue; battler = i; From 29adca79a514f3cb7f6de568abcd1f939f017442 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sat, 7 Jun 2025 07:06:20 -0700 Subject: [PATCH 22/25] add pkmnsnfrn as a contributor for projectManagement (#7081) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 3 ++- CREDITS.md | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index b459747530..e030f8953c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -118,7 +118,8 @@ "profile": "https://linktr.ee/pkmnsnfrn", "contributions": [ "maintenance", - "code" + "code", + "projectManagement" ] }, { diff --git a/CREDITS.md b/CREDITS.md index 3ac869cefc..644d980e68 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -30,7 +30,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Pawkkie
Pawkkie

🚧 πŸ’» πŸ“– Philipp AUER
Philipp AUER

🚧 πŸ’» tertu
tertu

🚧 πŸ’» - psf
psf

🚧 πŸ’» + psf
psf

🚧 πŸ’» πŸ“† wiz1989
wiz1989

πŸ’» PCG
PCG

πŸ’» kittenchilly
kittenchilly

πŸ’» πŸ”¬ πŸ”£ From 28d185be95a9e6194bda0e840fbd36b02665207e Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Sat, 7 Jun 2025 22:59:44 +0100 Subject: [PATCH 23/25] Fixes Pursuit potentially causing both battlers to switch into the same mon (#7084) --- src/battle_script_commands.c | 6 ++++++ src/battle_util.c | 22 +++++++++++----------- test/battle/move_effect/pursuit.c | 20 ++++++++++++++++++++ 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 05a2563cd5..fc4cee0621 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7445,6 +7445,12 @@ static void Cmd_moveend(void) SetActiveGimmick(gBattlerAttacker, GIMMICK_NONE); if (B_CHARGE >= GEN_9 && moveType == TYPE_ELECTRIC && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT)) gStatuses3[gBattlerAttacker] &= ~(STATUS3_CHARGED_UP); + // check if Stellar type boost should be used up + if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA + && GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR + && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS + && IsTypeStellarBoosted(gBattlerAttacker, moveType)) + ExpendTypeStellarBoost(gBattlerAttacker, moveType); memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); for (i = 0; i < gBattlersCount; i++) diff --git a/src/battle_util.c b/src/battle_util.c index 9e7405bb48..646edebed2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -545,6 +545,16 @@ void HandleAction_UseMove(void) void HandleAction_Switch(void) { gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; + + // if switching to a mon that is already on field, cancel switch + if (!(gAbsentBattlerFlags & (1u << BATTLE_PARTNER(gBattlerAttacker))) + && IsBattlerAlive(BATTLE_PARTNER(gBattlerAttacker)) + && gBattlerPartyIndexes[BATTLE_PARTNER(gBattlerAttacker)] == gBattleStruct->monToSwitchIntoId[gBattlerAttacker]) + { + gCurrentActionFuncId = B_ACTION_FINISHED; + return; + } + gBattle_BG0_X = 0; gBattle_BG0_Y = 0; gActionSelectionCursor[gBattlerAttacker] = 0; @@ -851,7 +861,7 @@ void HandleAction_NothingIsFainted(void) void HandleAction_ActionFinished(void) { - u32 i, j, moveType; + u32 i, j; bool32 afterYouActive = gSpecialStatuses[gBattlerByTurnOrder[gCurrentTurnActionNumber + 1]].afterYou; gBattleStruct->monToSwitchIntoId[gBattlerByTurnOrder[gCurrentTurnActionNumber]] = gSelectedMonPartyId = PARTY_SIZE; gCurrentTurnActionNumber++; @@ -862,16 +872,6 @@ void HandleAction_ActionFinished(void) | HITMARKER_OBEYS | HITMARKER_SYNCHRONIZE_EFFECT | HITMARKER_CHARGING | HITMARKER_IGNORE_DISGUISE); - // check if Stellar type boost should be used up - moveType = GetBattleMoveType(gCurrentMove); - - if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_TERA - && GetBattlerTeraType(gBattlerAttacker) == TYPE_STELLAR - && GetMoveCategory(gCurrentMove) != DAMAGE_CATEGORY_STATUS - && IsTypeStellarBoosted(gBattlerAttacker, moveType)) - { - ExpendTypeStellarBoost(gBattlerAttacker, moveType); - } ClearDamageCalcResults(); gCurrentMove = 0; gBattleScripting.animTurn = 0; diff --git a/test/battle/move_effect/pursuit.c b/test/battle/move_effect/pursuit.c index 649b331eec..b18aa74b09 100644 --- a/test/battle/move_effect/pursuit.c +++ b/test/battle/move_effect/pursuit.c @@ -673,4 +673,24 @@ SINGLE_BATTLE_TEST("Pursuit user faints to Life Orb and target still switches ou } } +DOUBLE_BATTLE_TEST("Pursuit user switches out due to Red Card and partner's switch is cancelled if switching to same PokΓ©mon") +{ + GIVEN { + ASSUME(GetItemHoldEffect(ITEM_RED_CARD) == HOLD_EFFECT_RED_CARD); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_ARCEUS); + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_RED_CARD); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_ARCEUS); + } WHEN { + TURN { SWITCH(opponentLeft, 2); SWITCH(playerRight, 2); MOVE(playerLeft, MOVE_PURSUIT, target: opponentLeft); } + } THEN { + // playerLeft switches to Arceus + EXPECT_EQ(playerLeft->species, SPECIES_ARCEUS); + // playerRight has their switch cancelled + EXPECT_EQ(playerRight->species, SPECIES_WYNAUT); + } +} + TO_DO_BATTLE_TEST("Baton Pass doesn't cause Pursuit to increase its power or priority"); From 5586b0c2165e21169c6398521303ac42fff53891 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Sun, 8 Jun 2025 00:00:14 +0200 Subject: [PATCH 24/25] add ravepossum as a contributor for code (#7083) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 9 +++++++++ CREDITS.md | 1 + 2 files changed, 10 insertions(+) diff --git a/.all-contributorsrc b/.all-contributorsrc index e030f8953c..0f6667d232 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -283,6 +283,15 @@ "contributions": [ "code" ] + }, + { + "login": "ravepossum", + "name": "RavePossum", + "avatar_url": "https://avatars.githubusercontent.com/u/145081120?v=4", + "profile": "https://github.com/ravepossum", + "contributions": [ + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index 644d980e68..488a40a146 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -51,6 +51,7 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d bassforte123
bassforte123

πŸ’» iriv24
iriv24

πŸ’» Bivurnum
Bivurnum

πŸ’» + RavePossum
RavePossum

πŸ’» From 0834d9d80be370dd0d995629a300fc8551529022 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Mon, 9 Jun 2025 22:52:37 +0200 Subject: [PATCH 25/25] Added loop iterator style (#7092) Co-authored-by: Hedara --- docs/STYLEGUIDE.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/docs/STYLEGUIDE.md b/docs/STYLEGUIDE.md index f53e1a2dcc..dc99be6b1b 100644 --- a/docs/STYLEGUIDE.md +++ b/docs/STYLEGUIDE.md @@ -265,6 +265,15 @@ void SetCurrentDifficultyLevel(enum DifficultyLevel desiredDifficulty) .power = B_UPDATED_MOVE_DATA >= GEN_6 ? 45 : 35, }, ``` +### Variable Declarations +Loop iterators should be declared as part of the loop unless there's a very good reason not to. +```C +for (u32 i = 0; i < LOOP_ITERATIONS; i++) +{ + dst1[i] = i; + dst2[i] = i; +} +``` ## Data Type Sizes When a variable number is used, the data type should generally `u32` (unsigned) or `s32` (signed). There are a few exceptions to this rule, such as: * Values stored in the saveblock should use the smallest data type possible. @@ -350,7 +359,7 @@ enum DifficultyLevel GetCurrentDifficultyLevel(void) } ``` -### Data file format +## Data file format External data files should use JSON.