From 720b2daecc2054e6e9b8d370dc7fbaf182c1a794 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 5 Dec 2024 18:25:27 -0300 Subject: [PATCH 01/31] Improve Pyramid location documentaion --- asm/macros/battle_frontier/battle_pyramid.inc | 4 ++-- data/scripts/field_poison.inc | 6 +++--- data/scripts/obtain_item.inc | 4 ++-- include/battle_pyramid.h | 9 ++++++++- include/constants/battle_pyramid.h | 6 +++++- src/battle_pyramid.c | 16 ++++++++-------- src/field_poison.c | 2 +- src/frontier_pass.c | 6 +++--- src/item_use.c | 2 +- src/party_menu.c | 2 +- 10 files changed, 34 insertions(+), 23 deletions(-) diff --git a/asm/macros/battle_frontier/battle_pyramid.inc b/asm/macros/battle_frontier/battle_pyramid.inc index bb5069f18a..42141d9937 100644 --- a/asm/macros/battle_frontier/battle_pyramid.inc +++ b/asm/macros/battle_frontier/battle_pyramid.inc @@ -69,8 +69,8 @@ .endm @ VAR_RESULT is 1 if player is on a Pyramid floor, 2 if on the Pyramid peak, 0 otherwise - .macro pyramid_inchallenge - setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_IS_IN + .macro pyramid_getlocation + setvar VAR_0x8004, BATTLE_PYRAMID_FUNC_CURRENT_LOCATION special CallBattlePyramidFunction .endm diff --git a/data/scripts/field_poison.inc b/data/scripts/field_poison.inc index ddda34ebaa..1d89bcfdfd 100644 --- a/data/scripts/field_poison.inc +++ b/data/scripts/field_poison.inc @@ -29,9 +29,9 @@ EventScript_FrontierFieldWhiteOut:: waitbuttonpress pike_inchallenge goto_if_eq VAR_RESULT, TRUE, BattleFrontier_BattlePike_EventScript_Retire - pyramid_inchallenge - goto_if_eq VAR_RESULT, 1, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost @ On Pyramid floor - goto_if_eq VAR_RESULT, 2, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost @ On Pyramid peak + pyramid_getlocation + goto_if_eq VAR_RESULT, PYRAMID_LOCATION_FLOOR, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost + goto_if_eq VAR_RESULT, PYRAMID_LOCATION_TOP, BattleFrontier_BattlePyramid_EventScript_WarpToLobbyLost trainerhill_inchallenge goto_if_eq VAR_RESULT, TRUE, TrainerHill_1F_EventScript_Lost special Script_FadeOutMapMusic diff --git a/data/scripts/obtain_item.inc b/data/scripts/obtain_item.inc index e982858e7b..6831a75b6e 100644 --- a/data/scripts/obtain_item.inc +++ b/data/scripts/obtain_item.inc @@ -118,8 +118,8 @@ EventScript_PickUpItem:: waitfanfare waitmessage bufferitemnameplural STR_VAR_2, VAR_0x8004, VAR_0x8005 - pyramid_inchallenge - goto_if_eq VAR_RESULT, TRUE, EventScript_PutBattlePyramidItemInBag + pyramid_getlocation + goto_if_eq VAR_RESULT, PYRAMID_LOCATION_FLOOR, EventScript_PutBattlePyramidItemInBag msgbox gText_PutItemInPocket, MSGBOX_DEFAULT return diff --git a/include/battle_pyramid.h b/include/battle_pyramid.h index 62320358b6..8b35e9967c 100644 --- a/include/battle_pyramid.h +++ b/include/battle_pyramid.h @@ -1,13 +1,15 @@ #ifndef GUARD_BATTLE_PYRAMID_H #define GUARD_BATTLE_PYRAMID_H +#include "constants/battle_pyramid.h" + void CallBattlePyramidFunction(void); u16 LocalIdToPyramidTrainerId(u8 localId); bool8 GetBattlePyramidTrainerFlag(u8 eventId); void MarkApproachingPyramidTrainersAsBattled(void); void GenerateBattlePyramidWildMon(void); u8 GetPyramidRunMultiplier(void); -u8 InBattlePyramid(void); +u8 CurrentBattlePyramidLocation(void); bool8 InBattlePyramid_(void); void PausePyramidChallenge(void); void SoftResetInBattlePyramid(void); @@ -21,4 +23,9 @@ void LoadBattlePyramidFloorObjectEventScripts(void); u8 GetNumBattlePyramidObjectEvents(void); u16 GetBattlePyramidPickupItemId(void); +static inline bool8 InBattlePyramid() +{ + return (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE); +} + #endif // GUARD_BATTLE_PYRAMID_H diff --git a/include/constants/battle_pyramid.h b/include/constants/battle_pyramid.h index ac80a2d7d3..08fa695cf2 100644 --- a/include/constants/battle_pyramid.h +++ b/include/constants/battle_pyramid.h @@ -43,7 +43,7 @@ #define BATTLE_PYRAMID_FUNC_SET_TRAINERS 9 #define BATTLE_PYRAMID_FUNC_SHOW_HINT_TEXT 10 #define BATTLE_PYRAMID_FUNC_UPDATE_STREAK 11 // unused -#define BATTLE_PYRAMID_FUNC_IS_IN 12 +#define BATTLE_PYRAMID_FUNC_CURRENT_LOCATION 12 #define BATTLE_PYRAMID_FUNC_UPDATE_LIGHT 13 #define BATTLE_PYRAMID_FUNC_CLEAR_HELD_ITEMS 14 #define BATTLE_PYRAMID_FUNC_SET_FLOOR_PALETTE 15 @@ -62,4 +62,8 @@ #define PYRAMID_LIGHT_SET_RADIUS 0 #define PYRAMID_LIGHT_INCR_RADIUS 1 +#define PYRAMID_LOCATION_NONE 0 // Not in the Pyramid +#define PYRAMID_LOCATION_FLOOR 1 +#define PYRAMID_LOCATION_TOP 2 + #endif // GUARD_CONSTANTS_BATTLE_PYRAMID_H diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index b4bb3cacca..b463e85357 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -79,7 +79,7 @@ static void HidePyramidItem(void); static void SetPyramidFacilityTrainers(void); static void ShowPostBattleHintText(void); static void UpdatePyramidWinStreak(void); -static void GetInBattlePyramid(void); +static void GetCurrentBattlePyramidLocation(void); static void UpdatePyramidLightRadius(void); static void ClearPyramidPartyHeldItems(void); static void SetPyramidFloorPalette(void); @@ -798,7 +798,7 @@ static void (* const sBattlePyramidFunctions[])(void) = [BATTLE_PYRAMID_FUNC_SET_TRAINERS] = SetPyramidFacilityTrainers, [BATTLE_PYRAMID_FUNC_SHOW_HINT_TEXT] = ShowPostBattleHintText, [BATTLE_PYRAMID_FUNC_UPDATE_STREAK] = UpdatePyramidWinStreak, - [BATTLE_PYRAMID_FUNC_IS_IN] = GetInBattlePyramid, + [BATTLE_PYRAMID_FUNC_CURRENT_LOCATION] = GetCurrentBattlePyramidLocation, [BATTLE_PYRAMID_FUNC_UPDATE_LIGHT] = UpdatePyramidLightRadius, [BATTLE_PYRAMID_FUNC_CLEAR_HELD_ITEMS] = ClearPyramidPartyHeldItems, [BATTLE_PYRAMID_FUNC_SET_FLOOR_PALETTE] = SetPyramidFloorPalette, @@ -1113,9 +1113,9 @@ static void UpdatePyramidWinStreak(void) gSaveBlock2Ptr->frontier.pyramidRecordStreaks[lvlMode] = gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode]; } -static void GetInBattlePyramid(void) +static void GetCurrentBattlePyramidLocation(void) { - gSpecialVar_Result = InBattlePyramid(); + gSpecialVar_Result = CurrentBattlePyramidLocation(); } static void UpdatePyramidLightRadius(void) @@ -1419,14 +1419,14 @@ u8 GetPyramidRunMultiplier(void) return sPyramidFloorTemplates[id].runMultiplier; } -u8 InBattlePyramid(void) +u8 CurrentBattlePyramidLocation(void) { if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR) - return 1; + return PYRAMID_LOCATION_FLOOR; else if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_TOP) - return 2; + return PYRAMID_LOCATION_TOP; else - return FALSE; + return PYRAMID_LOCATION_NONE; } bool8 InBattlePyramid_(void) diff --git a/src/field_poison.c b/src/field_poison.c index d952b4b640..e0b08b8716 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -92,7 +92,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) #ifdef BUGFIX if (InBattlePyramid() || InBattlePike() || InTrainerHillChallenge()) #else - if (InBattlePyramid() | InBattlePike() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() | InBattlePike() || InTrainerHillChallenge()) #endif gSpecialVar_Result = FLDPSN_FRONTIER_WHITEOUT; else diff --git a/src/frontier_pass.c b/src/frontier_pass.c index a351d81ce9..960684c9ea 100644 --- a/src/frontier_pass.c +++ b/src/frontier_pass.c @@ -917,12 +917,12 @@ static void CB2_ReturnFromRecord(void) sPassData->cursorX = sSavedPassData.cursorX; sPassData->cursorY = sSavedPassData.cursorY; memset(&sSavedPassData, 0, sizeof(sSavedPassData)); - switch (InBattlePyramid()) + switch (CurrentBattlePyramidLocation()) { - case 1: + case PYRAMID_LOCATION_FLOOR: PlayBGM(MUS_B_PYRAMID); break; - case 2: + case PYRAMID_LOCATION_TOP: PlayBGM(MUS_B_PYRAMID_TOP); break; default: diff --git a/src/item_use.c b/src/item_use.c index 322eaf76c0..181698ac30 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -983,7 +983,7 @@ static void Task_UseStatIncreaseItem(u8 taskId) { PlaySE(SE_USE_ITEM); RemoveBagItem(gSpecialVar_ItemId, 1); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // !InBattlePyramid() doesn't match DisplayItemMessage(taskId, FONT_NORMAL, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); else DisplayItemMessageInBattlePyramid(taskId, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); diff --git a/src/party_menu.c b/src/party_menu.c index cbd469713a..f6dd6a264c 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -5358,7 +5358,7 @@ void CB2_PartyMenuFromStartMenu(void) // As opposted to by selecting Give in the party menu, which is handled by CursorCb_Give void CB2_ChooseMonToGiveItem(void) { - MainCallback callback = (InBattlePyramid() == FALSE) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; + MainCallback callback = (!InBattlePyramid()) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_ITEM, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, callback); gPartyMenu.bagItem = gSpecialVar_ItemId; } From 29ef1cf9ad37a684ba7e379b5865840d326e4257 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 5 Dec 2024 21:00:55 -0300 Subject: [PATCH 02/31] Stick to the new name --- include/battle_pyramid.h | 5 ----- src/battle_pyramid.c | 4 ++-- src/battle_script_commands.c | 2 +- src/battle_setup.c | 24 ++++++++++++------------ src/battle_util.c | 4 ++-- src/event_object_movement.c | 4 ++-- src/field_poison.c | 2 +- src/item.c | 8 ++++---- src/item_menu.c | 4 ++-- src/item_use.c | 26 +++++++++++++------------- src/map_name_popup.c | 2 +- src/party_menu.c | 6 +++--- src/pokemon.c | 4 ++-- src/start_menu.c | 10 +++++----- src/trainer_see.c | 2 +- src/wild_encounter.c | 2 +- 16 files changed, 52 insertions(+), 57 deletions(-) diff --git a/include/battle_pyramid.h b/include/battle_pyramid.h index 8b35e9967c..990a2eca52 100644 --- a/include/battle_pyramid.h +++ b/include/battle_pyramid.h @@ -23,9 +23,4 @@ void LoadBattlePyramidFloorObjectEventScripts(void); u8 GetNumBattlePyramidObjectEvents(void); u16 GetBattlePyramidPickupItemId(void); -static inline bool8 InBattlePyramid() -{ - return (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE); -} - #endif // GUARD_BATTLE_PYRAMID_H diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index b463e85357..f4352a62b8 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -1437,7 +1437,7 @@ bool8 InBattlePyramid_(void) void PausePyramidChallenge(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { RestorePyramidPlayerParty(); gSaveBlock2Ptr->frontier.challengeStatus = CHALLENGE_STATUS_PAUSED; @@ -1448,7 +1448,7 @@ void PausePyramidChallenge(void) void SoftResetInBattlePyramid(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) DoSoftReset(); } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1891ea9285..db92de3c81 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9615,7 +9615,7 @@ static void Cmd_pickup(void) { } - else if (InBattlePyramid()) + else if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { for (i = 0; i < PARTY_SIZE; i++) { diff --git a/src/battle_setup.c b/src/battle_setup.c index ba5cdef0dc..18119a5255 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -405,7 +405,7 @@ static void DoStandardWildBattle(void) StopPlayerAvatar(); gMain.savedCallback = CB2_EndWildBattle; gBattleTypeFlags = 0; - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0); gBattleTypeFlags |= BATTLE_TYPE_PYRAMID; @@ -465,7 +465,7 @@ static void DoTrainerBattle(void) static void DoBattlePyramidTrainerHillBattle(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) CreateBattleStartTask(GetSpecialBattleTransition(B_TRANSITION_GROUP_B_PYRAMID), 0); else CreateBattleStartTask(GetSpecialBattleTransition(B_TRANSITION_GROUP_TRAINER_HILL), 0); @@ -603,7 +603,7 @@ static void CB2_EndWildBattle(void) CpuFill16(0, (void *)(BG_PLTT), BG_PLTT_SIZE); ResetOamRange(0, 128); - if (IsPlayerDefeated(gBattleOutcome) == TRUE && !InBattlePyramid() && !InBattlePike()) + if (IsPlayerDefeated(gBattleOutcome) == TRUE && CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE && !InBattlePike()) { SetMainCallback2(CB2_WhiteOut); } @@ -621,7 +621,7 @@ static void CB2_EndScriptedWildBattle(void) if (IsPlayerDefeated(gBattleOutcome) == TRUE) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); else SetMainCallback2(CB2_WhiteOut); @@ -794,14 +794,14 @@ static u8 GetWildBattleTransition(void) if (enemyLevel < playerLevel) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return B_TRANSITION_BLUR; else return sBattleTransitionTable_Wild[transitionType][0]; } else { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return B_TRANSITION_GRID_SQUARES; else return sBattleTransitionTable_Wild[transitionType][1]; @@ -1233,7 +1233,7 @@ u8 GetTrainerBattleMode(void) bool8 GetTrainerFlag(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return GetBattlePyramidTrainerFlag(gSelectedObjectEvent); else if (InTrainerHill()) return GetHillTrainerFlag(gSelectedObjectEvent); @@ -1275,7 +1275,7 @@ void BattleSetup_StartTrainerBattle(void) else gBattleTypeFlags = (BATTLE_TYPE_TRAINER); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0); gBattleTypeFlags |= BATTLE_TYPE_PYRAMID; @@ -1315,7 +1315,7 @@ void BattleSetup_StartTrainerBattle(void) gWhichTrainerToFaceAfterBattle = 0; gMain.savedCallback = CB2_EndTrainerBattle; - if (InBattlePyramid() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InTrainerHillChallenge()) DoBattlePyramidTrainerHillBattle(); else DoTrainerBattle(); @@ -1331,7 +1331,7 @@ static void CB2_EndTrainerBattle(void) } else if (IsPlayerDefeated(gBattleOutcome) == TRUE) { - if (InBattlePyramid() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InTrainerHillChallenge()) SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); else SetMainCallback2(CB2_WhiteOut); @@ -1339,7 +1339,7 @@ static void CB2_EndTrainerBattle(void) else { SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic); - if (!InBattlePyramid() && !InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE && !InTrainerHillChallenge()) { RegisterTrainerInMatchCall(); SetBattledTrainersFlags(); @@ -1376,7 +1376,7 @@ void BattleSetup_StartRematchBattle(void) void ShowTrainerIntroSpeech(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { if (gNoOfApproachingTrainers == 0 || gNoOfApproachingTrainers == 1) CopyPyramidTrainerSpeechBefore(LocalIdToPyramidTrainerId(gSpecialVar_LastTalked)); diff --git a/src/battle_util.c b/src/battle_util.c index 6e201a2956..b2247b3923 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -426,7 +426,7 @@ bool8 TryRunFromBattle(u8 battler) } else if (gBattleMons[battler].ability == ABILITY_RUN_AWAY) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { gBattleStruct->runTries++; pyramidMultiplier = GetPyramidRunMultiplier(); @@ -453,7 +453,7 @@ bool8 TryRunFromBattle(u8 battler) { if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE)) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { pyramidMultiplier = GetPyramidRunMultiplier(); speedVar = (gBattleMons[battler].speed * pyramidMultiplier) / (gBattleMons[BATTLE_OPPOSITE(battler)].speed) + (gBattleStruct->runTries * 30); diff --git a/src/event_object_movement.c b/src/event_object_movement.c index b3ffb76193..64fa3ef55a 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -1327,7 +1327,7 @@ u8 Unref_TryInitLocalObjectEvent(u8 localId) if (gMapHeader.events != NULL) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) objectEventCount = GetNumBattlePyramidObjectEvents(); else if (InTrainerHill()) objectEventCount = HILL_TRAINERS_PER_FLOOR; @@ -1643,7 +1643,7 @@ void TrySpawnObjectEvents(s16 cameraX, s16 cameraY) s16 top = gSaveBlock1Ptr->pos.y; s16 bottom = gSaveBlock1Ptr->pos.y + MAP_OFFSET_H + 2; - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) objectCount = GetNumBattlePyramidObjectEvents(); else if (InTrainerHill()) objectCount = HILL_TRAINERS_PER_FLOOR; diff --git a/src/field_poison.c b/src/field_poison.c index e0b08b8716..4548933533 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -90,7 +90,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) { // Battle facilities have their own white out script to handle the challenge loss #ifdef BUGFIX - if (InBattlePyramid() || InBattlePike() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InBattlePike() || InTrainerHillChallenge()) #else if (CurrentBattlePyramidLocation() | InBattlePike() || InTrainerHillChallenge()) #endif diff --git a/src/item.c b/src/item.c index b67cf5f218..37428e87df 100644 --- a/src/item.c +++ b/src/item.c @@ -133,7 +133,7 @@ bool8 CheckBagHasItem(u16 itemId, u16 count) if (ItemId_GetPocket(itemId) == 0) return FALSE; - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) return CheckPyramidBagHasItem(itemId, count); pocket = ItemId_GetPocket(itemId) - 1; // Check for item slots that contain the item @@ -181,7 +181,7 @@ bool8 CheckBagHasSpace(u16 itemId, u16 count) if (ItemId_GetPocket(itemId) == POCKET_NONE) return FALSE; - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) { return CheckPyramidBagHasSpace(itemId, count); } @@ -243,7 +243,7 @@ bool8 AddBagItem(u16 itemId, u16 count) return FALSE; // check Battle Pyramid Bag - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) { return AddPyramidBagItem(itemId, count); } @@ -351,7 +351,7 @@ bool8 RemoveBagItem(u16 itemId, u16 count) return FALSE; // check Battle Pyramid Bag - if (InBattlePyramid() || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || FlagGet(FLAG_STORING_ITEMS_IN_PYRAMID_BAG) == TRUE) { return RemovePyramidBagItem(itemId, count); } diff --git a/src/item_menu.c b/src/item_menu.c index f0abfcf62a..e0a7fd0e48 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -565,7 +565,7 @@ void CB2_BagMenuFromStartMenu(void) void CB2_BagMenuFromBattle(void) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) GoToBagMenu(ITEMMENULOCATION_BATTLE, POCKETS_COUNT, CB2_SetUpReshowBattleScreenAfterMenu2); else GoToBattlePyramidBagMenu(PYRAMIDBAG_LOC_BATTLE, CB2_SetUpReshowBattleScreenAfterMenu2); @@ -2036,7 +2036,7 @@ bool8 UseRegisteredKeyItemOnField(void) { u8 taskId; - if (InUnionRoom() == TRUE || InBattlePyramid() || InBattlePike() || InMultiPartnerRoom() == TRUE) + if (InUnionRoom() == TRUE || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InBattlePike() || InMultiPartnerRoom() == TRUE) return FALSE; HideMapNamePopUpWindow(); ChangeBgY_ScreenOff(0, 0, BG_COORD_SET); diff --git a/src/item_use.c b/src/item_use.c index 181698ac30..dd017ee170 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -102,7 +102,7 @@ static void SetUpItemUseCallback(u8 taskId) type = gTasks[taskId].tEnigmaBerryType - 1; else type = ItemId_GetType(gSpecialVar_ItemId) - 1; - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { gBagMenu->newScreenCallback = sItemUseCallbacks[type]; Task_FadeAndCloseBagMenu(taskId); @@ -144,7 +144,7 @@ static void DisplayCannotUseItemMessage(u8 taskId, bool8 isUsingRegisteredKeyIte StringExpandPlaceholders(gStringVar4, str); if (!isUsingRegisteredKeyItemOnField) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gText_DadsAdvice, Task_CloseBattlePyramidBagMessage); @@ -826,7 +826,7 @@ static void RemoveUsedItem(void) RemoveBagItem(gSpecialVar_ItemId, 1); CopyItemName(gSpecialVar_ItemId, gStringVar2); StringExpandPlaceholders(gStringVar4, gText_PlayerUsedVar2); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { UpdatePocketItemList(ItemId_GetPocket(gSpecialVar_ItemId)); UpdatePocketListPosition(ItemId_GetPocket(gSpecialVar_ItemId)); @@ -842,7 +842,7 @@ void ItemUseOutOfBattle_Repel(u8 taskId) { if (VarGet(VAR_REPEL_STEP_COUNT) == 0) gTasks[taskId].func = Task_StartUseRepel; - else if (!InBattlePyramid()) + else if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gText_RepelEffectsLingered, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gText_RepelEffectsLingered, Task_CloseBattlePyramidBagMessage); @@ -866,7 +866,7 @@ static void Task_UseRepel(u8 taskId) { VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gSpecialVar_ItemId)); RemoveUsedItem(); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage); @@ -878,7 +878,7 @@ static void Task_UsedBlackWhiteFlute(u8 taskId) if(++gTasks[taskId].data[8] > 7) { PlaySE(SE_GLASS_FLUTE); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gStringVar4, Task_CloseBattlePyramidBagMessage); @@ -951,12 +951,12 @@ void ItemUseInBattle_PokeBall(u8 taskId) if (IsPlayerPartyAndPokemonStorageFull() == FALSE) // have room for mon? { RemoveBagItem(gSpecialVar_ItemId, 1); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) Task_FadeAndCloseBagMenu(taskId); else CloseBattlePyramidBag(taskId); } - else if (!InBattlePyramid()) + else if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { DisplayItemMessage(taskId, FONT_NORMAL, gText_BoxFull, CloseItemMessage); } @@ -970,7 +970,7 @@ static void Task_CloseStatIncreaseMessage(u8 taskId) { if (JOY_NEW(A_BUTTON | B_BUTTON)) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) Task_FadeAndCloseBagMenu(taskId); else CloseBattlePyramidBag(taskId); @@ -983,7 +983,7 @@ static void Task_UseStatIncreaseItem(u8 taskId) { PlaySE(SE_USE_ITEM); RemoveBagItem(gSpecialVar_ItemId, 1); - if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // !InBattlePyramid() doesn't match + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE doesn't match DisplayItemMessage(taskId, FONT_NORMAL, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); else DisplayItemMessageInBattlePyramid(taskId, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); @@ -997,7 +997,7 @@ void ItemUseInBattle_StatIncrease(u8 taskId) if (ExecuteTableBasedItemEffect(&gPlayerParty[partyId], gSpecialVar_ItemId, partyId, 0) != FALSE) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gText_WontHaveEffect, CloseItemMessage); else DisplayItemMessageInBattlePyramid(taskId, gText_WontHaveEffect, Task_CloseBattlePyramidBagMessage); @@ -1011,7 +1011,7 @@ void ItemUseInBattle_StatIncrease(u8 taskId) static void ItemUseInBattle_ShowPartyMenu(u8 taskId) { - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) { gBagMenu->newScreenCallback = ChooseMonForInBattleItem; Task_FadeAndCloseBagMenu(taskId); @@ -1049,7 +1049,7 @@ void ItemUseInBattle_Escape(u8 taskId) if((gBattleTypeFlags & BATTLE_TYPE_TRAINER) == FALSE) { RemoveUsedItem(); - if (!InBattlePyramid()) + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, gStringVar4, Task_FadeAndCloseBagMenu); else DisplayItemMessageInBattlePyramid(taskId, gStringVar4, CloseBattlePyramidBag); diff --git a/src/map_name_popup.c b/src/map_name_popup.c index d004b18d56..150459762a 100644 --- a/src/map_name_popup.c +++ b/src/map_name_popup.c @@ -336,7 +336,7 @@ static void ShowMapNamePopUpWindow(void) u8 x; const u8 *mapDisplayHeaderSource; - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_TOP) { diff --git a/src/party_menu.c b/src/party_menu.c index f6dd6a264c..43f3529ea4 100755 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -3092,7 +3092,7 @@ static void CursorCb_Give(u8 taskId) static void CB2_SelectBagItemToGive(void) { - if (InBattlePyramid() == FALSE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE == FALSE) GoToBagMenu(ITEMMENULOCATION_PARTY, POCKETS_COUNT, CB2_GiveHoldItem); else GoToBattlePyramidBagMenu(PYRAMIDBAG_LOC_PARTY, CB2_GiveHoldItem); @@ -4275,7 +4275,7 @@ void CB2_ShowPartyMenuForItemUse(void) static void CB2_ReturnToBagMenu(void) { - if (InBattlePyramid() == FALSE) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE == FALSE) GoToBagMenu(ITEMMENULOCATION_LAST, POCKETS_COUNT, NULL); else GoToBattlePyramidBagMenu(PYRAMIDBAG_LOC_PREV, gPyramidBagMenuState.exitCallback); @@ -5358,7 +5358,7 @@ void CB2_PartyMenuFromStartMenu(void) // As opposted to by selecting Give in the party menu, which is handled by CursorCb_Give void CB2_ChooseMonToGiveItem(void) { - MainCallback callback = (!InBattlePyramid()) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; + MainCallback callback = (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) ? CB2_ReturnToBagMenu : CB2_ReturnToPyramidBagMenu; InitPartyMenu(PARTY_MENU_TYPE_FIELD, PARTY_LAYOUT_SINGLE, PARTY_ACTION_GIVE_ITEM, FALSE, PARTY_MSG_GIVE_TO_WHICH_MON, Task_HandleChooseMonInput, callback); gPartyMenu.bagItem = gSpecialVar_ItemId; } diff --git a/src/pokemon.c b/src/pokemon.c index e98182b0ae..8ec0c1a32c 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5840,7 +5840,7 @@ s32 GetBattlerMultiplayerId(u16 id) u8 GetTrainerEncounterMusicId(u16 trainerOpponentId) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return GetTrainerEncounterMusicIdInBattlePyramid(trainerOpponentId); else if (InTrainerHillChallenge()) return GetTrainerEncounterMusicIdInTrainerHill(trainerOpponentId); @@ -6970,7 +6970,7 @@ static bool8 ShouldSkipFriendshipChange(void) { if (gMain.inBattle && gBattleTypeFlags & (BATTLE_TYPE_FRONTIER)) return TRUE; - if (!gMain.inBattle && (InBattlePike() || InBattlePyramid())) + if (!gMain.inBattle && (InBattlePike() || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE)) return TRUE; return FALSE; } diff --git a/src/start_menu.c b/src/start_menu.c index 0910fad84d..13a46c51c6 100644 --- a/src/start_menu.c +++ b/src/start_menu.c @@ -293,7 +293,7 @@ static void BuildStartMenuActions(void) { BuildBattlePikeStartMenu(); } - else if (InBattlePyramid()) + else if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { BuildBattlePyramidStartMenu(); } @@ -439,7 +439,7 @@ static void RemoveExtraStartMenuWindows(void) CopyWindowToVram(sSafariBallsWindowId, COPYWIN_GFX); RemoveWindow(sSafariBallsWindowId); } - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { ClearStdWindowAndFrameToTransparent(sBattlePyramidFloorWindowId, FALSE); RemoveWindow(sBattlePyramidFloorWindowId); @@ -499,7 +499,7 @@ static bool32 InitStartMenuStep(void) case 3: if (GetSafariZoneFlag()) ShowSafariBallsWindow(); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) ShowPyramidFloorWindow(); sInitStartMenuData[0]++; break; @@ -720,7 +720,7 @@ static bool8 StartMenuPlayerNameCallback(void) static bool8 StartMenuSaveCallback(void) { - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) RemoveExtraStartMenuWindows(); gMenuCallback = SaveStartCallback; // Display save menu @@ -981,7 +981,7 @@ static u8 SaveConfirmSaveCallback(void) RemoveStartMenuWindow(); ShowSaveInfoWindow(); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { ShowSaveMessage(gText_BattlePyramidConfirmRest, SaveYesNoCallback); } diff --git a/src/trainer_see.c b/src/trainer_see.c index 212cbbdec3..a87ed496bc 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -256,7 +256,7 @@ static u8 CheckTrainer(u8 objectEventId) else scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); - if (InBattlePyramid()) + if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) { if (GetBattlePyramidTrainerFlag(objectEventId)) return 0; diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 11d01f04ea..211729dc4e 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -851,7 +851,7 @@ bool8 UpdateRepelCounter(void) { u16 steps; - if (InBattlePike() || InBattlePyramid()) + if (InBattlePike() || CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE) return FALSE; if (InUnionRoom() == TRUE) return FALSE; From 2a656ff1a54e13c3155e821ad2072f69bc0ef32e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 27 Dec 2024 12:40:25 -0300 Subject: [PATCH 03/31] Applied review changes --- src/field_poison.c | 2 +- src/item_use.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/field_poison.c b/src/field_poison.c index 4548933533..1b8ae94094 100644 --- a/src/field_poison.c +++ b/src/field_poison.c @@ -90,7 +90,7 @@ static void Task_TryFieldPoisonWhiteOut(u8 taskId) { // Battle facilities have their own white out script to handle the challenge loss #ifdef BUGFIX - if (CurrentBattlePyramidLocation() != PYRAMID_LOCATION_NONE || InBattlePike() || InTrainerHillChallenge()) + if (CurrentBattlePyramidLocation() || InBattlePike() || InTrainerHillChallenge()) #else if (CurrentBattlePyramidLocation() | InBattlePike() || InTrainerHillChallenge()) #endif diff --git a/src/item_use.c b/src/item_use.c index dd017ee170..29cf7ee5cc 100755 --- a/src/item_use.c +++ b/src/item_use.c @@ -983,7 +983,7 @@ static void Task_UseStatIncreaseItem(u8 taskId) { PlaySE(SE_USE_ITEM); RemoveBagItem(gSpecialVar_ItemId, 1); - if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) // CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE doesn't match + if (CurrentBattlePyramidLocation() == PYRAMID_LOCATION_NONE) DisplayItemMessage(taskId, FONT_NORMAL, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); else DisplayItemMessageInBattlePyramid(taskId, UseStatIncreaseItem(gSpecialVar_ItemId), Task_CloseStatIncreaseMessage); From 56bd65eb9d3dfbd0d7fc19ec7f08b45bb0affe03 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 27 Apr 2025 22:28:26 -0400 Subject: [PATCH 04/31] Fix other missing instances of MAX_LINK_PLAYERS --- src/battle_bg.c | 2 +- src/battle_controllers.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/battle_bg.c b/src/battle_bg.c index c32f5ec623..cc9f4a15ee 100644 --- a/src/battle_bg.c +++ b/src/battle_bg.c @@ -1024,7 +1024,7 @@ void InitLinkBattleVsScreen(u8 taskId) case 0: if (gBattleTypeFlags & BATTLE_TYPE_MULTI) { - for (i = 0; i < MAX_BATTLERS_COUNT; i++) + for (i = 0; i < MAX_LINK_PLAYERS; i++) { name = gLinkPlayers[i].name; linkPlayer = &gLinkPlayers[i]; diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 02276a7e14..4b19e62e5a 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -260,7 +260,7 @@ static void InitSinglePlayerBtlControllers(void) { u8 multiplayerId; - for (multiplayerId = gRecordedBattleMultiplayerId, i = 0; i < MAX_BATTLERS_COUNT; i++) + for (multiplayerId = gRecordedBattleMultiplayerId, i = 0; i < MAX_LINK_PLAYERS; i++) { switch (gLinkPlayers[i].id) { @@ -502,7 +502,7 @@ static void InitLinkBtlControllers(void) if (gBattleTypeFlags & BATTLE_TYPE_IS_MASTER) gBattleMainFunc = BeginBattleIntro; - for (i = 0; i < MAX_BATTLERS_COUNT; i++) + for (i = 0; i < MAX_LINK_PLAYERS; i++) { switch (gLinkPlayers[i].id) { From 2cc013ff3e3e89d380fe434795a62ece1fc62dbc Mon Sep 17 00:00:00 2001 From: Catnip-Consumer Date: Mon, 28 Apr 2025 14:36:19 +0300 Subject: [PATCH 05/31] Apply fixes to preproc for Windows compatibility --- tools/preproc/asm_file.cpp | 8 ++++---- tools/preproc/preproc.cpp | 10 ++++++++++ 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/tools/preproc/asm_file.cpp b/tools/preproc/asm_file.cpp index a82354cb5f..69b412b24e 100644 --- a/tools/preproc/asm_file.cpp +++ b/tools/preproc/asm_file.cpp @@ -679,7 +679,7 @@ void AsmFile::RaiseWarning(const char* format, ...) int AsmFile::SkipWhitespaceAndEol() { int newlines = 0; - while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\n') + while (m_buffer[m_pos] == '\t' || m_buffer[m_pos] == ' ' || m_buffer[m_pos] == '\r' || m_buffer[m_pos] == '\n') { if (m_buffer[m_pos] == '\n') newlines++; @@ -702,14 +702,14 @@ int AsmFile::FindLastLineNumber(std::string& filename) if (pos < 0) RaiseError("line indicator for header file not found before `enum`"); - + pos++; while (m_buffer[pos] == ' ' || m_buffer[pos] == '\t') pos++; if (!IsAsciiDigit(m_buffer[pos])) RaiseError("malformatted line indicator found before `enum`, expected line number"); - + unsigned n = 0; int digit = 0; while ((digit = ConvertDigit(m_buffer[pos++], 10)) != -1) @@ -744,7 +744,7 @@ int AsmFile::FindLastLineNumber(std::string& filename) filename += c; } - + return n + linebreaks - 1; } diff --git a/tools/preproc/preproc.cpp b/tools/preproc/preproc.cpp index 20c2de51b6..ac9496d701 100644 --- a/tools/preproc/preproc.cpp +++ b/tools/preproc/preproc.cpp @@ -26,6 +26,11 @@ #include "c_file.h" #include "charmap.h" +#ifdef _WIN32 +#include +#include +#endif + static void UsageAndExit(const char *program); Charmap* g_charmap; @@ -179,6 +184,11 @@ int main(int argc, char **argv) g_charmap = new Charmap(charmap); +#ifdef _WIN32 + // On Windows, piping from stdout can break newlines. Treat stdout as binary stream to avoid this. + _setmode(_fileno(stdout), _O_BINARY); +#endif + const char* extension = GetFileExtension(source); if (!extension) From 50d81616cd3db3d2b7534ed936b0d3541e5a08cb Mon Sep 17 00:00:00 2001 From: GriffinR Date: Tue, 10 Jun 2025 13:05:03 -0400 Subject: [PATCH 06/31] Relax MAPSEC region map data requirements --- .../region_map/region_map_sections.json.txt | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/data/region_map/region_map_sections.json.txt b/src/data/region_map/region_map_sections.json.txt index b73f992d6d..c3435d2d67 100644 --- a/src/data/region_map/region_map_sections.json.txt +++ b/src/data/region_map/region_map_sections.json.txt @@ -19,9 +19,23 @@ static const u8 sMapName_{{ cleanString(map_section.name) }}_Clone[] = _("{{ map const struct RegionMapLocation gRegionMapEntries[] = { ## for map_section in map_sections -{% if existsIn(map_section, "x") and existsIn(map_section, "y") and existsIn(map_section, "width") and existsIn(map_section, "height") and existsIn(map_section, "name") %} - [{{ map_section.id }}] = { {{ map_section.x }}, {{ map_section.y }}, {{ map_section.width }}, {{ map_section.height }}, sMapName_{{ cleanString(map_section.name) }}{% if existsIn(map_section, "name_clone") %}_Clone{% endif %} }, + [{{ map_section.id }}] = { +{% if existsIn(map_section, "x") %} + .x = {{ map_section.x }}, {% endif %} +{% if existsIn(map_section, "y") %} + .y = {{ map_section.y }}, +{% endif %} +{% if existsIn(map_section, "width") %} + .width = {{ map_section.width }}, +{% endif %} +{% if existsIn(map_section, "height") %} + .height = {{ map_section.height }}, +{% endif %} +{% if existsIn(map_section, "name") %} + .name = sMapName_{{ cleanString(map_section.name) }}{% if existsIn(map_section, "name_clone") %}_Clone{% endif %}, +{% endif %} + }, ## endfor }; From 64a6e8817cb143c4f6d81d7ba6bfb6486b156a81 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 25 Jun 2025 18:54:13 +0200 Subject: [PATCH 07/31] Fix sGpuRegBuffer potential alignment issues (#2157) --- src/gpu_regs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gpu_regs.c b/src/gpu_regs.c index 3bcc4fd931..d645c1442d 100644 --- a/src/gpu_regs.c +++ b/src/gpu_regs.c @@ -8,7 +8,7 @@ #define EMPTY_SLOT 0xFF -static u8 sGpuRegBuffer[GPU_REG_BUF_SIZE]; +static ALIGNED(2) u8 sGpuRegBuffer[GPU_REG_BUF_SIZE]; // sGpuRegBuffer is read as u16 so it needs to be properly aligned static u8 sGpuRegWaitingList[GPU_REG_BUF_SIZE]; static volatile bool8 sGpuRegBufferLocked; static volatile bool8 sShouldSyncRegIE; From 9df5ab16e8a11f289747dcf41abd4a8e8b6d42e0 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 25 Jun 2025 20:41:23 +0200 Subject: [PATCH 08/31] Ensure sMonMarkings_Gfx alignment (#2158) --- src/mon_markings.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mon_markings.c b/src/mon_markings.c index d7a61c27e7..1de8e413fd 100644 --- a/src/mon_markings.c +++ b/src/mon_markings.c @@ -23,7 +23,7 @@ static void SpriteCB_Cursor(struct Sprite *); static struct Sprite *CreateMarkingComboSprite(u16, u16, const u16 *, u16); static const u16 sMonMarkings_Pal[] = INCBIN_U16("graphics/interface/mon_markings.gbapal"); -static const u8 sMonMarkings_Gfx[] = INCBIN_U8("graphics/interface/mon_markings.4bpp"); +static const ALIGNED(4) u8 sMonMarkings_Gfx[] = INCBIN_U8("graphics/interface/mon_markings.4bpp"); // Alignment needed for dma copy static const struct OamData sOamData_MenuWindow = { From 44c30698951d66788029ad41a2e3254ff3ffb023 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Thu, 26 Jun 2025 16:22:09 -0400 Subject: [PATCH 09/31] Add explicit defaults for MAPSEC data --- src/data/region_map/region_map_sections.json | 708 +++--------------- .../region_map/region_map_sections.json.txt | 10 + 2 files changed, 128 insertions(+), 590 deletions(-) diff --git a/src/data/region_map/region_map_sections.json b/src/data/region_map/region_map_sections.json index fa7eb5efa4..49426128b8 100644 --- a/src/data/region_map/region_map_sections.json +++ b/src/data/region_map/region_map_sections.json @@ -675,11 +675,7 @@ }, { "id": "MAPSEC_INSIDE_OF_TRUCK", - "name": "INSIDE OF TRUCK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "INSIDE OF TRUCK" }, { "id": "MAPSEC_SKY_PILLAR", @@ -691,897 +687,453 @@ }, { "id": "MAPSEC_SECRET_BASE", - "name": "SECRET BASE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SECRET BASE" }, { "id": "MAPSEC_DYNAMIC", - "name": "", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "" }, { "id": "MAPSEC_PALLET_TOWN", - "name": "PALLET TOWN", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "PALLET TOWN" }, { "id": "MAPSEC_VIRIDIAN_CITY", - "name": "VIRIDIAN CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VIRIDIAN CITY" }, { "id": "MAPSEC_PEWTER_CITY", - "name": "PEWTER CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "PEWTER CITY" }, { "id": "MAPSEC_CERULEAN_CITY", - "name": "CERULEAN CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CERULEAN CITY" }, { "id": "MAPSEC_LAVENDER_TOWN", - "name": "LAVENDER TOWN", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "LAVENDER TOWN" }, { "id": "MAPSEC_VERMILION_CITY", - "name": "VERMILION CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VERMILION CITY" }, { "id": "MAPSEC_CELADON_CITY", - "name": "CELADON CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CELADON CITY" }, { "id": "MAPSEC_FUCHSIA_CITY", - "name": "FUCHSIA CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FUCHSIA CITY" }, { "id": "MAPSEC_CINNABAR_ISLAND", - "name": "CINNABAR ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CINNABAR ISLAND" }, { "id": "MAPSEC_INDIGO_PLATEAU", - "name": "INDIGO PLATEAU", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "INDIGO PLATEAU" }, { "id": "MAPSEC_SAFFRON_CITY", - "name": "SAFFRON CITY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SAFFRON CITY" }, { "id": "MAPSEC_ROUTE_4_POKECENTER", "name": "ROUTE 4", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_ROUTE_10_POKECENTER", "name": "ROUTE 10", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_ROUTE_1", - "name": "ROUTE 1", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 1" }, { "id": "MAPSEC_ROUTE_2", - "name": "ROUTE 2", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 2" }, { "id": "MAPSEC_ROUTE_3", - "name": "ROUTE 3", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 3" }, { "id": "MAPSEC_ROUTE_4", - "name": "ROUTE 4", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 4" }, { "id": "MAPSEC_ROUTE_5", - "name": "ROUTE 5", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 5" }, { "id": "MAPSEC_ROUTE_6", - "name": "ROUTE 6", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 6" }, { "id": "MAPSEC_ROUTE_7", - "name": "ROUTE 7", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 7" }, { "id": "MAPSEC_ROUTE_8", - "name": "ROUTE 8", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 8" }, { "id": "MAPSEC_ROUTE_9", - "name": "ROUTE 9", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 9" }, { "id": "MAPSEC_ROUTE_10", - "name": "ROUTE 10", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 10" }, { "id": "MAPSEC_ROUTE_11", - "name": "ROUTE 11", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 11" }, { "id": "MAPSEC_ROUTE_12", - "name": "ROUTE 12", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 12" }, { "id": "MAPSEC_ROUTE_13", - "name": "ROUTE 13", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 13" }, { "id": "MAPSEC_ROUTE_14", - "name": "ROUTE 14", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 14" }, { "id": "MAPSEC_ROUTE_15", - "name": "ROUTE 15", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 15" }, { "id": "MAPSEC_ROUTE_16", - "name": "ROUTE 16", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 16" }, { "id": "MAPSEC_ROUTE_17", - "name": "ROUTE 17", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 17" }, { "id": "MAPSEC_ROUTE_18", - "name": "ROUTE 18", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 18" }, { "id": "MAPSEC_ROUTE_19", - "name": "ROUTE 19", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 19" }, { "id": "MAPSEC_ROUTE_20", - "name": "ROUTE 20", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 20" }, { "id": "MAPSEC_ROUTE_21", - "name": "ROUTE 21", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 21" }, { "id": "MAPSEC_ROUTE_22", - "name": "ROUTE 22", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 22" }, { "id": "MAPSEC_ROUTE_23", - "name": "ROUTE 23", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 23" }, { "id": "MAPSEC_ROUTE_24", - "name": "ROUTE 24", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 24" }, { "id": "MAPSEC_ROUTE_25", - "name": "ROUTE 25", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROUTE 25" }, { "id": "MAPSEC_VIRIDIAN_FOREST", - "name": "VIRIDIAN FOREST", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VIRIDIAN FOREST" }, { "id": "MAPSEC_MT_MOON", - "name": "MT. MOON", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MT. MOON" }, { "id": "MAPSEC_S_S_ANNE", - "name": "S.S. ANNE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "S.S. ANNE" }, { "id": "MAPSEC_UNDERGROUND_PATH", - "name": "UNDERGROUND PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "UNDERGROUND PATH" }, { "id": "MAPSEC_UNDERGROUND_PATH_2", "name": "UNDERGROUND PATH", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_DIGLETTS_CAVE", - "name": "DIGLETT'S CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "DIGLETT'S CAVE" }, { "id": "MAPSEC_KANTO_VICTORY_ROAD", "name": "VICTORY ROAD", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_ROCKET_HIDEOUT", - "name": "ROCKET HIDEOUT", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROCKET HIDEOUT" }, { "id": "MAPSEC_SILPH_CO", - "name": "SILPH CO.", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SILPH CO." }, { "id": "MAPSEC_POKEMON_MANSION", - "name": "POKéMON MANSION", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POKéMON MANSION" }, { "id": "MAPSEC_KANTO_SAFARI_ZONE", "name": "SAFARI ZONE", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_POKEMON_LEAGUE", - "name": "POKéMON LEAGUE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POKéMON LEAGUE" }, { "id": "MAPSEC_ROCK_TUNNEL", - "name": "ROCK TUNNEL", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROCK TUNNEL" }, { "id": "MAPSEC_SEAFOAM_ISLANDS", - "name": "SEAFOAM ISLANDS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEAFOAM ISLANDS" }, { "id": "MAPSEC_POKEMON_TOWER", - "name": "POKéMON TOWER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POKéMON TOWER" }, { "id": "MAPSEC_CERULEAN_CAVE", - "name": "CERULEAN CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CERULEAN CAVE" }, { "id": "MAPSEC_POWER_PLANT", - "name": "POWER PLANT", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "POWER PLANT" }, { "id": "MAPSEC_ONE_ISLAND", - "name": "ONE ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ONE ISLAND" }, { "id": "MAPSEC_TWO_ISLAND", - "name": "TWO ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TWO ISLAND" }, { "id": "MAPSEC_THREE_ISLAND", - "name": "THREE ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "THREE ISLAND" }, { "id": "MAPSEC_FOUR_ISLAND", - "name": "FOUR ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FOUR ISLAND" }, { "id": "MAPSEC_FIVE_ISLAND", - "name": "FIVE ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FIVE ISLAND" }, { "id": "MAPSEC_SEVEN_ISLAND", - "name": "SEVEN ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVEN ISLAND" }, { "id": "MAPSEC_SIX_ISLAND", - "name": "SIX ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SIX ISLAND" }, { "id": "MAPSEC_KINDLE_ROAD", - "name": "KINDLE ROAD", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "KINDLE ROAD" }, { "id": "MAPSEC_TREASURE_BEACH", - "name": "TREASURE BEACH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TREASURE BEACH" }, { "id": "MAPSEC_CAPE_BRINK", - "name": "CAPE BRINK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CAPE BRINK" }, { "id": "MAPSEC_BOND_BRIDGE", - "name": "BOND BRIDGE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BOND BRIDGE" }, { "id": "MAPSEC_THREE_ISLE_PORT", - "name": "THREE ISLE PORT", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "THREE ISLE PORT" }, { "id": "MAPSEC_SEVII_ISLE_6", - "name": "SEVII ISLE 6", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 6" }, { "id": "MAPSEC_SEVII_ISLE_7", - "name": "SEVII ISLE 7", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 7" }, { "id": "MAPSEC_SEVII_ISLE_8", - "name": "SEVII ISLE 8", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 8" }, { "id": "MAPSEC_SEVII_ISLE_9", - "name": "SEVII ISLE 9", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 9" }, { "id": "MAPSEC_RESORT_GORGEOUS", - "name": "RESORT GORGEOUS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "RESORT GORGEOUS" }, { "id": "MAPSEC_WATER_LABYRINTH", - "name": "WATER LABYRINTH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "WATER LABYRINTH" }, { "id": "MAPSEC_FIVE_ISLE_MEADOW", - "name": "FIVE ISLE MEADOW", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FIVE ISLE MEADOW" }, { "id": "MAPSEC_MEMORIAL_PILLAR", - "name": "MEMORIAL PILLAR", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MEMORIAL PILLAR" }, { "id": "MAPSEC_OUTCAST_ISLAND", - "name": "OUTCAST ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "OUTCAST ISLAND" }, { "id": "MAPSEC_GREEN_PATH", - "name": "GREEN PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "GREEN PATH" }, { "id": "MAPSEC_WATER_PATH", - "name": "WATER PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "WATER PATH" }, { "id": "MAPSEC_RUIN_VALLEY", - "name": "RUIN VALLEY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "RUIN VALLEY" }, { "id": "MAPSEC_TRAINER_TOWER", - "name": "TRAINER TOWER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TRAINER TOWER" }, { "id": "MAPSEC_CANYON_ENTRANCE", - "name": "CANYON ENTRANCE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "CANYON ENTRANCE" }, { "id": "MAPSEC_SEVAULT_CANYON", - "name": "SEVAULT CANYON", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVAULT CANYON" }, { "id": "MAPSEC_TANOBY_RUINS", - "name": "TANOBY RUINS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TANOBY RUINS" }, { "id": "MAPSEC_SEVII_ISLE_22", - "name": "SEVII ISLE 22", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 22" }, { "id": "MAPSEC_SEVII_ISLE_23", - "name": "SEVII ISLE 23", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 23" }, { "id": "MAPSEC_SEVII_ISLE_24", - "name": "SEVII ISLE 24", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SEVII ISLE 24" }, { "id": "MAPSEC_NAVEL_ROCK_FRLG", - "name": "NAVEL ROCK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "NAVEL ROCK" }, { "id": "MAPSEC_MT_EMBER", - "name": "MT. EMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MT. EMBER" }, { "id": "MAPSEC_BERRY_FOREST", - "name": "BERRY FOREST", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BERRY FOREST" }, { "id": "MAPSEC_ICEFALL_CAVE", - "name": "ICEFALL CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ICEFALL CAVE" }, { "id": "MAPSEC_ROCKET_WAREHOUSE", - "name": "ROCKET WAREHOUSE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ROCKET WAREHOUSE" }, { "id": "MAPSEC_TRAINER_TOWER_2", "name": "TRAINER TOWER", - "name_clone": true, - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name_clone": true }, { "id": "MAPSEC_DOTTED_HOLE", - "name": "DOTTED HOLE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "DOTTED HOLE" }, { "id": "MAPSEC_LOST_CAVE", - "name": "LOST CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "LOST CAVE" }, { "id": "MAPSEC_PATTERN_BUSH", - "name": "PATTERN BUSH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "PATTERN BUSH" }, { "id": "MAPSEC_ALTERING_CAVE_FRLG", - "name": "ALTERING CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "ALTERING CAVE" }, { "id": "MAPSEC_TANOBY_CHAMBERS", - "name": "TANOBY CHAMBERS", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TANOBY CHAMBERS" }, { "id": "MAPSEC_THREE_ISLE_PATH", - "name": "THREE ISLE PATH", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "THREE ISLE PATH" }, { "id": "MAPSEC_TANOBY_KEY", - "name": "TANOBY KEY", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TANOBY KEY" }, { "id": "MAPSEC_BIRTH_ISLAND_FRLG", - "name": "BIRTH ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BIRTH ISLAND" }, { "id": "MAPSEC_MONEAN_CHAMBER", - "name": "MONEAN CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MONEAN CHAMBER" }, { "id": "MAPSEC_LIPTOO_CHAMBER", - "name": "LIPTOO CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "LIPTOO CHAMBER" }, { "id": "MAPSEC_WEEPTH_CHAMBER", - "name": "WEEPTH CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "WEEPTH CHAMBER" }, { "id": "MAPSEC_DILFORD_CHAMBER", - "name": "DILFORD CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "DILFORD CHAMBER" }, { "id": "MAPSEC_SCUFIB_CHAMBER", - "name": "SCUFIB CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SCUFIB CHAMBER" }, { "id": "MAPSEC_RIXY_CHAMBER", - "name": "RIXY CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "RIXY CHAMBER" }, { "id": "MAPSEC_VIAPOIS_CHAMBER", - "name": "VIAPOIS CHAMBER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "VIAPOIS CHAMBER" }, { "id": "MAPSEC_EMBER_SPA", - "name": "EMBER SPA", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "EMBER SPA" }, { "id": "MAPSEC_SPECIAL_AREA", - "name": "SPECIAL AREA", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "SPECIAL AREA" }, { "id": "MAPSEC_AQUA_HIDEOUT", @@ -1609,19 +1161,11 @@ }, { "id": "MAPSEC_BIRTH_ISLAND", - "name": "BIRTH ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "BIRTH ISLAND" }, { "id": "MAPSEC_FARAWAY_ISLAND", - "name": "FARAWAY ISLAND", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "FARAWAY ISLAND" }, { "id": "MAPSEC_ARTISAN_CAVE", @@ -1633,27 +1177,15 @@ }, { "id": "MAPSEC_MARINE_CAVE", - "name": "MARINE CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "MARINE CAVE" }, { "id": "MAPSEC_UNDERWATER_MARINE_CAVE", - "name": "UNDERWATER", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "UNDERWATER" }, { "id": "MAPSEC_TERRA_CAVE", - "name": "TERRA CAVE", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "TERRA CAVE" }, { "id": "MAPSEC_UNDERWATER_105", @@ -1697,11 +1229,7 @@ }, { "id": "MAPSEC_NAVEL_ROCK", - "name": "NAVEL ROCK", - "x": 0, - "y": 0, - "width": 1, - "height": 1 + "name": "NAVEL ROCK" }, { "id": "MAPSEC_TRAINER_HILL", diff --git a/src/data/region_map/region_map_sections.json.txt b/src/data/region_map/region_map_sections.json.txt index c3435d2d67..0da2d31794 100644 --- a/src/data/region_map/region_map_sections.json.txt +++ b/src/data/region_map/region_map_sections.json.txt @@ -22,18 +22,28 @@ const struct RegionMapLocation gRegionMapEntries[] = { [{{ map_section.id }}] = { {% if existsIn(map_section, "x") %} .x = {{ map_section.x }}, +{% else %} + .x = 0, {% endif %} {% if existsIn(map_section, "y") %} .y = {{ map_section.y }}, +{% else %} + .y = 0, {% endif %} {% if existsIn(map_section, "width") %} .width = {{ map_section.width }}, +{% else %} + .width = 1, {% endif %} {% if existsIn(map_section, "height") %} .height = {{ map_section.height }}, +{% else %} + .height = 1, {% endif %} {% if existsIn(map_section, "name") %} .name = sMapName_{{ cleanString(map_section.name) }}{% if existsIn(map_section, "name_clone") %}_Clone{% endif %}, +{% else %} + .name = (const u8[])_(""), {% endif %} }, ## endfor From 80b9c23d0af9cdde79fa2cd6a539f7e1a144d96d Mon Sep 17 00:00:00 2001 From: Raymond Dodge Date: Sun, 6 Jul 2025 13:49:47 -0400 Subject: [PATCH 10/31] Fix RL compressed data alignment `RLUnComp`, like `LZ77UnComp`, expects the source data to be word-aligned. So, to mirror how lz-compressed data is defined as `u32[]` to enforce word-alignment, this changes rl-compressed data to be defined as `u32[]` to enforce word-alignment. --- include/gba/syscall.h | 4 ++-- src/contest_painting.c | 26 +++++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/include/gba/syscall.h b/include/gba/syscall.h index c922084d5f..50f5781988 100644 --- a/include/gba/syscall.h +++ b/include/gba/syscall.h @@ -61,9 +61,9 @@ void LZ77UnCompWram(const u32 *src, void *dest); void LZ77UnCompVram(const u32 *src, void *dest); -void RLUnCompWram(const void *src, void *dest); +void RLUnCompWram(const u32 *src, void *dest); -void RLUnCompVram(const void *src, void *dest); +void RLUnCompVram(const u32 *src, void *dest); int MultiBoot(struct MultiBootParam *mp); diff --git a/src/contest_painting.c b/src/contest_painting.c index c72d0dc6af..e12fa4c4d7 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -69,19 +69,19 @@ extern const u8 gContestPaintingTough1[]; extern const u8 gContestPaintingTough2[]; extern const u8 gContestPaintingTough3[]; -static const u16 sPictureFramePalettes[] = INCBIN_U16("graphics/picture_frame/bg.gbapal"); -static const u8 sPictureFrameTiles_Cool[] = INCBIN_U8("graphics/picture_frame/cool.4bpp.rl"); -static const u8 sPictureFrameTiles_Beauty[] = INCBIN_U8("graphics/picture_frame/beauty.4bpp.rl"); -static const u8 sPictureFrameTiles_Cute[] = INCBIN_U8("graphics/picture_frame/cute.4bpp.rl"); -static const u8 sPictureFrameTiles_Smart[] = INCBIN_U8("graphics/picture_frame/smart.4bpp.rl"); -static const u8 sPictureFrameTiles_Tough[] = INCBIN_U8("graphics/picture_frame/tough.4bpp.rl"); -static const u8 sPictureFrameTiles_HallLobby[] = INCBIN_U8("graphics/picture_frame/lobby.4bpp.rl"); -static const u8 sPictureFrameTilemap_Cool[] = INCBIN_U8("graphics/picture_frame/cool_map.bin.rl"); -static const u8 sPictureFrameTilemap_Beauty[] = INCBIN_U8("graphics/picture_frame/beauty_map.bin.rl"); -static const u8 sPictureFrameTilemap_Cute[] = INCBIN_U8("graphics/picture_frame/cute_map.bin.rl"); -static const u8 sPictureFrameTilemap_Smart[] = INCBIN_U8("graphics/picture_frame/smart_map.bin.rl"); -static const u8 sPictureFrameTilemap_Tough[] = INCBIN_U8("graphics/picture_frame/tough_map.bin.rl"); -static const u8 sPictureFrameTilemap_HallLobby[] = INCBIN_U8("graphics/picture_frame/lobby_map.bin.rl"); +static const u16 sPictureFramePalettes[] = INCBIN_U16("graphics/picture_frame/bg.gbapal"); +static const u32 sPictureFrameTiles_Cool[] = INCBIN_U32("graphics/picture_frame/cool.4bpp.rl"); +static const u32 sPictureFrameTiles_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty.4bpp.rl"); +static const u32 sPictureFrameTiles_Cute[] = INCBIN_U32("graphics/picture_frame/cute.4bpp.rl"); +static const u32 sPictureFrameTiles_Smart[] = INCBIN_U32("graphics/picture_frame/smart.4bpp.rl"); +static const u32 sPictureFrameTiles_Tough[] = INCBIN_U32("graphics/picture_frame/tough.4bpp.rl"); +static const u32 sPictureFrameTiles_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby.4bpp.rl"); +static const u32 sPictureFrameTilemap_Cool[] = INCBIN_U32("graphics/picture_frame/cool_map.bin.rl"); +static const u32 sPictureFrameTilemap_Beauty[] = INCBIN_U32("graphics/picture_frame/beauty_map.bin.rl"); +static const u32 sPictureFrameTilemap_Cute[] = INCBIN_U32("graphics/picture_frame/cute_map.bin.rl"); +static const u32 sPictureFrameTilemap_Smart[] = INCBIN_U32("graphics/picture_frame/smart_map.bin.rl"); +static const u32 sPictureFrameTilemap_Tough[] = INCBIN_U32("graphics/picture_frame/tough_map.bin.rl"); +static const u32 sPictureFrameTilemap_HallLobby[] = INCBIN_U32("graphics/picture_frame/lobby_map.bin.rl"); static const u8 *const sContestCategoryNames_Unused[] = { From e63e89e2704abf7b8515c20b0c8ada769b60ae6a Mon Sep 17 00:00:00 2001 From: Philipp AUER Date: Mon, 21 Jul 2025 19:33:44 +0200 Subject: [PATCH 11/31] Fix potential stack memory leak in gbagfx due to out of bounds read (#2162) * fix(tools): gbagfx potential oob read --------- Co-authored-by: sbird --- tools/gbagfx/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/gbagfx/main.c b/tools/gbagfx/main.c index 98a1a1edf9..497a869e14 100644 --- a/tools/gbagfx/main.c +++ b/tools/gbagfx/main.c @@ -333,6 +333,9 @@ void HandleJascToGbaPaletteCommand(char *inputPath, char *outputPath, int argc, if (numColors < 1) FATAL_ERROR("Number of colors must be positive.\n"); + + if (numColors > 255) + FATAL_ERROR("Number of colors must be less than 256.\n"); } else { From 6f8a1bbdb8a5ef75c4372cc625164a41e95ec2a4 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Wed, 23 Jul 2025 04:28:34 -0400 Subject: [PATCH 12/31] Add pack/unpack for data masks (#2163) --- include/global.fieldmap.h | 17 +++++++++++++ include/global.h | 3 +++ src/battle_pyramid.c | 1 + src/braille_puzzles.c | 12 +++++----- src/decoration.c | 21 ++++++++++++---- src/field_specials.c | 50 +++++++++++++++++++-------------------- src/fieldmap.c | 18 +++++++------- src/fldeff_escalator.c | 4 ++-- src/fldeff_misc.c | 8 +++---- src/scrcmd.c | 2 +- src/secret_base.c | 14 +++++------ src/trainer_hill.c | 12 +++++----- 12 files changed, 98 insertions(+), 64 deletions(-) diff --git a/include/global.fieldmap.h b/include/global.fieldmap.h index d3e260e192..1207bd80ea 100644 --- a/include/global.fieldmap.h +++ b/include/global.fieldmap.h @@ -7,19 +7,36 @@ #define MAPGRID_METATILE_ID_MASK 0x03FF // Bits 0-9 #define MAPGRID_COLLISION_MASK 0x0C00 // Bits 10-11 #define MAPGRID_ELEVATION_MASK 0xF000 // Bits 12-15 +#define MAPGRID_METATILE_ID_SHIFT 0 #define MAPGRID_COLLISION_SHIFT 10 #define MAPGRID_ELEVATION_SHIFT 12 +#define PACK_METATILE(metatileId) PACK(metatileId, MAPGRID_METATILE_ID_SHIFT, MAPGRID_METATILE_ID_MASK) +#define PACK_COLLISION(collision) PACK(collision, MAPGRID_COLLISION_SHIFT, MAPGRID_COLLISION_MASK) +#define PACK_ELEVATION(elevation) PACK(elevation, MAPGRID_ELEVATION_SHIFT, MAPGRID_ELEVATION_MASK) +#define UNPACK_METATILE(data) UNPACK(data, MAPGRID_METATILE_ID_SHIFT, MAPGRID_METATILE_ID_MASK) +#define UNPACK_COLLISION(data) UNPACK(data, MAPGRID_COLLISION_SHIFT, MAPGRID_COLLISION_MASK) +#define UNPACK_ELEVATION(data) UNPACK(data, MAPGRID_ELEVATION_SHIFT, MAPGRID_ELEVATION_MASK) + // An undefined map grid block has all metatile id bits set and nothing else #define MAPGRID_UNDEFINED MAPGRID_METATILE_ID_MASK +// When setting impassability manually GF sets all the collision bits +#define MAPGRID_IMPASSABLE MAPGRID_COLLISION_MASK + // Masks/shifts for metatile attributes // Metatile attributes consist of an 8 bit behavior value, 4 unused bits, and a 4 bit layer type value // This is the data stored in each data/tilesets/*/*/metatile_attributes.bin file #define METATILE_ATTR_BEHAVIOR_MASK 0x00FF // Bits 0-7 #define METATILE_ATTR_LAYER_MASK 0xF000 // Bits 12-15 +#define METATILE_ATTR_BEHAVIOR_SHIFT 0 #define METATILE_ATTR_LAYER_SHIFT 12 +#define PACK_BEHAVIOR(behavior) PACK(behavior, METATILE_ATTR_BEHAVIOR_SHIFT, METATILE_ATTR_BEHAVIOR_MASK) +#define PACK_LAYER_TYPE(layerType) PACK(layerType, METATILE_ATTR_LAYER_SHIFT, METATILE_ATTR_LAYER_MASK) +#define UNPACK_BEHAVIOR(data) UNPACK(data, METATILE_ATTR_BEHAVIOR_SHIFT, METATILE_ATTR_BEHAVIOR_MASK) +#define UNPACK_LAYER_TYPE(data) UNPACK(data, METATILE_ATTR_LAYER_SHIFT, METATILE_ATTR_LAYER_MASK) + enum { METATILE_LAYER_TYPE_NORMAL, // Metatile uses middle and top bg layers METATILE_LAYER_TYPE_COVERED, // Metatile uses bottom and middle bg layers diff --git a/include/global.h b/include/global.h index ad29e4897b..f0882710e5 100644 --- a/include/global.h +++ b/include/global.h @@ -119,6 +119,9 @@ #define T2_READ_32(ptr) ((ptr)[0] + ((ptr)[1] << 8) + ((ptr)[2] << 16) + ((ptr)[3] << 24)) #define T2_READ_PTR(ptr) (void *) T2_READ_32(ptr) +#define PACK(data, shift, mask) ( ((data) << (shift)) & (mask) ) +#define UNPACK(data, shift, mask) ( ((data) & (mask)) >> (shift) ) + // Macros for checking the joypad #define TEST_BUTTON(field, button) ((field) & (button)) #define JOY_NEW(button) TEST_BUTTON(gMain.newKeys, button) diff --git a/src/battle_pyramid.c b/src/battle_pyramid.c index d78cd38417..dc604a5207 100644 --- a/src/battle_pyramid.c +++ b/src/battle_pyramid.c @@ -1557,6 +1557,7 @@ void GenerateBattlePyramidFloorLayout(u16 *backupMapData, bool8 setPlayerPositio gSaveBlock1Ptr->pos.x = (mapLayout->width * (i % PYRAMID_FLOOR_SQUARES_WIDE)) + x; gSaveBlock1Ptr->pos.y = (mapLayout->height * (i / PYRAMID_FLOOR_SQUARES_WIDE)) + y; } + // Copy the elevation and collision, but overwrite the metatile ID map[x] = (layoutMap[x] & (MAPGRID_ELEVATION_MASK | MAPGRID_COLLISION_MASK)) | METATILE_BattlePyramid_Floor; } else diff --git a/src/braille_puzzles.c b/src/braille_puzzles.c index 28ed8cdf5f..7ac88091ef 100644 --- a/src/braille_puzzles.c +++ b/src/braille_puzzles.c @@ -80,9 +80,9 @@ void DoBrailleDigEffect(void) MapGridSetMetatileIdAt( 9 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopLeft); MapGridSetMetatileIdAt(10 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopMid); MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopRight); - MapGridSetMetatileIdAt( 9 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt( 9 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_IMPASSABLE); MapGridSetMetatileIdAt(10 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomMid); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_IMPASSABLE); DrawWholeMapView(); PlaySE(SE_BANG); FlagSet(FLAG_SYS_BRAILLE_DIG); @@ -207,9 +207,9 @@ static void DoBrailleRegirockEffect(void) MapGridSetMetatileIdAt(7 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopLeft); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopMid); MapGridSetMetatileIdAt(9 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopRight); - MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_IMPASSABLE); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomMid); - MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_IMPASSABLE); DrawWholeMapView(); PlaySE(SE_BANG); FlagSet(FLAG_SYS_REGIROCK_PUZZLE_COMPLETED); @@ -246,9 +246,9 @@ static void DoBrailleRegisteelEffect(void) MapGridSetMetatileIdAt(7 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopLeft); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopMid); MapGridSetMetatileIdAt(9 + MAP_OFFSET, 19 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_TopRight); - MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(7 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomLeft | MAPGRID_IMPASSABLE); MapGridSetMetatileIdAt(8 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomMid); - MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(9 + MAP_OFFSET, 20 + MAP_OFFSET, METATILE_Cave_SealedChamberEntrance_BottomRight | MAPGRID_IMPASSABLE); DrawWholeMapView(); PlaySE(SE_BANG); FlagSet(FLAG_SYS_REGISTEEL_PUZZLE_COMPLETED); diff --git a/src/decoration.c b/src/decoration.c index 98c6dba176..2bb97893e1 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -1221,9 +1221,9 @@ static void ShowDecorationOnMap_(u16 mapX, u16 mapY, u8 decWidth, u8 decHeight, { x = mapX + i; attributes = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + gDecorations[decoration].tiles[j * decWidth + i]); - if (MetatileBehavior_IsSecretBaseImpassable(attributes & METATILE_ATTR_BEHAVIOR_MASK) == TRUE + if (MetatileBehavior_IsSecretBaseImpassable(UNPACK_BEHAVIOR(attributes)) == TRUE || (gDecorations[decoration].permission != DECORPERM_PASS_FLOOR && (attributes >> METATILE_ATTR_LAYER_SHIFT) != METATILE_LAYER_TYPE_NORMAL)) - impassableFlag = MAPGRID_COLLISION_MASK; + impassableFlag = MAPGRID_IMPASSABLE; else impassableFlag = 0; @@ -1514,6 +1514,17 @@ static bool8 IsFloorOrBoardAndHole(u16 behaviorAt, const struct Decoration *deco return FALSE; } +#ifdef BUGFIX +#define GetLayerType(tileId) UNPACK_LAYER_TYPE(GetMetatileAttributesById(tileId)) +#else +// This incompletely extracts the layer type data. The result is that comparisons against any nonzero +// value in the valid range always have the same result. +// Because GF only compares against 0 (METATILE_LAYER_TYPE_NORMAL) there are no ill effects and it's possible this +// is what they intended. We use the named constant for the comparisons, which implies you can use nonzero constants at +// those locations (which you can't), so to avoid this trap and keep the better documentation this is included as a bug fix. +#define GetLayerType(tileId) GetMetatileAttributesById(tileId) & METATILE_ATTR_LAYER_MASK +#endif + static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { u8 i; @@ -1538,7 +1549,7 @@ static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { curX = gTasks[taskId].tCursorX + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); - layerType = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ATTR_LAYER_MASK; + layerType = GetLayerType(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]); if (!IsFloorOrBoardAndHole(behaviorAt, decoration)) return FALSE; @@ -1559,7 +1570,7 @@ static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { curX = gTasks[taskId].tCursorX + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); - layerType = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]) & METATILE_ATTR_LAYER_MASK; + layerType = GetLayerType(NUM_TILES_IN_PRIMARY + decoration->tiles[(mapY - 1 - i) * mapX + j]); if (!MetatileBehavior_IsNormal(behaviorAt) && !IsSecretBaseTrainerSpot(behaviorAt, layerType)) return FALSE; @@ -1576,7 +1587,7 @@ static bool8 CanPlaceDecoration(u8 taskId, const struct Decoration *decoration) { curX = gTasks[taskId].tCursorX + j; behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); - layerType = GetMetatileAttributesById(NUM_TILES_IN_PRIMARY + decoration->tiles[j]) & METATILE_ATTR_LAYER_MASK; + layerType = GetLayerType(NUM_TILES_IN_PRIMARY + decoration->tiles[j]); if (!MetatileBehavior_IsNormal(behaviorAt) && !MetatileBehavior_IsSecretBaseNorthWall(behaviorAt)) return FALSE; diff --git a/src/field_specials.c b/src/field_specials.c index 98384d52ab..b92efa14ed 100644 --- a/src/field_specials.c +++ b/src/field_specials.c @@ -659,10 +659,10 @@ void MauvilleGymSetDefaultBarriers(void) MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH2_On); break; case METATILE_MauvilleGym_GreenBeamH3_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH3_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH3_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamH4_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH4_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamH4_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamH1_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH1_Off); @@ -683,37 +683,37 @@ void MauvilleGymSetDefaultBarriers(void) MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH2_On); break; case METATILE_MauvilleGym_RedBeamH3_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH3_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH3_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamH4_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH4_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH4_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamV2_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_FloorTile); break; case METATILE_MauvilleGym_RedBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamV2_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_FloorTile); break; case METATILE_MauvilleGym_PoleBottom_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV1_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV1_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_FloorTile: if (MapGridGetMetatileIdAt(x, y - 1) == METATILE_MauvilleGym_GreenBeamV1_On) - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV2_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_GreenBeamV2_On | MAPGRID_IMPASSABLE); else - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV2_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV2_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_PoleBottom_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV1_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamV1_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_PoleTop_Off: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleTop_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleTop_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_PoleTop_On: MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleTop_Off); @@ -764,10 +764,10 @@ void MauvilleGymDeactivatePuzzle(void) MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_RedBeamH4_Off); break; case METATILE_MauvilleGym_GreenBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_On | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_RedBeamV1_On: - MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_MauvilleGym_PoleBottom_Off | MAPGRID_IMPASSABLE); break; case METATILE_MauvilleGym_GreenBeamV2_On: case METATILE_MauvilleGym_RedBeamV2_On: @@ -876,8 +876,8 @@ static void PetalburgGymSetDoorMetatiles(u8 roomNumber, u16 metatileId) } for (i = 0; i < nDoors; i++) { - MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET, metatileId | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET + 1, (metatileId + METATILE_ROW_WIDTH) | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET, metatileId | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(doorCoordsX[i] + MAP_OFFSET, doorCoordsY[i] + MAP_OFFSET + 1, (metatileId + METATILE_ROW_WIDTH) | MAPGRID_IMPASSABLE); } DrawWholeMapView(); } @@ -1066,7 +1066,7 @@ static void PCTurnOnEffect_SetMetatile(s16 isScreenOn, s8 dx, s8 dy) else if (gSpecialVar_0x8004 == PC_LOCATION_MAYS_HOUSE) metatileId = METATILE_BrendansMaysHouse_MayPC_On; } - MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_IMPASSABLE); } // For this special, gSpecialVar_0x8004 is expected to be some PC_LOCATION_* value. @@ -1106,7 +1106,7 @@ static void PCTurnOffEffect(void) else if (gSpecialVar_0x8004 == PC_LOCATION_MAYS_HOUSE) metatileId = METATILE_BrendansMaysHouse_MayPC_Off; - MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gSaveBlock1Ptr->pos.x + dx + MAP_OFFSET, gSaveBlock1Ptr->pos.y + dy + MAP_OFFSET, metatileId | MAPGRID_IMPASSABLE); DrawWholeMapView(); } @@ -1138,14 +1138,14 @@ static void LotteryCornerComputerEffect(struct Task *task) if (task->tIsScreenOn) { // Screen is on, set it off - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_IMPASSABLE); } else { // Screen is off, set it on - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Flash | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Flash | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Flash | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Flash | MAPGRID_IMPASSABLE); } DrawWholeMapView(); @@ -1160,8 +1160,8 @@ static void LotteryCornerComputerEffect(struct Task *task) void EndLotteryCornerComputerEffect(void) { - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_COLLISION_MASK); - MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 1 + MAP_OFFSET, METATILE_Shop_Laptop1_Normal | MAPGRID_IMPASSABLE); + MapGridSetMetatileIdAt(11 + MAP_OFFSET, 2 + MAP_OFFSET, METATILE_Shop_Laptop2_Normal | MAPGRID_IMPASSABLE); DrawWholeMapView(); } @@ -1941,7 +1941,7 @@ static void Task_MoveElevatorWindowLights(u8 taskId) for (y = 0; y < ELEVATOR_WINDOW_HEIGHT; y++) { for (x = 0; x < ELEVATOR_WINDOW_WIDTH; x++) - MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Ascending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Ascending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_IMPASSABLE); } } else @@ -1950,7 +1950,7 @@ static void Task_MoveElevatorWindowLights(u8 taskId) for (y = 0; y < ELEVATOR_WINDOW_HEIGHT; y++) { for (x = 0; x < ELEVATOR_WINDOW_WIDTH; x++) - MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Descending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET + 1, y + MAP_OFFSET, sElevatorWindowTiles_Descending[y][tMoveCounter % ELEVATOR_LIGHT_STAGES] | MAPGRID_IMPASSABLE); } } DrawWholeMapView(); diff --git a/src/fieldmap.c b/src/fieldmap.c index 8c0e416f45..97db758caa 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -56,7 +56,7 @@ static bool8 IsCoordInIncomingConnectingMap(int coord, int srcMax, int destMax, i = (x + 1) & 1; \ i += ((y + 1) & 1) * 2; \ \ - block = gMapHeader.mapLayout->border[i] | MAPGRID_COLLISION_MASK; \ + block = gMapHeader.mapLayout->border[i] | MAPGRID_IMPASSABLE; \ }) #define AreCoordsWithinMapGridBounds(x, y) (x >= 0 && x < gBackupMapLayout.width && y >= 0 && y < gBackupMapLayout.height) @@ -349,7 +349,7 @@ u8 MapGridGetElevationAt(int x, int y) if (block == MAPGRID_UNDEFINED) return 0; - return block >> MAPGRID_ELEVATION_SHIFT; + return UNPACK_ELEVATION(block); } u8 MapGridGetCollisionAt(int x, int y) @@ -359,7 +359,7 @@ u8 MapGridGetCollisionAt(int x, int y) if (block == MAPGRID_UNDEFINED) return TRUE; - return (block & MAPGRID_COLLISION_MASK) >> MAPGRID_COLLISION_SHIFT; + return UNPACK_COLLISION(block); } u32 MapGridGetMetatileIdAt(int x, int y) @@ -367,21 +367,21 @@ u32 MapGridGetMetatileIdAt(int x, int y) u16 block = GetMapGridBlockAt(x, y); if (block == MAPGRID_UNDEFINED) - return GetBorderBlockAt(x, y) & MAPGRID_METATILE_ID_MASK; + return UNPACK_METATILE(GetBorderBlockAt(x, y)); - return block & MAPGRID_METATILE_ID_MASK; + return UNPACK_METATILE(block); } u32 MapGridGetMetatileBehaviorAt(int x, int y) { u16 metatile = MapGridGetMetatileIdAt(x, y); - return GetMetatileAttributesById(metatile) & METATILE_ATTR_BEHAVIOR_MASK; + return UNPACK_BEHAVIOR(GetMetatileAttributesById(metatile)); } u8 MapGridGetMetatileLayerTypeAt(int x, int y) { u16 metatile = MapGridGetMetatileIdAt(x, y); - return (GetMetatileAttributesById(metatile) & METATILE_ATTR_LAYER_MASK) >> METATILE_ATTR_LAYER_SHIFT; + return UNPACK_LAYER_TYPE(GetMetatileAttributesById(metatile)); } void MapGridSetMetatileIdAt(int x, int y, u16 metatile) @@ -390,6 +390,8 @@ void MapGridSetMetatileIdAt(int x, int y, u16 metatile) if (AreCoordsWithinMapGridBounds(x, y)) { i = x + y * gBackupMapLayout.width; + + // Elevation is ignored in the argument, but copy metatile ID and collision gBackupMapLayout.map[i] = (gBackupMapLayout.map[i] & MAPGRID_ELEVATION_MASK) | (metatile & ~MAPGRID_ELEVATION_MASK); } } @@ -832,7 +834,7 @@ static bool8 SkipCopyingMetatileFromSavedMap(u16 *mapBlock, u16 mapWidth, u8 yMo else mapBlock += mapWidth; - if (IsLargeBreakableDecoration(*mapBlock & MAPGRID_METATILE_ID_MASK, yMode) == TRUE) + if (IsLargeBreakableDecoration(UNPACK_METATILE(*mapBlock), yMode) == TRUE) return TRUE; return FALSE; } diff --git a/src/fldeff_escalator.c b/src/fldeff_escalator.c index eabbd53549..f49b97b0c8 100644 --- a/src/fldeff_escalator.c +++ b/src/fldeff_escalator.c @@ -126,13 +126,13 @@ static void Task_DrawEscalator(u8 taskId) SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_1, 0); break; case 2: - SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_2, MAPGRID_COLLISION_MASK); + SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_2, MAPGRID_IMPASSABLE); break; case 3: SetEscalatorMetatile(taskId, sEscalatorMetatiles_1F_3, 0); break; case 4: - SetEscalatorMetatile(taskId, sEscalatorMetatiles_2F_0, MAPGRID_COLLISION_MASK); + SetEscalatorMetatile(taskId, sEscalatorMetatiles_2F_0, MAPGRID_IMPASSABLE); break; case 5: SetEscalatorMetatile(taskId, sEscalatorMetatiles_2F_1, 0); diff --git a/src/fldeff_misc.c b/src/fldeff_misc.c index 513cd13e76..1c361fb6f0 100644 --- a/src/fldeff_misc.c +++ b/src/fldeff_misc.c @@ -840,9 +840,9 @@ void DoSecretBasePCTurnOffEffect(void) PlaySE(SE_PC_OFF); if (!VarGet(VAR_CURRENT_SECRET_BASE)) - MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_IMPASSABLE); else - MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_RegisterPC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_RegisterPC | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); } @@ -1083,7 +1083,7 @@ static void SpriteCB_SandPillar_BreakTop(struct Sprite *sprite) PlaySE(SE_M_ROCK_THROW); if (MapGridGetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1) == METATILE_SecretBase_SandOrnament_TopWall) - MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1, METATILE_SecretBase_Wall_TopMid | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1, METATILE_SecretBase_Wall_TopMid | MAPGRID_IMPASSABLE); else MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6] - 1, METATILE_SecretBase_SandOrnament_BrokenTop); @@ -1103,7 +1103,7 @@ static void SpriteCB_SandPillar_BreakBase(struct Sprite *sprite) } else { - MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6], METATILE_SecretBase_SandOrnament_BrokenBase | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(gFieldEffectArguments[5], gFieldEffectArguments[6], METATILE_SecretBase_SandOrnament_BrokenBase | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(gFieldEffectArguments[5], gFieldEffectArguments[6]); sprite->data[0] = 0; sprite->callback = SpriteCB_SandPillar_End; diff --git a/src/scrcmd.c b/src/scrcmd.c index 32502e97ce..9c7dd864e5 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -2043,7 +2043,7 @@ bool8 ScrCmd_setmetatile(struct ScriptContext *ctx) if (!isImpassable) MapGridSetMetatileIdAt(x, y, metatileId); else - MapGridSetMetatileIdAt(x, y, metatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, metatileId | MAPGRID_IMPASSABLE); return FALSE; } diff --git a/src/secret_base.c b/src/secret_base.c index df06f9120c..41b0f78339 100644 --- a/src/secret_base.c +++ b/src/secret_base.c @@ -332,7 +332,7 @@ void ToggleSecretBaseEntranceMetatile(void) { if (sSecretBaseEntranceMetatiles[i].closedMetatileId == metatileId) { - MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); return; } @@ -343,7 +343,7 @@ void ToggleSecretBaseEntranceMetatile(void) { if (sSecretBaseEntranceMetatiles[i].openMetatileId == metatileId) { - MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].closedMetatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].closedMetatileId | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); return; } @@ -398,7 +398,7 @@ void SetOccupiedSecretBaseEntranceMetatiles(struct MapEvents const *events) { if (sSecretBaseEntranceMetatiles[i].closedMetatileId == tile_id) { - MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, sSecretBaseEntranceMetatiles[i].openMetatileId | MAPGRID_IMPASSABLE); break; } } @@ -477,7 +477,7 @@ static void EnterNewlyCreatedSecretBase_StartFadeIn(void) FindMetatileIdMapCoords(&x, &y, METATILE_SecretBase_PC); x += MAP_OFFSET; y += MAP_OFFSET; - MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x, y, METATILE_SecretBase_PC | MAPGRID_IMPASSABLE); CurrentMapDrawMetatileAt(x, y); FadeInFromBlack(); CreateTask(EnterNewlyCreatedSecretBase_WaitFadeIn, 0); @@ -538,13 +538,13 @@ void InitSecretBaseAppearance(bool8 hidePC) { // Another player's secret base. Change PC type to the "Register" PC. FindMetatileIdMapCoords(&x, &y, METATILE_SecretBase_PC); - MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_RegisterPC | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_RegisterPC | MAPGRID_IMPASSABLE); } else if (hidePC == TRUE && VarGet(VAR_SECRET_BASE_INITIALIZED) == 1) { // Change PC to regular ground tile. FindMetatileIdMapCoords(&x, &y, METATILE_SecretBase_PC); - MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_Ground | MAPGRID_COLLISION_MASK); + MapGridSetMetatileIdAt(x + MAP_OFFSET, y + MAP_OFFSET, METATILE_SecretBase_Ground | MAPGRID_IMPASSABLE); } } } @@ -840,7 +840,7 @@ static void ClosePlayerSecretBaseEntrance(void) { MapGridSetMetatileIdAt(events->bgEvents[i].x + MAP_OFFSET, events->bgEvents[i].y + MAP_OFFSET, - sSecretBaseEntranceMetatiles[j].closedMetatileId | MAPGRID_COLLISION_MASK); + sSecretBaseEntranceMetatiles[j].closedMetatileId | MAPGRID_IMPASSABLE); break; } } diff --git a/src/trainer_hill.c b/src/trainer_hill.c index a42b988305..f2037b20d8 100644 --- a/src/trainer_hill.c +++ b/src/trainer_hill.c @@ -669,17 +669,17 @@ bool32 LoadTrainerHillFloorObjectEventScripts(void) return TRUE; } -static u16 GetMetatileForFloor(u8 floorId, u32 x, u32 y, u32 floorWidth) // floorWidth is always 16 +static u16 GetMapDataForFloor(u8 floorId, u32 x, u32 y, u32 floorWidth) // floorWidth is always 16 { bool8 impassable; - u16 metatile; + u16 metatileId; u16 elevation; impassable = (sHillData->floors[floorId].map.collisionData[y] >> (15 - x) & 1); - metatile = sHillData->floors[floorId].map.metatileData[floorWidth * y + x] + NUM_METATILES_IN_PRIMARY; - elevation = 3 << MAPGRID_ELEVATION_SHIFT; + metatileId = sHillData->floors[floorId].map.metatileData[floorWidth * y + x] + NUM_METATILES_IN_PRIMARY; + elevation = PACK_ELEVATION(3); - return ((impassable << MAPGRID_COLLISION_SHIFT) & MAPGRID_COLLISION_MASK) | elevation | (metatile & MAPGRID_METATILE_ID_MASK); + return PACK_COLLISION(impassable) | elevation | PACK_METATILE(metatileId); } void GenerateTrainerHillFloorLayout(u16 *mapArg) @@ -724,7 +724,7 @@ void GenerateTrainerHillFloorLayout(u16 *mapArg) for (y = 0; y < HILL_FLOOR_HEIGHT_MAIN; y++) { for (x = 0; x < HILL_FLOOR_WIDTH; x++) - dst[x] = GetMetatileForFloor(mapId, x, y, HILL_FLOOR_WIDTH); + dst[x] = GetMapDataForFloor(mapId, x, y, HILL_FLOOR_WIDTH); dst += 31; } From 219823f9a9d09d02780b23f7809f0578419c6293 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Fri, 25 Jul 2025 04:49:15 -0400 Subject: [PATCH 13/31] Fix Incompatible Z-Move Activation (#7399) Co-authored-by: ghoulslash Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- src/battle_controller_player.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index a0b4e73ece..1a258e18fb 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -897,7 +897,10 @@ void HandleInputChooseMove(u32 battler) } else if (JOY_NEW(START_BUTTON)) { - if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE && !HasTrainerUsedGimmick(battler, gBattleStruct->gimmick.usableGimmick[battler])) + if (gBattleStruct->gimmick.usableGimmick[battler] != GIMMICK_NONE + && !HasTrainerUsedGimmick(battler, gBattleStruct->gimmick.usableGimmick[battler]) + && !(gBattleStruct->gimmick.usableGimmick[battler] == GIMMICK_Z_MOVE + && GetUsableZMove(battler, moveInfo->moves[gMoveSelectionCursor[battler]]) == MOVE_NONE)) { gBattleStruct->gimmick.playerSelect ^= 1; ReloadMoveNames(battler); From 845838bbc0281ab2ca7b69c92b6576e649c22bd5 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 25 Jul 2025 15:32:45 +0200 Subject: [PATCH 14/31] Fixes bug for affectionScore in doubles for spread moves (#7395) --- src/battle_script_commands.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index fcd325305c..eb0738a24e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2177,7 +2177,7 @@ static void Cmd_adjustdamage(void) u8 param; u32 battlerDef; u32 rand = Random() % 100; - u32 affectionScore = GetBattlerAffectionHearts(gBattlerTarget); + u32 affectionScore; u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); enum BattleMoveEffects moveEffect = GetMoveEffect(gCurrentMove); bool32 calcSpreadMoveDamage = IsSpreadMove(moveTarget) && !IsBattleMoveStatus(gCurrentMove); @@ -2221,7 +2221,8 @@ static void Cmd_adjustdamage(void) holdEffect = GetBattlerHoldEffect(battlerDef, TRUE); param = GetBattlerHoldEffectParam(battlerDef); - + affectionScore = GetBattlerAffectionHearts(battlerDef); + gPotentialItemEffectBattler = battlerDef; if (moveEffect == EFFECT_FALSE_SWIPE) From 38964e4f0a7e556a68ed6e995de6ea325f92a951 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 25 Jul 2025 19:26:12 +0200 Subject: [PATCH 15/31] Fixes Wandering Spirit overwriting battlers (#7407) --- data/battle_scripts_1.s | 4 ++++ test/battle/hold_effect/eject_button.c | 18 ++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6d36b2b530..4db067a4b9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -8189,6 +8189,8 @@ BattleScript_MummyActivates:: return BattleScript_WanderingSpiritActivates:: + saveattacker + savetarget .if B_ABILITY_POP_UP == TRUE copybyte gBattlerAbility, gBattlerTarget sethword sABILITY_OVERWRITE, ABILITY_WANDERING_SPIRIT @@ -8205,6 +8207,8 @@ BattleScript_WanderingSpiritActivates:: jumpiffainted BS_TARGET, TRUE, BattleScript_WanderingSpiritActivatesRet switchinabilities BS_TARGET BattleScript_WanderingSpiritActivatesRet: + restoreattacker + restoretarget return BattleScript_TargetsStatWasMaxedOut:: diff --git a/test/battle/hold_effect/eject_button.c b/test/battle/hold_effect/eject_button.c index 9dd73833a5..681858605b 100644 --- a/test/battle/hold_effect/eject_button.c +++ b/test/battle/hold_effect/eject_button.c @@ -232,3 +232,21 @@ DOUBLE_BATTLE_TEST("Eject Button activation will not trigger an attack from the } } } + +SINGLE_BATTLE_TEST("Eject Button activates after Wandring Spirit") +{ + GIVEN { + PLAYER(SPECIES_EKANS) { Ability(ABILITY_INTIMIDATE); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_YAMASK_GALAR) { Item(ITEM_EJECT_BUTTON); Ability(ABILITY_WANDERING_SPIRIT); } + } WHEN { + TURN { + SWITCH(opponent, 1); + MOVE(player, MOVE_DRAGON_CLAW); + SEND_OUT(opponent, 0); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_CLAW, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); + } +} From fa129ba906ea3a330f98d198eb3885f7c3fc24a7 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Fri, 25 Jul 2025 13:28:24 -0400 Subject: [PATCH 16/31] Fix hit escape switching hardcode (#7403) --- src/battle_controller_opponent.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index f6fae5ae57..a139c9bfc3 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -623,6 +623,7 @@ static void OpponentHandleChoosePokemon(u32 battler) { s32 chosenMonId; s32 pokemonInBattle = 1; + enum SwitchType switchType = SWITCH_AFTER_KO; // Choosing Revival Blessing target if ((gBattleResources->bufferA[battler][1] & 0xF) == PARTY_ACTION_CHOOSE_FAINTED_MON) @@ -632,7 +633,9 @@ static void OpponentHandleChoosePokemon(u32 battler) // Switching out else if (gBattleStruct->AI_monToSwitchIntoId[battler] == PARTY_SIZE) { - chosenMonId = GetMostSuitableMonToSwitchInto(battler, SWITCH_AFTER_KO); + if (IsSwitchOutEffect(GetMoveEffect(gCurrentMove)) || gAiLogicData->ejectButtonSwitch || gAiLogicData->ejectPackSwitch) + switchType = SWITCH_MID_BATTLE; + chosenMonId = GetMostSuitableMonToSwitchInto(battler, switchType); if (chosenMonId == PARTY_SIZE) { s32 battler1, battler2, firstId, lastId; From 5da5cb4c8cd9103b6c97c3857eebb91e3390e955 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Sat, 26 Jul 2025 20:19:45 +0200 Subject: [PATCH 17/31] document shop menu palette --- src/shop.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/shop.c b/src/shop.c index 587060f024..338e067938 100644 --- a/src/shop.c +++ b/src/shop.c @@ -43,6 +43,7 @@ #define TAG_ITEM_ICON_BASE 2110 #define MAX_ITEMS_SHOWN 8 +#define SHOP_MENU_PALETTE_ID 12 enum { WIN_BUY_SELL_QUIT, @@ -740,7 +741,7 @@ static void BuyMenuDecompressBgGraphics(void) { DecompressAndCopyTileDataToVram(1, gShopMenu_Gfx, 0x3A0, 0x3E3, 0); LZDecompressWram(gShopMenu_Tilemap, sShopData->tilemapBuffers[0]); - LoadCompressedPalette(gShopMenu_Pal, BG_PLTT_ID(12), PLTT_SIZE_4BPP); + LoadCompressedPalette(gShopMenu_Pal, BG_PLTT_ID(SHOP_MENU_PALETTE_ID), PLTT_SIZE_4BPP); } static void BuyMenuInitWindows(void) @@ -941,7 +942,7 @@ static void BuyMenuCopyMenuBgToBg1TilemapBuffer(void) for (i = 0; i < 1024; i++) { if (src[i] != 0) - dest[i] = src[i] + 0xC3E3; + dest[i] = src[i] + ((SHOP_MENU_PALETTE_ID << 12) | 0x3E3); } } From 7b2fe32050c72bf00a9cce96a6ec2bcd15e1c4a2 Mon Sep 17 00:00:00 2001 From: surskitty Date: Mon, 28 Jul 2025 07:11:04 -0400 Subject: [PATCH 18/31] Make B_VAR_STARTING_STATUS tests run in CI (#7419) --- include/config/test.h | 4 ++++ include/constants/vars.h | 18 +++++++++--------- test/battle/starting_status/terrain.c | 27 ++++++++++++++------------- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/include/config/test.h b/include/config/test.h index 6122d14aa1..9e880d57c7 100644 --- a/include/config/test.h +++ b/include/config/test.h @@ -1132,6 +1132,10 @@ // Vars #undef B_VAR_DIFFICULTY #define B_VAR_DIFFICULTY TESTING_VAR_DIFFICULTY +#undef B_VAR_STARTING_STATUS +#define B_VAR_STARTING_STATUS TESTING_VAR_STARTING_STATUS +#undef B_VAR_STARTING_STATUS_TIMER +#define B_VAR_STARTING_STATUS_TIMER TESTING_VAR_STARTING_STATUS_TIMER // Flags #undef B_FLAG_SLEEP_CLAUSE diff --git a/include/constants/vars.h b/include/constants/vars.h index aac52dec0e..a12c2ff3a5 100644 --- a/include/constants/vars.h +++ b/include/constants/vars.h @@ -325,15 +325,15 @@ #define VAR_TEMP_TRANSFERRED_SPECIES VAR_TEMP_1 #if TESTING -#define TESTING_VARS_START 0x9000 -#define TESTING_VAR_DIFFICULTY (TESTING_VARS_START + 0x0) -#define TESTING_VAR_UNUSED_1 (TESTING_VARS_START + 0x1) -#define TESTING_VAR_UNUSED_2 (TESTING_VARS_START + 0x2) -#define TESTING_VAR_UNUSED_3 (TESTING_VARS_START + 0x3) -#define TESTING_VAR_UNUSED_4 (TESTING_VARS_START + 0x4) -#define TESTING_VAR_UNUSED_5 (TESTING_VARS_START + 0x5) -#define TESTING_VAR_UNUSED_6 (TESTING_VARS_START + 0x6) -#define TESTING_VAR_UNUSED_7 (TESTING_VARS_START + 0x7) +#define TESTING_VARS_START 0x9000 +#define TESTING_VAR_DIFFICULTY (TESTING_VARS_START + 0x0) +#define TESTING_VAR_STARTING_STATUS (TESTING_VARS_START + 0x1) +#define TESTING_VAR_STARTING_STATUS_TIMER (TESTING_VARS_START + 0x2) +#define TESTING_VAR_UNUSED_3 (TESTING_VARS_START + 0x3) +#define TESTING_VAR_UNUSED_4 (TESTING_VARS_START + 0x4) +#define TESTING_VAR_UNUSED_5 (TESTING_VARS_START + 0x5) +#define TESTING_VAR_UNUSED_6 (TESTING_VARS_START + 0x6) +#define TESTING_VAR_UNUSED_7 (TESTING_VARS_START + 0x7) #endif // TESTING #endif // GUARD_CONSTANTS_VARS_H diff --git a/test/battle/starting_status/terrain.c b/test/battle/starting_status/terrain.c index ab31bbbb96..3d84dba000 100644 --- a/test/battle/starting_status/terrain.c +++ b/test/battle/starting_status/terrain.c @@ -29,19 +29,20 @@ SINGLE_BATTLE_TEST("B_VAR_STARTING_STATUS starts a chosen terrain at the beginni TURN { ; } TURN { ; } } SCENE { - switch (terrain) { - case STARTING_STATUS_GRASSY_TERRAIN: - MESSAGE("Grass grew to cover the battlefield!"); - break; - case STARTING_STATUS_PSYCHIC_TERRAIN: - MESSAGE("The battlefield got weird!"); - break; - case STARTING_STATUS_MISTY_TERRAIN: - MESSAGE("Mist swirled around the battlefield!"); - break; - case STARTING_STATUS_ELECTRIC_TERRAIN: - MESSAGE("An electric current is running across the battlefield!"); - break; + switch (terrain) + { + case STARTING_STATUS_GRASSY_TERRAIN: + MESSAGE("The battlefield is covered with grass!"); + break; + case STARTING_STATUS_PSYCHIC_TERRAIN: + MESSAGE("The battlefield seems weird!"); + break; + case STARTING_STATUS_MISTY_TERRAIN: + MESSAGE("Mist swirls around the battlefield!"); + break; + case STARTING_STATUS_ELECTRIC_TERRAIN: + MESSAGE("An electric current is running across the battlefield!"); + break; } ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_RESTORE_BG); NONE_OF { From 95e45b5568e8692d770ccd8258bb02174ad60058 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Mon, 28 Jul 2025 08:10:03 -0400 Subject: [PATCH 19/31] Fix Echoing Voice calcs (#7416) --- src/battle_util.c | 2 +- test/battle/ai/ai_switching.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index b5e68f9cbd..7c9ff8d03e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8219,7 +8219,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData } case EFFECT_ECHOED_VOICE: // gBattleStruct->sameMoveTurns incremented in ppreduce - if (gBattleStruct->sameMoveTurns[battlerAtk] != 0) + if (gBattleStruct->sameMoveTurns[battlerAtk] != 0 && GetMoveEffect(gLastResultingMoves[battlerAtk]) == EFFECT_ECHOED_VOICE) { basePower += (basePower * gBattleStruct->sameMoveTurns[battlerAtk]); if (basePower > 200) diff --git a/test/battle/ai/ai_switching.c b/test/battle/ai/ai_switching.c index 0c9e94695e..03334e04c2 100644 --- a/test/battle/ai/ai_switching.c +++ b/test/battle/ai/ai_switching.c @@ -1268,3 +1268,18 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_SWITCHING: AI considers 0 hits to KO as los TURN { MOVE(player, MOVE_TACKLE); EXPECT_SEND_OUT(opponent, 2); } } } + +AI_SINGLE_BATTLE_TEST("AI_FLAG_SMART_MON_CHOICES: AI sees Echoed Voice damage correctly") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_OMNISCIENT); + PLAYER(SPECIES_WOBBUFFET) { Speed(5); Moves(MOVE_SCRATCH, MOVE_ECHOED_VOICE); } + OPPONENT(SPECIES_ZIGZAGOON) { Speed(4); Level(55); Moves(MOVE_CELEBRATE); } + OPPONENT(SPECIES_DRAPION) { Speed(4); SpDefense(25); Moves(MOVE_WICKED_BLOW); Ability(ABILITY_SNIPER); } + OPPONENT(SPECIES_GASTLY) { Speed(4); Level(1); Moves(MOVE_TACKLE); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_CELEBRATE); } + TURN { MOVE(player, MOVE_SCRATCH); EXPECT_MOVE(opponent, MOVE_CELEBRATE); EXPECT_SEND_OUT(opponent, 1); } + } +} From 8bfc5b3093b457548ccf3afda4479ee5425ea3de Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Mon, 28 Jul 2025 13:21:12 +0100 Subject: [PATCH 20/31] Fixes Razor Wind not activating after hit effects after the first target (#7413) --- data/battle_scripts_1.s | 1 + test/battle/move_effect/two_turns_attack.c | 30 ++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 4db067a4b9..31835383dd 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3529,6 +3529,7 @@ BattleScript_PowerHerbActivation: BattleScript_EffectTwoTurnsAttack:: jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_TwoTurnMovesSecondTurn jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_NO_ATTACKSTRING, BattleScript_TwoTurnMovesSecondTurn + jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_ATTACKSTRING_PRINTED, BattleScript_EffectHit @ if it's not the first hit tryfiretwoturnmovewithoutcharging BS_ATTACKER, BattleScript_EffectHit @ e.g. Solar Beam call BattleScript_FirstChargingTurn tryfiretwoturnmoveaftercharging BS_ATTACKER, BattleScript_TwoTurnMovesSecondTurn @ e.g. Electro Shot diff --git a/test/battle/move_effect/two_turns_attack.c b/test/battle/move_effect/two_turns_attack.c index 4dd79ade46..661a45c110 100644 --- a/test/battle/move_effect/two_turns_attack.c +++ b/test/battle/move_effect/two_turns_attack.c @@ -67,6 +67,36 @@ SINGLE_BATTLE_TEST("Razor Wind doesn't need to charge with Power Herb") } } +DOUBLE_BATTLE_TEST("Razor Wind successfully KOs both opponents") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_POWER_HERB); } + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET) { HP(1); } + OPPONENT(SPECIES_WYNAUT) { HP(1); } + } WHEN { + TURN { MOVE(playerLeft, MOVE_RAZOR_WIND); } + } SCENE { + if (B_UPDATED_MOVE_DATA >= GEN_5) { + NOT MESSAGE("Wobbuffet whipped up a whirlwind!"); + MESSAGE("Wobbuffet used Razor Wind!"); + } else + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, playerLeft); + if (B_UPDATED_MOVE_DATA < GEN_5) + MESSAGE("Wobbuffet whipped up a whirlwind!"); + else + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, playerLeft); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, playerLeft); + MESSAGE("Wobbuffet became fully charged due to its Power Herb!"); + if (B_UPDATED_MOVE_DATA < GEN_5) + MESSAGE("Wobbuffet used Razor Wind!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_RAZOR_WIND, playerLeft); + HP_BAR(opponentLeft); + MESSAGE("The opposing Wobbuffet fainted!"); + MESSAGE("The opposing Wynaut fainted!"); + } +} + SINGLE_BATTLE_TEST("Skull Bash needs a charging turn") { GIVEN { From 6a96be81818cd9a659c0ebfb1e8e143993013f76 Mon Sep 17 00:00:00 2001 From: Hedara Date: Mon, 28 Jul 2025 19:30:43 +0200 Subject: [PATCH 21/31] Changed incorrect comment --- src/pokenav_main_menu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pokenav_main_menu.c b/src/pokenav_main_menu.c index d2765b6706..547a2d84b5 100644 --- a/src/pokenav_main_menu.c +++ b/src/pokenav_main_menu.c @@ -32,7 +32,7 @@ struct Pokenav_MainMenu // Needed to match LoadLeftHeaderGfxForSubMenu. struct CompressedSpriteSheetNoSize { - const u32 *data; // LZ77 compressed palette data + const u32 *data; // Compressed sprite data u32 tag; }; From cb4450efaf0d62d1817cb44c369ac48f53257d95 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Wed, 30 Jul 2025 19:54:12 +0200 Subject: [PATCH 22/31] Fixes Effect Spore and Baneful Bunker/Burning Bulwark (#7412) --- include/battle.h | 3 ++- src/battle_script_commands.c | 8 ++++-- src/battle_util.c | 20 +++++++++----- test/battle/ability/effect_spore.c | 18 +++++++++++++ test/battle/move_effect/protect.c | 42 ++++++++++++++++++++++++++++++ 5 files changed, 81 insertions(+), 10 deletions(-) diff --git a/include/battle.h b/include/battle.h index d59432e6c1..79cc591980 100644 --- a/include/battle.h +++ b/include/battle.h @@ -666,7 +666,8 @@ struct BattleStruct u8 anyMonHasTransformed:1; // Only used in battle_tv.c u8 multipleSwitchInState:2; u8 multipleSwitchInCursor:3; - u8 padding1:2; + u8 sleepClauseNotBlocked:1; + u8 padding1:1; u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; void (*savedCallback)(void); u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index f39c7a2386..6798b9bd9c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6543,7 +6543,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BANEFUL_BUNKER: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && CanBePoisoned(gBattlerTarget, gBattlerAttacker, gLastUsedAbility, GetBattlerAbility(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_POISON | MOVE_EFFECT_AFFECTS_USER; @@ -6554,7 +6555,8 @@ static void Cmd_moveend(void) } break; case PROTECT_BURNING_BULWARK: - if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE))) + if (!IsProtectivePadsProtected(gBattlerAttacker, GetBattlerHoldEffect(gBattlerAttacker, TRUE)) + && CanBeBurned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker))) { gProtectStructs[gBattlerAttacker].touchedProtectLike = FALSE; gBattleScripting.moveEffect = MOVE_EFFECT_BURN | MOVE_EFFECT_AFFECTS_USER; @@ -6728,6 +6730,7 @@ static void Cmd_moveend(void) { BestowItem(BATTLE_PARTNER(i), i); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(i)].ability; + gEffectBattler = i; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(i); gBattlerAttacker = i; BattleScriptPushCursor(); @@ -9231,6 +9234,7 @@ static bool32 TrySymbiosis(u32 battler, u32 itemId, bool32 moveEnd) { BestowItem(BATTLE_PARTNER(battler), battler); gLastUsedAbility = gBattleMons[BATTLE_PARTNER(battler)].ability; + gEffectBattler = battler; gBattleScripting.battler = gBattlerAbility = BATTLE_PARTNER(battler); if (moveEnd) BattleScriptPushCursor(); diff --git a/src/battle_util.c b/src/battle_util.c index d2303bca8a..e580c63616 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4627,9 +4627,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_EFFECT_SPORE: { - u32 ability = GetBattlerAbility(gBattlerAttacker); + u32 abilityAtk = GetBattlerAbility(gBattlerAttacker); if ((!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GRASS) || B_POWDER_GRASS < GEN_6) - && ability != ABILITY_OVERCOAT + && abilityAtk != ABILITY_OVERCOAT && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_SAFETY_GOGGLES) { u32 poison, paralysis, sleep; @@ -4657,7 +4657,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IsBattlerTurnDamaged(gBattlerTarget) - && CanBeSlept(gBattlerAttacker, gBattlerTarget, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE) + && CanBeSlept(gBattlerTarget, gBattlerAttacker, abilityAtk, NOT_BLOCKED_BY_SLEEP_CLAUSE) && !CanBattlerAvoidContactEffects(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerAttacker), GetBattlerHoldEffect(gBattlerAttacker, TRUE), move)) { if (IsSleepClauseEnabled()) @@ -5553,17 +5553,23 @@ bool32 IsBattlerTerrainAffected(u32 battler, u32 terrainFlag) bool32 CanBeSlept(u32 battlerAtk, u32 battlerDef, u32 abilityDef, enum SleepClauseBlock isBlockedBySleepClause) { - if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause) + if (IsSleepClauseActiveForSide(GetBattlerSide(battlerDef)) && isBlockedBySleepClause != NOT_BLOCKED_BY_SLEEP_CLAUSE) return FALSE; + if (isBlockedBySleepClause == NOT_BLOCKED_BY_SLEEP_CLAUSE) + gBattleStruct->sleepClauseNotBlocked = TRUE; + + bool32 effect = FALSE; if (CanSetNonVolatileStatus(battlerAtk, battlerDef, ABILITY_NONE, // attacker ability does not matter abilityDef, MOVE_EFFECT_SLEEP, // also covers yawn STATUS_CHECK_TRIGGER)) - return TRUE; - return FALSE; + effect = TRUE; + + gBattleStruct->sleepClauseNotBlocked = FALSE; + return effect; } bool32 CanBePoisoned(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u32 abilityDef) @@ -5714,7 +5720,7 @@ bool32 CanSetNonVolatileStatus(u32 battlerAtk, u32 battlerDef, u32 abilityAtk, u { battleScript = BattleScript_CantMakeAsleep; } - else if (CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) + else if (!gBattleStruct->sleepClauseNotBlocked && CanSleepDueToSleepClause(battlerAtk, battlerDef, option)) { battleScript = BattleScript_SleepClauseBlocked; } diff --git a/test/battle/ability/effect_spore.c b/test/battle/ability/effect_spore.c index 57f5399b53..ff61683b54 100644 --- a/test/battle/ability/effect_spore.c +++ b/test/battle/ability/effect_spore.c @@ -88,3 +88,21 @@ SINGLE_BATTLE_TEST("Effect Spore causes sleep 11% of the time") STATUS_ICON(player, sleep: TRUE); } } + +SINGLE_BATTLE_TEST("Effect Spore will check if it can inflict status onto attacker, not itself") +{ + PASSES_RANDOMLY(11, 100, RNG_EFFECT_SPORE); + GIVEN { + ASSUME(B_ABILITY_TRIGGER_CHANCE >= GEN_5); + ASSUME(MoveMakesContact(MOVE_SCRATCH)); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BRELOOM) { Status1(STATUS1_BURN); Ability(ABILITY_EFFECT_SPORE); } + } WHEN { + TURN { MOVE(player, MOVE_SCRATCH); } + } SCENE { + ABILITY_POPUP(opponent, ABILITY_EFFECT_SPORE); + ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_SLP, player); + MESSAGE("The opposing Breloom's Effect Spore made Wobbuffet sleep!"); + STATUS_ICON(player, sleep: TRUE); + } +} diff --git a/test/battle/move_effect/protect.c b/test/battle/move_effect/protect.c index 09fc4c12bf..6dddfae4e7 100644 --- a/test/battle/move_effect/protect.c +++ b/test/battle/move_effect/protect.c @@ -194,6 +194,27 @@ SINGLE_BATTLE_TEST("Protect: Baneful Bunker poisons pokemon for moves making con } } +SINGLE_BATTLE_TEST("Protect: Baneful Bunker can't poison pokemon if they are already statused") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_WILL_O_WISP); } + TURN { MOVE(opponent, MOVE_BANEFUL_BUNKER); MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WILL_O_WISP, opponent); + STATUS_ICON(player, STATUS1_BURN); + ANIMATION(ANIM_TYPE_MOVE, MOVE_BANEFUL_BUNKER, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SCRATCH, player); + HP_BAR(opponent); + STATUS_ICON(player, STATUS1_POISON); + } + } +} + SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making contact") { u16 usedMove = MOVE_NONE; @@ -226,6 +247,27 @@ SINGLE_BATTLE_TEST("Protect: Burning Bulwark burns pokemon for moves making cont } } +SINGLE_BATTLE_TEST("Protect: Burning Bulwark can't burn pokemon if they are already statused") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_TOXIC); } + TURN { MOVE(opponent, MOVE_BURNING_BULWARK); MOVE(player, MOVE_SCRATCH); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TOXIC, opponent); + STATUS_ICON(player, STATUS1_TOXIC_POISON); + 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); + } + } +} + SINGLE_BATTLE_TEST("Protect: Recoil damage is not applied if target was protected") { u32 j, k; From d8059ce3d1879c0fb9d3c834036c31f34684c54d Mon Sep 17 00:00:00 2001 From: Hedara Date: Wed, 30 Jul 2025 20:34:43 +0200 Subject: [PATCH 23/31] 1.12.2 release version --- .../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.2.md | 164 ++++++++++++++++++ include/constants/expansion.h | 4 +- 7 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 docs/changelogs/1.12.x/1.12.2.md diff --git a/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml b/.github/ISSUE_TEMPLATE/01_battle_engine_bugs.yaml index 1ab103d6c7..b48cda404c 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.1 (Latest release) + - 1.12.2 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.1 - 1.12.0 - 1.11.4 - 1.11.3 diff --git a/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml b/.github/ISSUE_TEMPLATE/02_battle_ai_issues.yaml index 49bf8a5525..95b00ef2d1 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.1 (Latest release) + - 1.12.2 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.1 - 1.12.0 - 1.11.4 - 1.11.3 diff --git a/.github/ISSUE_TEMPLATE/04_other_errors.yaml b/.github/ISSUE_TEMPLATE/04_other_errors.yaml index 0d25f6a96a..d955d09cbc 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.1 (Latest release) + - 1.12.2 (Latest release) - master (default, unreleased bugfixes) - upcoming (Edge) + - 1.12.1 - 1.12.0 - 1.11.4 - 1.11.3 diff --git a/README.md b/README.md index 6d86c27a2a..4cd0a5f161 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.1 https://github.com/rh-hideout/pokeemerald-expansion/ +Based off RHH's pokeemerald-expansion 1.12.2 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 258d078cdb..89767de31b 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.2](changelogs/1.12.x/1.12.2.md) - [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]() diff --git a/docs/changelogs/1.12.x/1.12.2.md b/docs/changelogs/1.12.x/1.12.2.md new file mode 100644 index 0000000000..9f1b210638 --- /dev/null +++ b/docs/changelogs/1.12.x/1.12.2.md @@ -0,0 +1,164 @@ +```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) +* add bassforte123 as a contributor for code by @allcontributors[bot] in [#7003](https://github.com/rh-hideout/pokeemerald-expansion/pull/7003) +* add iriv24 as a contributor for code by @allcontributors[bot] in [#7059](https://github.com/rh-hideout/pokeemerald-expansion/pull/7059) +* add Bivurnum as a contributor for code by @allcontributors[bot] in [#7067](https://github.com/rh-hideout/pokeemerald-expansion/pull/7067) +* 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) +* add Emiliasky as a contributor for test by @allcontributors[bot] in [#7082](https://github.com/rh-hideout/pokeemerald-expansion/pull/7082) +* Update CREDITS.md with correct line placement by @pkmnsnfrn in [#7096](https://github.com/rh-hideout/pokeemerald-expansion/pull/7096) +* 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) +* add fakuzatsu as a contributor for code by @allcontributors[bot] in [#7136](https://github.com/rh-hideout/pokeemerald-expansion/pull/7136) +* Fixed description of `FORM_CHANGE_WITHDRAW` by @AsparagusEduardo in [#7152](https://github.com/rh-hideout/pokeemerald-expansion/pull/7152) +* add poetahto as a contributor for code by @allcontributors[bot] in [#7162](https://github.com/rh-hideout/pokeemerald-expansion/pull/7162) +* 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) +* add pablopenna as a contributor for code by @allcontributors[bot] in [#7202](https://github.com/rh-hideout/pokeemerald-expansion/pull/7202) + +### 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) + + + * Chloroblast causing recoil damage even if the move fails to connect by @LinathanZel in #7007 + + +* [DRAFT] 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 🧹 +* Update CI to ignore allcontributors commits by @pkmnsnfrn in [#7046](https://github.com/rh-hideout/pokeemerald-expansion/pull/7046) +* Update CREDITS.md with correct line placement by @pkmnsnfrn in [#7096](https://github.com/rh-hideout/pokeemerald-expansion/pull/7096) +* 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 11822f8510..b8987abb43 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.1 +// Last version: 1.12.2 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 12 #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 FALSE +#define EXPANSION_TAGGED_RELEASE TRUE #endif From 637f7dff46d7f270b015e4311373c8d32b9ebcb0 Mon Sep 17 00:00:00 2001 From: Hedara Date: Wed, 30 Jul 2025 20:35:16 +0200 Subject: [PATCH 24/31] Start of 1.12.3 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 b8987abb43..cdfaa6228e 100644 --- a/include/constants/expansion.h +++ b/include/constants/expansion.h @@ -4,10 +4,10 @@ // Last version: 1.12.2 #define EXPANSION_VERSION_MAJOR 1 #define EXPANSION_VERSION_MINOR 12 -#define EXPANSION_VERSION_PATCH 2 +#define EXPANSION_VERSION_PATCH 3 // 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 48c850c60b533ce73a33b93002175e08bb01de07 Mon Sep 17 00:00:00 2001 From: "allcontributors[bot]" <46447321+allcontributors[bot]@users.noreply.github.com> Date: Wed, 30 Jul 2025 18:32:16 -0700 Subject: [PATCH 25/31] add tustin2121 as a contributor for doc, and code (#7445) Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com> --- .all-contributorsrc | 10 ++++++++++ CREDITS.md | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/.all-contributorsrc b/.all-contributorsrc index c8b79ba30e..c4ed2ea558 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -338,6 +338,16 @@ "contributions": [ "code" ] + }, + { + "login": "tustin2121", + "name": "tustin2121", + "avatar_url": "https://avatars.githubusercontent.com/u/794812?v=4", + "profile": "https://tustin2121.github.io/", + "contributions": [ + "doc", + "code" + ] } ], "contributorsPerLine": 7, diff --git a/CREDITS.md b/CREDITS.md index ab5c596248..17809a3c3f 100644 --- a/CREDITS.md +++ b/CREDITS.md @@ -58,7 +58,8 @@ Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/d Zatsu
Zatsu

💻 poetahto
poetahto

💻 lordraindance2
lordraindance2

💻 - Pablo Pena
Pablo Pena

💻 + Pablo Pena
Pablo Pena

💻 + tustin2121
tustin2121

📖 💻 From 01105171a3701384d156499fc8329c4cd6b403ea Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Thu, 31 Jul 2025 18:30:50 +0100 Subject: [PATCH 26/31] Fixes Magnet Rise when user is Rooted/Smacked Down (#7449) --- data/battle_scripts_1.s | 2 + test/battle/move_effect/magic_room.c | 2 + test/battle/move_effect/magnet_rise.c | 55 ++++++++++++++++++- .../move_effect_secondary/will_o_wisp.c | 4 -- 4 files changed, 58 insertions(+), 5 deletions(-) delete mode 100644 test/battle/move_effect_secondary/will_o_wisp.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 31835383dd..13d3c09012 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2601,6 +2601,8 @@ BattleScript_EffectMagnetRise:: attackcanceler attackstring ppreduce + jumpifstatus3 BS_ATTACKER, STATUS3_ROOTED, BattleScript_ButItFailed + jumpifstatus3 BS_ATTACKER, STATUS3_SMACKED_DOWN, BattleScript_ButItFailed setuserstatus3 STATUS3_MAGNET_RISE, BattleScript_ButItFailed attackanimation waitanimation diff --git a/test/battle/move_effect/magic_room.c b/test/battle/move_effect/magic_room.c index b1be6ac5bc..98d55cfd57 100644 --- a/test/battle/move_effect/magic_room.c +++ b/test/battle/move_effect/magic_room.c @@ -35,3 +35,5 @@ DOUBLE_BATTLE_TEST("Magic Room prevents item hold effects") ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponentRight); } } + +TO_DO_BATTLE_TEST("TODO: Write Magic Room (Move Effect) test titles") diff --git a/test/battle/move_effect/magnet_rise.c b/test/battle/move_effect/magnet_rise.c index 9fde0046fd..7e50bb24cb 100644 --- a/test/battle/move_effect/magnet_rise.c +++ b/test/battle/move_effect/magnet_rise.c @@ -1,4 +1,57 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("TODO: Write Magic Room (Move Effect) test titles") +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_MAGNET_RISE) == EFFECT_MAGNET_RISE); +} + +SINGLE_BATTLE_TEST("Magnet Rise rises the user into the air, avoiding Ground-type attacks") +{ + GIVEN { + ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_MAGNET_RISE); MOVE(opponent, MOVE_EARTHQUAKE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGNET_RISE, player); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EARTHQUAKE, opponent); + HP_BAR(player); + } + } +} + +SINGLE_BATTLE_TEST("Magnet Rise fails if the user is Rooted") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_INGRAIN) == EFFECT_INGRAIN); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_INGRAIN); } + TURN { MOVE(player, MOVE_MAGNET_RISE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_INGRAIN, player); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGNET_RISE, player); + } +} + +SINGLE_BATTLE_TEST("Magnet Rise fails if the user is Grounded by Smack Down") +{ + GIVEN { + ASSUME(GetMoveEffect(MOVE_SMACK_DOWN) == EFFECT_SMACK_DOWN); + ASSUME(gSpeciesInfo[SPECIES_XATU].types[0] == TYPE_FLYING || gSpeciesInfo[SPECIES_XATU].types[1] == TYPE_FLYING); + PLAYER(SPECIES_XATU); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_SMACK_DOWN); MOVE(player, MOVE_MAGNET_RISE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SMACK_DOWN, opponent); + MESSAGE("Xatu fell straight down!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_MAGNET_RISE, player); + } +} + +TO_DO_BATTLE_TEST("TODO: Write Magnet Rise (Move Effect) test titles") diff --git a/test/battle/move_effect_secondary/will_o_wisp.c b/test/battle/move_effect_secondary/will_o_wisp.c deleted file mode 100644 index 08b1bd6c69..0000000000 --- a/test/battle/move_effect_secondary/will_o_wisp.c +++ /dev/null @@ -1,4 +0,0 @@ -#include "global.h" -#include "test/battle.h" - -TO_DO_BATTLE_TEST("TODO: Write Will-O-Wisp (Move Effect) test titles") From 297cd83871890e040a7f37d4cfb16518bdbafae0 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 2 Aug 2025 17:43:44 +0200 Subject: [PATCH 27/31] Clean up some Normalize tests to make them make sense (#7461) Co-authored-by: Hedara --- test/battle/ability/normalize.c | 40 +++++++-------------------------- 1 file changed, 8 insertions(+), 32 deletions(-) diff --git a/test/battle/ability/normalize.c b/test/battle/ability/normalize.c index 2a449f74a5..33fe89c587 100644 --- a/test/battle/ability/normalize.c +++ b/test/battle/ability/normalize.c @@ -156,53 +156,29 @@ SINGLE_BATTLE_TEST("Normalize boosts power of affected moves by 20% (Gen7+)", s1 } } -SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Electrify's effect", s16 damage) +SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Electrify's effect") { - 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; } - GIVEN { ASSUME(GetMoveEffect(MOVE_ELECTRIFY) == EFFECT_ELECTRIFY); - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); - PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } - OPPONENT(SPECIES_WOBBUFFET); + PLAYER(SPECIES_SKITTY) { Ability(ABILITY_NORMALIZE); } + OPPONENT(SPECIES_ROOKIDEE) { Item(ITEM_WACAN_BERRY); } } WHEN { TURN { MOVE(opponent, MOVE_ELECTRIFY); MOVE(player, MOVE_WATER_GUN); } } SCENE { - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - if (genConfig >= GEN_7) - EXPECT_EQ(results[0].damage, results[2].damage); - else - EXPECT_EQ(results[1].damage, results[3].damage); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); } } -SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Ion Deluge's effect", s16 damage) +SINGLE_BATTLE_TEST("Normalize-affected moves become Electric-type under Ion Deluge's effect") { - 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; } - GIVEN { ASSUME(GetMoveEffect(MOVE_ION_DELUGE) == EFFECT_ION_DELUGE); - WITH_CONFIG(GEN_CONFIG_ATE_MULTIPLIER, genConfig); - PLAYER(SPECIES_SKITTY) { Ability(ability); Moves(MOVE_WATER_GUN); } - OPPONENT(SPECIES_WOBBUFFET); + PLAYER(SPECIES_SKITTY) { Ability(ABILITY_NORMALIZE); Moves(MOVE_WATER_GUN); } + OPPONENT(SPECIES_ROOKIDEE) { Item(ITEM_WACAN_BERRY); } } WHEN { TURN { MOVE(opponent, MOVE_ION_DELUGE); MOVE(player, MOVE_WATER_GUN); } } SCENE { - HP_BAR(opponent, captureDamage: &results[i].damage); - } FINALLY { - if (genConfig >= GEN_7) - EXPECT_EQ(results[0].damage, results[2].damage); - else - EXPECT_EQ(results[1].damage, results[3].damage); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); } } From 54ffc6bf0856661be1289afa7961d30e1a2c3414 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sun, 3 Aug 2025 21:59:48 +0200 Subject: [PATCH 28/31] Fixes Leech Seed recovery not applying behind Sub --- data/battle_scripts_1.s | 1 + test/battle/move_effect/leech_seed.c | 28 +++++++++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 13d3c09012..23c1e10aa9 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5776,6 +5776,7 @@ BattleScript_LeechSeedTurnDrainHealBlock:: BattleScript_LeechSeedTurnDrainRecovery:: call BattleScript_LeechSeedTurnDrain BattleScript_LeechSeedTurnDrainGainHp: + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_PASSIVE_DAMAGE healthbarupdate BS_TARGET datahpupdate BS_TARGET printfromtable gLeechSeedStringIds diff --git a/test/battle/move_effect/leech_seed.c b/test/battle/move_effect/leech_seed.c index 56da50a12b..49f963f416 100644 --- a/test/battle/move_effect/leech_seed.c +++ b/test/battle/move_effect/leech_seed.c @@ -66,11 +66,11 @@ DOUBLE_BATTLE_TEST("Leech Seed will drain HP based on speed of the drained mon") OPPONENT(SPECIES_WYNAUT) { Speed(3); } OPPONENT(SPECIES_WOBBUFFET) { Speed(4); } } WHEN { - TURN { - MOVE(playerLeft, MOVE_LEECH_SEED, target: opponentLeft); - MOVE(playerRight, MOVE_LEECH_SEED, target: opponentRight); - MOVE(opponentLeft, MOVE_LEECH_SEED, target: playerLeft); - MOVE(opponentRight, MOVE_LEECH_SEED, target: playerRight); + TURN { + MOVE(playerLeft, MOVE_LEECH_SEED, target: opponentLeft); + MOVE(playerRight, MOVE_LEECH_SEED, target: opponentRight); + MOVE(opponentLeft, MOVE_LEECH_SEED, target: playerLeft); + MOVE(opponentRight, MOVE_LEECH_SEED, target: playerRight); } } SCENE { ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, opponentRight); @@ -88,6 +88,24 @@ DOUBLE_BATTLE_TEST("Leech Seed will drain HP based on speed of the drained mon") } } +SINGLE_BATTLE_TEST("Leech Seeded recovers health through Substitute") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SUBSTITUTE); } + TURN { MOVE(player, MOVE_LEECH_SEED); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_LEECH_SEED, player); + HP_BAR(player); + HP_BAR(opponent); + HP_BAR(player); + } +} + TO_DO_BATTLE_TEST("Leech Seed doesn't affect already seeded targets") TO_DO_BATTLE_TEST("Leech Seed's effect is paused until a new battler replaces the original user's position") // Faint, can't be replaced, then revived. TO_DO_BATTLE_TEST("Leech Seed's effect pause still prevents it from being seeded again") From 014f289ea9e279d5f2008b0c8ebecdfc24d84c70 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Mon, 4 Aug 2025 11:41:43 +0100 Subject: [PATCH 29/31] Fixes Round and Fusion moves doubling power from previous turn's move (#7476) --- src/battle_script_commands.c | 7 ++++--- src/battle_util.c | 22 ++++++++++------------ 2 files changed, 14 insertions(+), 15 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6798b9bd9c..d749d450d7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6829,6 +6829,7 @@ static void Cmd_moveend(void) UpdateStallMons(); if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) || (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED)) + || gBattleStruct->pledgeMove == TRUE // Is the battler that uses the first Pledge move in the combo || gProtectStructs[gBattlerAttacker].nonVolatileStatusImmobility) gBattleStruct->battlerState[gBattlerAttacker].stompingTantrumTimer = 2; @@ -12194,7 +12195,7 @@ void BS_RemoveStockpileCounters(void) { NATIVE_ARGS(); - if (GetMoveEffect(gCurrentMove) == EFFECT_SWALLOW + if (GetMoveEffect(gCurrentMove) == EFFECT_SPIT_UP && gSpecialStatuses[gBattlerAttacker].parentalBondState == PARENTAL_BOND_1ST_HIT && IsBattlerAlive(gBattlerTarget)) { @@ -16996,7 +16997,7 @@ static void TryUpdateRoundTurnOrder(void) } // update turn order for round users - for (i = 0; roundUsers[i] != 0xFF && i < 3; i++) + for (i = 0; i < 3 && roundUsers[i] != 0xFF; i++) { gBattlerByTurnOrder[currRounder] = roundUsers[i]; gProtectStructs[roundUsers[i]].quash = TRUE; // Make it so their turn order can't be changed again @@ -17004,7 +17005,7 @@ static void TryUpdateRoundTurnOrder(void) } // Update turn order for non-round users - for (i = 0; nonRoundUsers[i] != 0xFF && i < 3; i++) + for (i = 0; i < 3 && nonRoundUsers[i] != 0xFF; i++) { gBattlerByTurnOrder[currRounder] = nonRoundUsers[i]; currRounder++; diff --git a/src/battle_util.c b/src/battle_util.c index e580c63616..fb28a6129c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8072,6 +8072,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData u32 battlerAtk = damageCalcData->battlerAtk; u32 battlerDef = damageCalcData->battlerDef; u32 move = damageCalcData->move; + u32 moveEffect = GetMoveEffect(move); u32 i; u32 basePower = GetMovePower(move); @@ -8083,7 +8084,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData if (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX) return GetMaxMovePower(move); - switch (GetMoveEffect(move)) + switch (moveEffect) { case EFFECT_PLEDGE: if (gBattleStruct->pledgeMove) @@ -8242,18 +8243,15 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData || gDisableStructs[battlerDef].isFirstTurn == 2) basePower *= 2; break; - case EFFECT_ROUND: - for (i = 0; i < gBattlersCount; i++) - { - if (i != battlerAtk && IsBattlerAlive(i) && GetMoveEffect(gLastUsedMove) == EFFECT_ROUND) - { - basePower *= 2; - break; - } - } - break; case EFFECT_FUSION_COMBO: - if (GetMoveEffect(gLastUsedMove) == EFFECT_FUSION_COMBO && move != gLastUsedMove) + if (move == gLastUsedMove) + break; + // fallthrough + case EFFECT_ROUND: + // don't double power due to previous turn's Round/Fusion move + if (gCurrentTurnActionNumber != 0 + && gActionsByTurnOrder[gCurrentTurnActionNumber - 1] == B_ACTION_USE_MOVE + && GetMoveEffect(gLastUsedMove) == moveEffect) basePower *= 2; break; case EFFECT_LASH_OUT: From 3dbcb2adb4a11ccec6b8a6547a401d52273d257a Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Mon, 4 Aug 2025 06:42:22 -0400 Subject: [PATCH 30/31] Add Synthesis + Utililty Umbrella test (#7472) Co-authored-by: ghoulslash --- test/battle/move_effect/synthesis.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/battle/move_effect/synthesis.c b/test/battle/move_effect/synthesis.c index 6799bd2870..954cf2e854 100644 --- a/test/battle/move_effect/synthesis.c +++ b/test/battle/move_effect/synthesis.c @@ -46,3 +46,21 @@ SINGLE_BATTLE_TEST("Synthesis recovers 1/4 of the user's max HP in Rain, Sandsto HP_BAR(player, damage: -(400 / 4)); } } + +SINGLE_BATTLE_TEST("Synthesis recovers regular amount in sandstorm if holding utility umbrella") +{ + u32 item; + PARAMETRIZE { item = ITEM_LIFE_ORB; } + PARAMETRIZE { item = ITEM_UTILITY_UMBRELLA; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); MaxHP(400); Item(item); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SANDSTORM); MOVE(player, MOVE_SYNTHESIS); } + } SCENE { + if (item != ITEM_UTILITY_UMBRELLA) + HP_BAR(player, damage: -(400 / 4)); + else + HP_BAR(player, damage: -(400 / 2)); + } +} From 523390ac5151b4a7bc70bc77baf901f10ee0e09e Mon Sep 17 00:00:00 2001 From: Kevin <85093953+kevinwklawrence@users.noreply.github.com> Date: Mon, 4 Aug 2025 07:49:05 -0400 Subject: [PATCH 31/31] Update how_to_new_pokemon.md (#7440) --- docs/tutorials/how_to_new_pokemon.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/tutorials/how_to_new_pokemon.md b/docs/tutorials/how_to_new_pokemon.md index de2d41d57c..37c0d28ae3 100644 --- a/docs/tutorials/how_to_new_pokemon.md +++ b/docs/tutorials/how_to_new_pokemon.md @@ -524,9 +524,9 @@ Edit [src/data/graphics/pokemon.h](https://github.com/rh-hideout/pokeemerald-exp ```diff #if P_FAMILY_PECHARUNT const u32 gMonFrontPic_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/front.4bpp.lz"); - const u32 gMonPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/normal.gbapal.lz"); + const u16 gMonPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/normal.gbapal"); const u32 gMonBackPic_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/back.4bpp.lz"); - const u32 gMonShinyPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/shiny.gbapal.lz"); + const u16 gMonShinyPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/shiny.gbapal"); const u8 gMonIcon_Pecharunt[] = INCBIN_U8("graphics/pokemon/pecharunt/icon.4bpp"); #if P_FOOTPRINTS const u8 gMonFootprint_Pecharunt[] = INCBIN_U8("graphics/pokemon/pecharunt/footprint.1bpp"); @@ -534,20 +534,20 @@ Edit [src/data/graphics/pokemon.h](https://github.com/rh-hideout/pokeemerald-exp #if OW_POKEMON_OBJECT_EVENTS const u32 gObjectEventPic_Pecharunt[] = INCBIN_COMP("graphics/pokemon/pecharunt/overworld.4bpp"); #if OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE - const u32 gOverworldPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/overworld_normal.gbapal.lz"); - const u32 gShinyOverworldPalette_Pecharunt[] = INCBIN_U32("graphics/pokemon/pecharunt/overworld_shiny.gbapal.lz"); + const u16 gOverworldPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/overworld_normal.gbapal"); + const u16 gShinyOverworldPalette_Pecharunt[] = INCBIN_U16("graphics/pokemon/pecharunt/overworld_shiny.gbapal"); #endif //OW_PKMN_OBJECTS_SHARE_PALETTES #endif //OW_POKEMON_OBJECT_EVENTS #endif //P_FAMILY_PECHARUNT const u32 gMonFrontPic_Egg[] = INCBIN_U32("graphics/pokemon/egg/anim_front.4bpp.lz"); - const u32 gMonPalette_Egg[] = INCBIN_U32("graphics/pokemon/egg/normal.gbapal.lz"); + const u16 gMonPalette_Egg[] = INCBIN_U16("graphics/pokemon/egg/normal.gbapal"); const u8 gMonIcon_Egg[] = INCBIN_U8("graphics/pokemon/egg/icon.4bpp"); + const u32 gMonFrontPic_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/anim_front.4bpp.lz"); + const u32 gMonBackPic_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/back.4bpp.lz"); -+ const u32 gMonPalette_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/normal.gbapal.lz"); -+ const u32 gMonShinyPalette_Mewthree[] = INCBIN_U32("graphics/pokemon/mewthree/shiny.gbapal.lz"); ++ const u16 gMonPalette_Mewthree[] = INCBIN_U16("graphics/pokemon/mewthree/normal.gbapal"); ++ const u16 gMonShinyPalette_Mewthree[] = INCBIN_U16("graphics/pokemon/mewthree/shiny.gbapal"); + const u8 gMonIcon_Mewthree[] = INCBIN_U8("graphics/pokemon/mewthree/icon.4bpp"); + const u8 gMonFootprint_Mewthree[] = INCBIN_U8("graphics/pokemon/mewthree/footprint.1bpp"); ```