From 98a8c38d17d2b7de7c1a3a0c8d9643a2ac2b9d93 Mon Sep 17 00:00:00 2001 From: PhlexPlexico <3514085+PhlexPlexico@users.noreply.github.com> Date: Fri, 17 Jan 2025 09:34:05 -0600 Subject: [PATCH] fix: Ingame Tracker Updates (#100) * TrackerUpdates1 Adds new location for "Inside Clock Tower" Attempts to add randomizer version * Include commit ID in menu, reduce the amount of text allowable in the commitId. * Update gfx.cpp add swamp skulltulas to dungeon item screen & fix keys * TrackerUpdates2 - Adds attempt at icon creation - Adds new row for Stray Fairies per dungeon - Adjusts spacing to accommidate double digit values in skulltula tokens - Adjusts placement of skulltula token counters to align with stray fairy counter - Adds Stray Fairy and Skulltula Icon to legend page * Update gfx.cpp update %02d to %02u * Update colouring and texture of sprites. * Include model destruction in attempt to hopefully resolve crashes. Attempting to reach parity of code to oot3dr. * Finally fix the boathouse override not working when defeating the Woodfall Temple. This will fix pictograph item gets from here on in. * Update spoiler log and bits being set for scenes. This should fix the spoiler log revealing for temples. --------- Co-authored-by: Tacoman369 <90735287+Tacoman369@users.noreply.github.com> --- code/include/game/common_data.h | 2 +- code/include/rnd/draw.h | 4 +- code/include/rnd/gfx.h | 2 +- code/include/rnd/icons.h | 22 +++++ code/include/rnd/models.h | 1 + code/include/rnd/spoiler_data.h | 2 + code/mm.ld | 4 +- code/source/asm/hooks.s | 8 ++ code/source/asm/patches.s | 8 +- code/source/rnd/gfx.cpp | 135 +++++++++++++++++++++++------- code/source/rnd/item_override.cpp | 4 +- code/source/rnd/models.cpp | 30 +++++-- code/source/rnd/savefile.cpp | 12 ++- 13 files changed, 181 insertions(+), 53 deletions(-) diff --git a/code/include/game/common_data.h b/code/include/game/common_data.h index 19d30030..dade03c8 100644 --- a/code/include/game/common_data.h +++ b/code/include/game/common_data.h @@ -312,7 +312,7 @@ namespace game { SkulltulaRegister skulltulas_collected; int anonymous_60; u8 gap1210[4]; - u8 defeated_bosses[4]; // like a history log of deafeated bosses or seen giants + int defeated_bosses; // like a history log of deafeated bosses or seen giants int previous_defeated_boss; // or last viewed giant cutscene, values 4 and greater makes // woodfall giant repeat for all temples. // u8 gap1221[3]; diff --git a/code/include/rnd/draw.h b/code/include/rnd/draw.h index bdf4d682..3dd1703d 100644 --- a/code/include/rnd/draw.h +++ b/code/include/rnd/draw.h @@ -98,7 +98,9 @@ typedef enum { ICON_BUTTON_FACEH, ICON_BUTTON_FACEV, ICON_BUTTON_JOYSTICK, - ICONS_COUNT + ICON_SKULLTULA, + ICON_FAIRY, + ICON_COUNT } Draw_IconType; void Draw_Lock(void); diff --git a/code/include/rnd/gfx.h b/code/include/rnd/gfx.h index 66f0b1a6..45e8b3bd 100644 --- a/code/include/rnd/gfx.h +++ b/code/include/rnd/gfx.h @@ -57,10 +57,10 @@ namespace rnd { } GfxPage; void Gfx_Init(void); - static u8 openingButton(); extern "C" void Gfx_Update(); extern "C" void Gfx_SleepQueryCallback(); extern "C" void Gfx_AwakeCallback(); + void* getExpHeapPtr(); } // namespace rnd diff --git a/code/include/rnd/icons.h b/code/include/rnd/icons.h index c10b236c..bbb7c195 100644 --- a/code/include/rnd/icons.h +++ b/code/include/rnd/icons.h @@ -285,5 +285,27 @@ static const unsigned char rIcons[][ICON_HEIGHT] = {{ 0x44, /* 01000100 */ 0x38, /* 00111000 */ 0x00, /* 00000000 */ + }, + { + /* Gold Skulltula Token */ + 0x00, /* 00000000 */ + 0x38, /* 00111000 */ + 0x44, /* 01000100 */ + 0x6c, /* 01101100 */ + 0x54, /* 01010100 */ + 0x28, /* 00101000 */ + 0x00, /* 00000000 */ + 0x00, /* 00000000 */ + }, + { + /* Stray Fairy */ + 0x00, /* 00000000 */ + 0x44, /* 01000100 */ + 0x28, /* 00101000 */ + 0x38, /* 00111000 */ + 0x38, /* 00111000 */ + 0x10, /* 00010000 */ + 0x2c, /* 00101100 */ + 0x00, /* 00000000 */ }}; #endif \ No newline at end of file diff --git a/code/include/rnd/models.h b/code/include/rnd/models.h index 8c17fc05..df2f5888 100644 --- a/code/include/rnd/models.h +++ b/code/include/rnd/models.h @@ -1,6 +1,7 @@ #ifndef _RND_MODELS_H_ #define _RND_MODELS_H_ #include "game/actor.h" +#include "rnd/gfx.h" #include "rnd/item_table.h" #include "rnd/objects.h" #include "z3d/z3DVec.h" diff --git a/code/include/rnd/spoiler_data.h b/code/include/rnd/spoiler_data.h index b467bca6..31a19ce3 100644 --- a/code/include/rnd/spoiler_data.h +++ b/code/include/rnd/spoiler_data.h @@ -32,6 +32,7 @@ namespace rnd { // Location groups for checks, used to group the checks by logical location typedef enum { GROUP_NO_GROUP, + GROUP_INSIDE_CLOCKTOWER, GROUP_S_CLOCK_TOWN, GROUP_LAUNDRY_POOL, GROUP_E_CLOCK_TOWN, @@ -111,6 +112,7 @@ namespace rnd { char StringData[SPOILER_STRING_DATA_SIZE]; u16 GroupItemCounts[SPOILER_COLLECTION_GROUP_COUNT]; u16 GroupOffsets[SPOILER_COLLECTION_GROUP_COUNT]; + char randoVersion[14]; } SpoilerData; typedef struct { diff --git a/code/mm.ld b/code/mm.ld index 1e825e84..b54abdc3 100644 --- a/code/mm.ld +++ b/code/mm.ld @@ -653,9 +653,9 @@ SECTIONS{ *(.patch_HandleOcarinaHooks) } - /* .patch_RemoveWoodfallClearConditionFromBoatHouse 0x6737E8 : { + .patch_RemoveWoodfallClearConditionFromBoatHouse 0x39655C : { *(.patch_RemoveWoodfallClearConditionFromBoatHouse) - } */ + } . = 0x61CD8C; /* Addr already 4 byte aligned! */ diff --git a/code/source/asm/hooks.s b/code/source/asm/hooks.s index 334ae43b..ee374a2f 100644 --- a/code/source/asm/hooks.s +++ b/code/source/asm/hooks.s @@ -291,6 +291,14 @@ hook_CheckMoTSetting: bl SettingsMaskOfTruthCheck b 0x35C42C +.global hook_RemoveWoodfallClearConditionFromBoatHouse +hook_RemoveWoodfallClearConditionFromBoatHouse: + push {r0-r12, lr} + bl RemoveBoathouseRestriction + pop {r0-r12,lr} + cmp r0,#0x2 + bx lr + .section .loader .global hook_into_loader hook_into_loader: diff --git a/code/source/asm/patches.s b/code/source/asm/patches.s index c80d2cc5..e6af9e79 100644 --- a/code/source/asm/patches.s +++ b/code/source/asm/patches.s @@ -289,10 +289,10 @@ RemoveJimWhenExitingHideout_patch: @ and should always evaluate to false. @ https://github.com/zeldaret/mm/blob/6541532abb5c03088ad67748bbb23965c654127e/src/overlays/actors/ovl_En_Dnh/z_en_dnh.c#L21 @ https://github.com/zeldaret/mm/blob/main/include/z64msgevent.h#L354 -@ .section .patch_RemoveWoodfallClearConditionFromBoatHouse -@ .global patch_RemoveWoodfallClearConditionFromBoatHouse -@ patch_RemoveWoodfallClearConditionFromBoatHouse: -@ .byte 0x0C +.section .patch_RemoveWoodfallClearConditionFromBoatHouse +.global patch_RemoveWoodfallClearConditionFromBoatHouse +patch_RemoveWoodfallClearConditionFromBoatHouse: + bl hook_RemoveWoodfallClearConditionFromBoatHouse .section .patch_loader .global loader_patch diff --git a/code/source/rnd/gfx.cpp b/code/source/rnd/gfx.cpp index 2bb23589..86d8c634 100644 --- a/code/source/rnd/gfx.cpp +++ b/code/source/rnd/gfx.cpp @@ -20,13 +20,15 @@ namespace rnd { u32 pressed; bool handledInput; const char* spoilerCollectionGroupNames[] = { - "All Item Locations", "South Clock Town", "Laundry Pool", "East Clock Town", "StockPotInn", - "West Clock Town", "North Clock Town", "Termina Field", "Southern Swamp", "Deku Palace", - "Woodfall", "Snowhead", "Mountain Village", "Twin Islands", "Goron Village", - "Milk Road", "Romani Ranch", "Great Bay Coast", "Pinnacle Rock", "Zora Cape", - "Zora Hall", "Ikana Canyon", "Ikana Graveyard", "Stone Tower", "Woodfall Temple", - "Snowhead Temple", "Great Bay Temple", "Stone Tower Temple", "Pirate Fortress", "Beneath the Well", - "Ikana Castle", "Secret Shrine", "The Moon", "Swamp Skulltula House", "Ocean Skulltula House", + "All Item Locations", "Inside Clock Tower", "South Clock Town", "Laundry Pool", + "East Clock Town", "StockPotInn", "West Clock Town", "North Clock Town", + "Termina Field", "Southern Swamp", "Deku Palace", "Woodfall", + "Snowhead", "Mountain Village", "Twin Islands", "Goron Village", + "Milk Road", "Romani Ranch", "Great Bay Coast", "Pinnacle Rock", + "Zora Cape", "Zora Hall", "Ikana Canyon", "Ikana Graveyard", + "Stone Tower", "Woodfall Temple", "Snowhead Temple", "Great Bay Temple", + "Stone Tower Temple", "Pirate Fortress", "Beneath the Well", "Ikana Castle", + "Secret Shrine", "The Moon", "Swamp Skulltula House", "Ocean Skulltula House", }; static s8 spoilerGroupDungeonIds[] = { @@ -54,43 +56,49 @@ namespace rnd { -1, -1, -1, - GROUP_DUNGEON_WOODFALL_TEMPLE, - GROUP_DUNGEON_SNOWHEAD_TEMPLE, - GROUP_DUNGEON_GREAT_BAY, - GROUP_DUNGEON_STONE_TOWER, - GROUP_DUNGEON_PIRATE_FORTRESS, - GROUP_DUNGEON_BENEATH_THE_WELL, - GROUP_DUNGEON_IKANA_CASTLE, - GROUP_DUNGEON_SECRET_SHRINE, - GROUP_DUNGEON_THE_MOON, - GROUP_SWAMP_SKULLTULA_HOUSE, - GROUP_OCEAN_SKULLTULA_HOUSE, + -1, + DUNGEON_WOODFALL, + DUNGEON_SNOWHEAD, + DUNGEON_GREAT_BAY, + DUNGEON_STONE_TOWER, + -1, + -1, + -1, + -1, + -1, + -1, + -1, }; static bool IsDungeonDiscovered(s8 dungeonId) { game::SaveData& saveData = game::GetCommonData().save; + u8 sceneId = 0x0; + bool hasMap = 0; if (dungeonId == DUNGEON_THE_MOON) { return false; } - - u8 idToModeKnown[] = {0, 1, 2, 3, 4, 5, 6, 7, 8}; - if (idToModeKnown[dungeonId]) { - return true; - } - - // A dungeon is considered discovered if we've visited the dungeon, have the map, - // Or known bc of settings - bool hasMap = 0; - if (dungeonId == 0) { + // A dungeon is considered discovered if we've visited the dungeon or have the map, + // Check for Woodfall Temple Map + if (dungeonId == DUNGEON_WOODFALL) { hasMap = saveData.inventory.woodfall_dungeon_items.map.Value(); - } else if (dungeonId == 1) { + sceneId = 0x1B; + } + // Check for Snowhead Temple Map + else if (dungeonId == DUNGEON_SNOWHEAD) { hasMap = saveData.inventory.snowhead_dungeon_items.map.Value(); - } else if (dungeonId == 2) { + sceneId = 0x21; + } + // Check for Great Bay Temple Map + else if (dungeonId == DUNGEON_GREAT_BAY) { hasMap = saveData.inventory.great_bay_dungeon_items.map.Value(); - } else if (dungeonId == 3) { + sceneId = 0x49; + } + // Check for Stone Tower Temple Map + else if (dungeonId == DUNGEON_STONE_TOWER) { hasMap = saveData.inventory.stone_tower_dungeon_items.map.Value(); + sceneId = 0x16; } - return (hasMap = 1); // to-do: check overworld map for GB & Ikana areas for other dungeons. & scene check. + return hasMap == 1 || SaveFile_GetIsSceneDiscovered(sceneId); } static bool CanShowSpoilerGroup(SpoilerCollectionCheckGroup group) { @@ -203,6 +211,12 @@ namespace rnd { static void Gfx_DrawSeedHash(void) { u8 offsetY = 0; + + Draw_DrawString(10, 16 + (SPACING_Y * offsetY++), COLOR_TITLE, "Randomizer Version:"); + Draw_DrawFormattedString(10 + (SPACING_X * 4), 16 + (SPACING_Y * offsetY++), COLOR_WHITE, "%s", + gSpoilerData.randoVersion); + offsetY++; + Draw_DrawFormattedString(10, 16 + (SPACING_Y * offsetY++), COLOR_TITLE, "Seed Hash:"); for (u32 hashIndex = 0; hashIndex < ARR_SIZE(gSettingsContext.hashIndexes); ++hashIndex) { Draw_DrawFormattedString(10 + (SPACING_X * 4), 16 + (SPACING_Y * offsetY++), COLOR_WHITE, "%s", @@ -227,6 +241,8 @@ namespace rnd { Draw_DrawString(10, 16 + (spacingY * offsetY++), COLOR_TITLE, "Dungeon Items Legend"); offsetY++; + Draw_DrawIcon(10, 16 + (spacingY * offsetY), COLOR_PINK, ICON_FAIRY); + Draw_DrawString(24, 16 + (spacingY * offsetY++), COLOR_WHITE, "Stray Fairies: Have / Total"); Draw_DrawIcon(10, 16 + (spacingY * offsetY), COLOR_WHITE, ICON_SMALL_KEY); Draw_DrawString(24, 16 + (spacingY * offsetY++), COLOR_WHITE, "Small Keys: Have / Found"); Draw_DrawIcon(10, 16 + (spacingY * offsetY), COLOR_ICON_BOSS_KEY, ICON_BOSS_KEY); @@ -242,10 +258,14 @@ namespace rnd { Draw_DrawString(24, 16 + (spacingY * offsetY++), COLOR_WHITE, "Barren Location"); Draw_DrawString(10, 16 + (spacingY * offsetY), COLOR_WHITE, "-"); Draw_DrawString(24, 16 + (spacingY * offsetY++), COLOR_WHITE, "Non-WotH / Non-Barren Location"); + offsetY++; + Draw_DrawIcon(10, 16 + (spacingY * offsetY), COLOR_YELLOW, ICON_SKULLTULA); + Draw_DrawString(24, 16 + (spacingY * offsetY++), COLOR_WHITE, "Skulltula Token(s)"); return; } Draw_DrawString(10, 16, COLOR_TITLE, "Dungeon Items"); // Draw header icons + Draw_DrawIcon(182, 16, COLOR_PINK, ICON_FAIRY); Draw_DrawIcon(214, 16, COLOR_WHITE, ICON_SMALL_KEY); Draw_DrawIcon(240, 16, COLOR_WHITE, ICON_BOSS_KEY); Draw_DrawIcon(260, 16, COLOR_WHITE, ICON_MAP); @@ -298,6 +318,38 @@ namespace rnd { Draw_DrawString(24, yPos, COLOR_WHITE, DungeonNames[dungeonId]); + // Stray Fairies + if (dungeonId <= DUNGEON_STONE_TOWER) { + u8 straysHave = 0; + if ((dungeonId == DUNGEON_WOODFALL)) { + straysHave = saveData.inventory.woodfall_fairies == 255 ? 0 : saveData.inventory.woodfall_fairies; + } + if ((dungeonId == DUNGEON_SNOWHEAD)) { + straysHave = saveData.inventory.snowhead_fairies == 255 ? 0 : saveData.inventory.snowhead_fairies; + } + if ((dungeonId == DUNGEON_GREAT_BAY)) { + straysHave = saveData.inventory.great_bay_fairies == 255 ? 0 : saveData.inventory.great_bay_fairies; + } + if ((dungeonId == DUNGEON_STONE_TOWER)) { + straysHave = saveData.inventory.stone_tower_fairies == 255 ? 0 : saveData.inventory.stone_tower_fairies; + } + Draw_DrawFormattedString(170, yPos, straysHave > 0 ? COLOR_WHITE : COLOR_DARK_GRAY, "%02u", straysHave); + Draw_DrawString(182, yPos, COLOR_WHITE, "/"); + + // u8 fairiesFound = Dungeon_FoundSmallKeys(dungeonId); + // if ((gSettingsContext.keysanity == u8(rnd::KeysanitySetting::KEYSANITY_START_WITH)) && + // (dungeonId <= DUNGEON_STONE_TOWER)) { + // keysFound += Dungeon_KeyAmount(dungeonId); + // } Todo : Stray Fairies - Start With + u32 straysTotalColor = COLOR_WHITE; + if ((straysHave >= 15) && IsDungeonDiscovered(dungeonId)) { + straysTotalColor = COLOR_GREEN; + } else if (straysHave == 0) { + straysTotalColor = COLOR_DARK_GRAY; + } + Draw_DrawFormattedString(188, yPos, straysTotalColor, "15"); + } + // Small Keys if (dungeonId <= DUNGEON_STONE_TOWER) { u8 keysHave = 0; @@ -358,6 +410,21 @@ namespace rnd { yPos += spacingY; } + + // Skulltulas + u8 swampTokensHave = saveData.skulltulas_collected.swamp_count; + u8 oceanTokensHave = saveData.skulltulas_collected.ocean_count; + yPos += spacingY; + Draw_DrawString(10, yPos, COLOR_TITLE, "Skulltula Tokens"); + Draw_DrawIcon(182, yPos, COLOR_YELLOW, ICON_SKULLTULA); + yPos += spacingY; + Draw_DrawString(24, yPos, COLOR_WHITE, "Swamp Skulltula Tokens"); + Draw_DrawFormattedString(170, yPos, swampTokensHave > 0 ? COLOR_WHITE : COLOR_DARK_GRAY, "%02u", swampTokensHave); + Draw_DrawString(182, yPos, COLOR_WHITE, "/30"); + yPos += spacingY; + Draw_DrawString(24, yPos, COLOR_WHITE, "Ocean Skulltula Tokens"); + Draw_DrawFormattedString(170, yPos, oceanTokensHave > 0 ? COLOR_WHITE : COLOR_DARK_GRAY, "%02u", oceanTokensHave); + Draw_DrawString(182, yPos, COLOR_WHITE, "/30"); } static void Gfx_DrawSpoilerData(void) { @@ -782,4 +849,8 @@ namespace rnd { } } + void* getExpHeapPtr() { + return util::GetPointer(0x1F1BF8)(); + } + } // namespace rnd diff --git a/code/source/rnd/item_override.cpp b/code/source/rnd/item_override.cpp index ee8b8d92..f666b120 100644 --- a/code/source/rnd/item_override.cpp +++ b/code/source/rnd/item_override.cpp @@ -52,8 +52,8 @@ namespace rnd { rItemOverrides[0].value.looksLikeItemId = 0x56; rItemOverrides[1].key.scene = 0x6F; rItemOverrides[1].key.type = ItemOverride_Type::OVR_COLLECTABLE; - rItemOverrides[1].value.getItemId = 0x46; - rItemOverrides[1].value.looksLikeItemId = 0x46; + rItemOverrides[1].value.getItemId = 0x44; + rItemOverrides[1].value.looksLikeItemId = 0x44; rItemOverrides[2].key.scene = 0x12; rItemOverrides[2].key.type = ItemOverride_Type::OVR_COLLECTABLE; rItemOverrides[2].value.getItemId = 0x37; diff --git a/code/source/rnd/models.cpp b/code/source/rnd/models.cpp index 9b89fbec..9173275e 100644 --- a/code/source/rnd/models.cpp +++ b/code/source/rnd/models.cpp @@ -20,6 +20,15 @@ namespace rnd { util::GetPointer(0x1FEAB0)(fromMtx, toMtx); } + void TexAnim_Spawn(void* skelModel, int objectId) { + util::GetPointer(0x12A3DC)(skelModel, objectId); + } + + void SkeletonAnimationModel_Destroy(void* skelModel) { + void* expHeap = getExpHeapPtr(); + util::GetPointer(0x1EE6C4)(expHeap, skelModel); + } + /** Used to set the mesh for rupees and stray fairies. * @param drawItemId Value from DrawGraphicItemID enum, but decreased by one for some reason. */ @@ -66,9 +75,8 @@ namespace rnd { model->objectBankIdx = objectBankIdx; } - void Model_SetAnim(void* model, s16 objectId, u32 objectAnimIdx) { - // void* cmabMan = ExtendedObject_GetCMABByIndex(objectId, objectAnimIdx); - // TexAnim_Spawn((model+0x0C), cmabMan); + void Model_SetAnim(void* model, s16 objectId) { + TexAnim_Spawn(model, objectId); } void Model_SetMatrix(Model* model) { @@ -110,8 +118,14 @@ namespace rnd { if (model->saModel != NULL) Model_SetMtxAndModel(model->saModel, &tmpMtx); - if (model->saModel2 != NULL) + if (model->saModel2 != NULL) { + float tmpY = model->actor->actor_shape.rot.y; + if (model->objectId != 0x0020) { + model->actor->actor_shape.rot.y = GetContext().gctx->main_camera.field_11C.y; + } Model_SetMtxAndModel(model->saModel2, &tmpMtx); + model->actor->actor_shape.rot.y = tmpY; + } } void Model_Init(Model* model, game::GlobalContext* globalCtx) { @@ -120,12 +134,12 @@ namespace rnd { if (model->itemRow->objectModelIdx2 >= 0) { model->saModel2 = SkeletonAnimationModel_Spawn(model->actor, globalCtx, objectId, model->itemRow->objectModelIdx2); - // Model_SetAnim(model->saModel2, model->itemRow->objectId, model->itemRow->cmabIndex2); + Model_SetAnim(model->saModel2, model->itemRow->objectId); } SkeletonAnimationModel_SetMeshByDrawItemID(model->saModel, (s32)model->itemRow->graphicId - 1); if (model->itemRow->objectModelIdx != 0xFF) { - // Model_SetAnim(model->saModel, model->itemRow->objectId, model->itemRow->cmabIndex); + Model_SetAnim(model->saModel, model->itemRow->objectId); // model->saModel->unk_0C->animSpeed = 2.0f; // model->saModel->unk_0C->animMode = 1; } @@ -135,11 +149,11 @@ namespace rnd { void Model_Destroy(Model* model) { if (model->saModel != NULL) { - // TODO: figure out how to properly destroy the model, if it's needed - // model->saModel->vtbl->destroy_function(model->saModel); + SkeletonAnimationModel_Destroy(model->saModel); model->saModel = NULL; } if (model->saModel2 != NULL) { + SkeletonAnimationModel_Destroy(model->saModel2); model->saModel2 = NULL; } model->actor = NULL; diff --git a/code/source/rnd/savefile.cpp b/code/source/rnd/savefile.cpp index 7fd9dddf..c37d9b11 100644 --- a/code/source/rnd/savefile.cpp +++ b/code/source/rnd/savefile.cpp @@ -843,7 +843,7 @@ namespace rnd { u32 numBits = sizeof(u32) * 8; u32 idx = sceneNum / numBits; if (idx < SAVEFILE_SCENES_DISCOVERED_IDX_COUNT) { - u32 bit = 1 << (sceneNum - (idx * numBits)); + u32 bit = 1 << abs(sceneNum - (idx * numBits)); return (gExtSaveData.scenesDiscovered[idx] & bit) != 0; } return 0; @@ -857,7 +857,7 @@ namespace rnd { u16 numBits = sizeof(u32) * 8; u32 idx = sceneNum / numBits; if (idx < SAVEFILE_SCENES_DISCOVERED_IDX_COUNT) { - u32 sceneBit = 1 << (sceneNum - (idx * numBits)); + u32 sceneBit = 1 << abs(sceneNum - (idx * numBits)); gExtSaveData.scenesDiscovered[idx] |= sceneBit; } } @@ -1064,6 +1064,14 @@ namespace rnd { return; } } + + void RemoveBoathouseRestriction() { + int* msgDataPtr = (int*)0x6737E8; + if (gExtSaveData.givenItemChecks.odolwaDefeated == 1 && gExtSaveData.givenItemChecks.enTruGivenItem == 0) + util::Write(msgDataPtr, 0x0, 0x0C); + else + util::Write(msgDataPtr, 0x0, 0x14); + } } } // namespace rnd