From 8f55dd0624b35c14a38a1a202acaa22b132fa71d Mon Sep 17 00:00:00 2001 From: Garrett Cox Date: Mon, 8 Aug 2022 14:07:02 -0500 Subject: [PATCH] Add support for shuffling maps and compasses --- soh/include/z64item.h | 42 +++++++ soh/include/z64player.h | 2 +- .../randomizer/3drando/settings.cpp | 9 +- .../Enhancements/randomizer/randomizer.cpp | 100 +++++++++++---- .../Enhancements/randomizer/randomizerTypes.h | 2 +- soh/src/code/z_message_PAL.c | 80 ++++++++++++ soh/src/code/z_parameter.c | 115 ++++++++++++------ soh/src/code/z_sram.c | 96 +++++++++------ .../actors/ovl_player_actor/z_player.c | 22 ++++ 9 files changed, 359 insertions(+), 109 deletions(-) diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 8883eb8ca7..3a409a7056 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -268,6 +268,26 @@ typedef enum { /* 0xB1 */ ITEM_SPIRIT_TEMPLE_BOSS_KEY, /* 0xB2 */ ITEM_SHADOW_TEMPLE_BOSS_KEY, /* 0xB3 */ ITEM_GANONS_CASTLE_BOSS_KEY, + /* 0xB4 */ ITEM_DEKU_TREE_MAP, + /* 0xB5 */ ITEM_DODONGOS_CAVERN_MAP, + /* 0xB6 */ ITEM_JABU_JABUS_BELLY_MAP, + /* 0xB7 */ ITEM_FOREST_TEMPLE_MAP, + /* 0xB8 */ ITEM_FIRE_TEMPLE_MAP, + /* 0xB9 */ ITEM_WATER_TEMPLE_MAP, + /* 0xBA */ ITEM_SPIRIT_TEMPLE_MAP, + /* 0xBB */ ITEM_SHADOW_TEMPLE_MAP, + /* 0xBC */ ITEM_BOTTOM_OF_THE_WELL_MAP, + /* 0xBD */ ITEM_ICE_CAVERN_MAP, + /* 0xBE */ ITEM_DEKU_TREE_COMPASS, + /* 0xBF */ ITEM_DODONGOS_CAVERN_COMPASS, + /* 0xC0 */ ITEM_JABU_JABUS_BELLY_COMPASS, + /* 0xC1 */ ITEM_FOREST_TEMPLE_COMPASS, + /* 0xC2 */ ITEM_FIRE_TEMPLE_COMPASS, + /* 0xC3 */ ITEM_WATER_TEMPLE_COMPASS, + /* 0xC4 */ ITEM_SPIRIT_TEMPLE_COMPASS, + /* 0xC5 */ ITEM_SHADOW_TEMPLE_COMPASS, + /* 0xC6 */ ITEM_BOTTOM_OF_THE_WELL_COMPASS, + /* 0xC7 */ ITEM_ICE_CAVERN_COMPASS, /* 0xFC */ ITEM_LAST_USED = 0xFC, /* 0xFE */ ITEM_NONE_FE = 0xFE, /* 0xFF */ ITEM_NONE = 0xFF @@ -461,6 +481,28 @@ typedef enum { /* 0xAC */ GI_SHADOW_TEMPLE_BOSS_KEY, /* 0xAD */ GI_GANONS_CASTLE_BOSS_KEY, + /* 0xAE */ GI_DEKU_TREE_MAP, + /* 0xAF */ GI_DODONGOS_CAVERN_MAP, + /* 0xB0 */ GI_JABU_JABUS_BELLY_MAP, + /* 0xB1 */ GI_FOREST_TEMPLE_MAP, + /* 0xB2 */ GI_FIRE_TEMPLE_MAP, + /* 0xB3 */ GI_WATER_TEMPLE_MAP, + /* 0xB4 */ GI_SPIRIT_TEMPLE_MAP, + /* 0xB5 */ GI_SHADOW_TEMPLE_MAP, + /* 0xB6 */ GI_BOTTOM_OF_THE_WELL_MAP, + /* 0xB7 */ GI_ICE_CAVERN_MAP, + + /* 0xB8 */ GI_DEKU_TREE_COMPASS, + /* 0xB9 */ GI_DODONGOS_CAVERN_COMPASS, + /* 0xBA */ GI_JABU_JABUS_BELLY_COMPASS, + /* 0xBB */ GI_FOREST_TEMPLE_COMPASS, + /* 0xBC */ GI_FIRE_TEMPLE_COMPASS, + /* 0xBD */ GI_WATER_TEMPLE_COMPASS, + /* 0xBE */ GI_SPIRIT_TEMPLE_COMPASS, + /* 0xBF */ GI_SHADOW_TEMPLE_COMPASS, + /* 0xC0 */ GI_BOTTOM_OF_THE_WELL_COMPASS, + /* 0xC1 */ GI_ICE_CAVERN_COMPASS, + /* 0xAE */ GI_MAX } GetItemID; diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 8be7056742..08c77a0eec 100644 --- a/soh/include/z64player.h +++ b/soh/include/z64player.h @@ -13,7 +13,7 @@ typedef struct { /* 0x04 */ u16 objectId; } GetItemEntry; // size = 0x06 -extern GetItemEntry sGetItemTable[175]; +extern GetItemEntry sGetItemTable[195]; typedef enum { /* 0 */ PLAYER_SWORD_NONE, diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index e6a4f1385d..d310717dbb 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2544,14 +2544,7 @@ namespace Settings { StartingDekuShield.SetSelectedIndex(cvarSettings[RSK_STARTING_DEKU_SHIELD]); StartingKokiriSword.SetSelectedIndex(cvarSettings[RSK_STARTING_KOKIRI_SWORD]); - if(cvarSettings[RSK_STARTING_MAPS_COMPASSES]) { - // "Start With" is index 0 - MapsAndCompasses.SetSelectedIndex(0); - } else { - // We don't support maps/compasses outside of their own dungeon yet - // "Own Dungeon" is index 2 - MapsAndCompasses.SetSelectedIndex(2); - } + MapsAndCompasses.SetSelectedIndex(cvarSettings[RSK_STARTING_MAPS_COMPASSES]); StartingConsumables.SetSelectedIndex(cvarSettings[RSK_STARTING_CONSUMABLES]); StartingMaxRupees.SetSelectedIndex(cvarSettings[RSK_FULL_WALLETS]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b3ab450284..d4b2874c6c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -985,6 +985,18 @@ std::unordered_map itemIdToModel = { { GI_NONE, GID_MAXIMUM }, { GI_REQUIEM_OF_SPIRIT, GID_SONG_REQUIEM }, { GI_NOCTURNE_OF_SHADOW, GID_SONG_NOCTURNE }, { GI_PRELUDE_OF_LIGHT, GID_SONG_PRELUDE }, + { GI_DOUBLE_DEFENSE, GID_HEART_CONTAINER }, + { GI_STONE_KOKIRI, GID_KOKIRI_EMERALD }, + { GI_STONE_GORON, GID_GORON_RUBY }, + { GI_STONE_ZORA, GID_ZORA_SAPPHIRE }, + { GI_MEDALLION_FOREST, GID_MEDALLION_FOREST }, + { GI_MEDALLION_FIRE, GID_MEDALLION_FIRE }, + { GI_MEDALLION_WATER, GID_MEDALLION_WATER }, + { GI_MEDALLION_SPIRIT, GID_MEDALLION_SPIRIT }, + { GI_MEDALLION_SHADOW, GID_MEDALLION_SHADOW }, + { GI_MEDALLION_LIGHT, GID_MEDALLION_LIGHT }, + { GI_SINGLE_MAGIC, GID_MAGIC_SMALL }, + { GI_DOUBLE_MAGIC, GID_MAGIC_LARGE }, { GI_GERUDO_FORTRESS_SMALL_KEY, GID_KEY_SMALL }, { GI_FOREST_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, { GI_FIRE_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, @@ -1000,18 +1012,26 @@ std::unordered_map itemIdToModel = { { GI_NONE, GID_MAXIMUM }, { GI_SPIRIT_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, { GI_SHADOW_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, { GI_GANONS_CASTLE_BOSS_KEY, GID_KEY_BOSS }, - { GI_DOUBLE_DEFENSE, GID_HEART_CONTAINER }, - { GI_STONE_KOKIRI, GID_KOKIRI_EMERALD }, - { GI_STONE_GORON, GID_GORON_RUBY }, - { GI_STONE_ZORA, GID_ZORA_SAPPHIRE }, - { GI_MEDALLION_FOREST, GID_MEDALLION_FOREST }, - { GI_MEDALLION_FIRE, GID_MEDALLION_FIRE }, - { GI_MEDALLION_WATER, GID_MEDALLION_WATER }, - { GI_MEDALLION_SPIRIT, GID_MEDALLION_SPIRIT }, - { GI_MEDALLION_SHADOW, GID_MEDALLION_SHADOW }, - { GI_MEDALLION_LIGHT, GID_MEDALLION_LIGHT }, - { GI_SINGLE_MAGIC, GID_MAGIC_SMALL }, - { GI_DOUBLE_MAGIC, GID_MAGIC_LARGE }, + { GI_DEKU_TREE_MAP, GID_DUNGEON_MAP }, + { GI_DODONGOS_CAVERN_MAP, GID_DUNGEON_MAP }, + { GI_JABU_JABUS_BELLY_MAP, GID_DUNGEON_MAP }, + { GI_FOREST_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_FIRE_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_WATER_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_SPIRIT_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_SHADOW_TEMPLE_MAP, GID_DUNGEON_MAP }, + { GI_BOTTOM_OF_THE_WELL_MAP, GID_DUNGEON_MAP }, + { GI_ICE_CAVERN_MAP, GID_DUNGEON_MAP }, + { GI_DEKU_TREE_COMPASS, GID_COMPASS }, + { GI_DODONGOS_CAVERN_COMPASS, GID_COMPASS }, + { GI_JABU_JABUS_BELLY_COMPASS, GID_COMPASS }, + { GI_FOREST_TEMPLE_COMPASS, GID_COMPASS }, + { GI_FIRE_TEMPLE_COMPASS, GID_COMPASS }, + { GI_WATER_TEMPLE_COMPASS, GID_COMPASS }, + { GI_SPIRIT_TEMPLE_COMPASS, GID_COMPASS }, + { GI_SHADOW_TEMPLE_COMPASS, GID_COMPASS }, + { GI_BOTTOM_OF_THE_WELL_COMPASS, GID_COMPASS }, + { GI_ICE_CAVERN_COMPASS, GID_COMPASS }, { GI_ICE_TRAP, GID_RUPEE_GOLD }, { GI_ICE_TRAP, GID_MAXIMUM }, { GI_TEXT_0, GID_MAXIMUM } }; @@ -1634,10 +1654,18 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { } break; case RSK_STARTING_MAPS_COMPASSES: - if(it.value() == "Own Dungeon") { - gSaveContext.randoSettings[index].value = 0; - } else if (it.value() == "Start With") { - gSaveContext.randoSettings[index].value = 1; + if(it.value() == "Start With") { + gSaveContext.randoSettings[index].value = 0; + } else if(it.value() == "Vanilla") { + gSaveContext.randoSettings[index].value = 1; + } else if(it.value() == "Own Dungeon") { + gSaveContext.randoSettings[index].value = 2; + } else if(it.value() == "Any Dungeon") { + gSaveContext.randoSettings[index].value = 3; + } else if(it.value() == "Overworld") { + gSaveContext.randoSettings[index].value = 4; + } else if(it.value() == "Anywhere") { + gSaveContext.randoSettings[index].value = 5; } break; case RSK_STARTING_DEKU_SHIELD: @@ -2300,30 +2328,47 @@ GetItemID Randomizer::GetItemFromGet(RandomizerGet randoGet, GetItemID ogItemId) case RG_PRELUDE_OF_LIGHT: return GI_PRELUDE_OF_LIGHT; - // todo implement dungeon-specific maps/compasses case RG_DEKU_TREE_MAP: + return GI_DEKU_TREE_MAP; case RG_DODONGOS_CAVERN_MAP: + return GI_DODONGOS_CAVERN_MAP; case RG_JABU_JABUS_BELLY_MAP: + return GI_JABU_JABUS_BELLY_MAP; case RG_FOREST_TEMPLE_MAP: + return GI_FOREST_TEMPLE_MAP; case RG_FIRE_TEMPLE_MAP: + return GI_FIRE_TEMPLE_MAP; case RG_WATER_TEMPLE_MAP: + return GI_WATER_TEMPLE_MAP; case RG_SPIRIT_TEMPLE_MAP: + return GI_SPIRIT_TEMPLE_MAP; case RG_SHADOW_TEMPLE_MAP: + return GI_SHADOW_TEMPLE_MAP; case RG_BOTTOM_OF_THE_WELL_MAP: + return GI_BOTTOM_OF_THE_WELL_MAP; case RG_ICE_CAVERN_MAP: - return GI_MAP; + return GI_ICE_CAVERN_MAP; case RG_DEKU_TREE_COMPASS: + return GI_DEKU_TREE_COMPASS; case RG_DODONGOS_CAVERN_COMPASS: + return GI_DODONGOS_CAVERN_COMPASS; case RG_JABU_JABUS_BELLY_COMPASS: + return GI_JABU_JABUS_BELLY_COMPASS; case RG_FOREST_TEMPLE_COMPASS: + return GI_FOREST_TEMPLE_COMPASS; case RG_FIRE_TEMPLE_COMPASS: + return GI_FIRE_TEMPLE_COMPASS; case RG_WATER_TEMPLE_COMPASS: + return GI_WATER_TEMPLE_COMPASS; case RG_SPIRIT_TEMPLE_COMPASS: + return GI_SPIRIT_TEMPLE_COMPASS; case RG_SHADOW_TEMPLE_COMPASS: + return GI_SHADOW_TEMPLE_COMPASS; case RG_BOTTOM_OF_THE_WELL_COMPASS: + return GI_BOTTOM_OF_THE_WELL_COMPASS; case RG_ICE_CAVERN_COMPASS: - return GI_COMPASS; + return GI_ICE_CAVERN_COMPASS; case RG_FOREST_TEMPLE_BOSS_KEY: return GI_FOREST_TEMPLE_BOSS_KEY; @@ -3518,7 +3563,7 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_SHUFFLE_KOKIRI_SWORD] = CVar_GetS32("gRandomizeShuffleKokiriSword", 0) || CVar_GetS32("gRandomizeStartingKokiriSword", 0); cvarSettings[RSK_STARTING_DEKU_SHIELD] = CVar_GetS32("gRandomizeStartingDekuShield", 0); - cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 0); + cvarSettings[RSK_STARTING_MAPS_COMPASSES] = CVar_GetS32("gRandomizeStartingMapsCompasses", 1); cvarSettings[RSK_SHUFFLE_DUNGEON_REWARDS] = CVar_GetS32("gRandomizeShuffleDungeonReward", 0); cvarSettings[RSK_SHUFFLE_SONGS] = CVar_GetS32("gRandomizeShuffleSongs", 0); cvarSettings[RSK_SHUFFLE_TOKENS] = CVar_GetS32("gRandomizeShuffleTokens", 0); @@ -3627,8 +3672,7 @@ void DrawRandoEditor(bool& open) { const char* randoShuffleAdultTrade[2] = { "Off", "On" }; // Shuffle Dungeon Items Settings - const char* randoShuffleMapsAndCompasses[6] = { "Own Dungeon", "Any Dungeon", "Overworld", - "Anywhere", "Start With", "Vanilla" }; + const char* randoShuffleMapsAndCompasses[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; const char* randoShuffleSmallKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; const char* randoShuffleGerudoFortressKeys[4] = { "Vanilla", "Any Dungeon", "Overworld", "Anywhere" }; const char* randoShuffleBossKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; @@ -4198,7 +4242,17 @@ void DrawRandoEditor(bool& open) { PaddedSeparator(); // Start with Maps & Compasses - SohImGui::EnhancementCheckbox(Settings::MapsAndCompasses.GetName().c_str(), "gRandomizeStartingMapsCompasses"); + ImGui::Text(Settings::MapsAndCompasses.GetName().c_str()); + InsertHelpHoverText( + "Own dungeon - Boss Keys can only appear in their respective dungeon.\n" + "\n" + "Any dungeon - Boss Keys can only appear inside of any dungon.\n" + "\n" + "Overworld - Boss Keys can only appear outside of dungeons.\n" + "\n" + "Anywhere - Boss Keys can appear anywhere in the world." + ); + SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 1); ImGui::PopItemWidth(); ImGui::EndTable(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 28a159bfeb..1f663123ae 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -971,7 +971,7 @@ typedef enum { RSK_STARTING_DEKU_SHIELD, RSK_STARTING_KOKIRI_SWORD, RSK_SHUFFLE_KOKIRI_SWORD, - RSK_STARTING_MAPS_COMPASSES, //RANDOTODO more options for this, rn it's just start with or own dungeon + RSK_STARTING_MAPS_COMPASSES, RSK_SHUFFLE_DUNGEON_REWARDS, RSK_SHUFFLE_SONGS, RSK_SHUFFLE_TOKENS, diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index b5444faac1..5c7bccac0a 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1801,6 +1801,86 @@ void Message_OpenText(GlobalContext* globalCtx, u16 textId) { break; } msgCtx->msgLength = font->msgLength = strlen(font->msgBuf); + } else if (gSaveContext.n64ddFlag && textId == 0x66 && GET_PLAYER(globalCtx)->getItemId >= GI_DEKU_TREE_MAP && GET_PLAYER(globalCtx)->getItemId <= GI_ICE_CAVERN_MAP) { + char* keyMsg; + switch (gSaveContext.language) { + case LANGUAGE_ENG: default: + switch (GET_PLAYER(globalCtx)->getItemId) { + case GI_DEKU_TREE_MAP: + keyMsg = "\x08You got the \x05\x42\Deku Tree Map\x05\x40!\x09\x02"; + break; + case GI_DODONGOS_CAVERN_MAP: + keyMsg = "\x08You got the \x05\x41\Dodongo's Cavern Map\x05\x40!\x09\x02"; + break; + case GI_JABU_JABUS_BELLY_MAP: + keyMsg = "\x08You got the \x05\x43\Jabu Jabu's Belly Map\x05\x40!\x09\x02"; + break; + case GI_FOREST_TEMPLE_MAP: + keyMsg = "\x08You got the \x05\x42\Forest Temple Map\x05\x40!\x09\x02"; + break; + case GI_FIRE_TEMPLE_MAP: + keyMsg = "\x08You got the \x05\x41\Fire Temple Map\x05\x40!\x09\x02"; + break; + case GI_WATER_TEMPLE_MAP: + keyMsg = "\x08You got the \x05\x43\Water Temple Map\x05\x40!\x09\x02"; + break; + case GI_SPIRIT_TEMPLE_MAP: + keyMsg = "\x08You got the \x05\x46\Spirit Temple Map\x05\x40!\x09\x02"; + break; + case GI_SHADOW_TEMPLE_MAP: + keyMsg = "\x08You got the \x05\x45\Shadow Temple Map\x05\x40!\x09\x02"; + break; + case GI_BOTTOM_OF_THE_WELL_MAP: + keyMsg = "\x08You got the \x05\x45\Bottom of the Well Map\x05\x40!\x09\x02"; + break; + case GI_ICE_CAVERN_MAP: + keyMsg = "\x08You got the \x05\x43\Ice Cavern Map\x05\x40!\x09\x02"; + break; + } + strcpy(font->msgBuf, keyMsg); + break; + } + msgCtx->msgLength = font->msgLength = strlen(font->msgBuf); + } else if (gSaveContext.n64ddFlag && textId == 0x67 && GET_PLAYER(globalCtx)->getItemId >= GI_DEKU_TREE_COMPASS && GET_PLAYER(globalCtx)->getItemId <= GI_ICE_CAVERN_COMPASS) { + char* keyMsg; + switch (gSaveContext.language) { + case LANGUAGE_ENG: default: + switch (GET_PLAYER(globalCtx)->getItemId) { + case GI_DEKU_TREE_COMPASS: + keyMsg = "\x08You got the \x05\x42\Deku Tree Compass\x05\x40!\x09\x02"; + break; + case GI_DODONGOS_CAVERN_COMPASS: + keyMsg = "\x08You got the \x05\x41\Dodongo's Cavern Compass\x05\x40!\x09\x02"; + break; + case GI_JABU_JABUS_BELLY_COMPASS: + keyMsg = "\x08You got the \x05\x43\Jabu Jabu's Belly Compass\x05\x40!\x09\x02"; + break; + case GI_FOREST_TEMPLE_COMPASS: + keyMsg = "\x08You got the \x05\x42\Forest Temple Compass\x05\x40!\x09\x02"; + break; + case GI_FIRE_TEMPLE_COMPASS: + keyMsg = "\x08You got the \x05\x41\Fire Temple Compass\x05\x40!\x09\x02"; + break; + case GI_WATER_TEMPLE_COMPASS: + keyMsg = "\x08You got the \x05\x43\Water Temple Compass\x05\x40!\x09\x02"; + break; + case GI_SPIRIT_TEMPLE_COMPASS: + keyMsg = "\x08You got the \x05\x46\Spirit Temple Compass\x05\x40!\x09\x02"; + break; + case GI_SHADOW_TEMPLE_COMPASS: + keyMsg = "\x08You got the \x05\x45\Shadow Temple Compass\x05\x40!\x09\x02"; + break; + case GI_BOTTOM_OF_THE_WELL_COMPASS: + keyMsg = "\x08You got the \x05\x45\Bottom of the Well Compass\x05\x40!\x09\x02"; + break; + case GI_ICE_CAVERN_COMPASS: + keyMsg = "\x08You got the \x05\x43\Ice Cavern Compass\x05\x40!\x09\x02"; + break; + } + strcpy(font->msgBuf, keyMsg); + break; + } + msgCtx->msgLength = font->msgLength = strlen(font->msgBuf); } else if (textId == 0xF8 && GET_PLAYER(globalCtx)->getItemId == GI_ICE_TRAP) { switch (gSaveContext.language) { case LANGUAGE_FRA: diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index a71c8a52c2..b121c97d3b 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1749,52 +1749,76 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { gSaveContext.inventory.dungeonItems[gSaveContext.mapIndex] |= gBitFlags[item - ITEM_KEY_BOSS]; } return ITEM_NONE; - } else if ((item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY)) { + } else if (item == ITEM_KEY_SMALL) { + if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) { + gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1; + return ITEM_NONE; + } else { + gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++; + return ITEM_NONE; + } + } else if ( + (item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY) || + (item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY) || + (item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP) || + (item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS) + ) { int mapIndex = gSaveContext.mapIndex; switch (item) { + case ITEM_DEKU_TREE_MAP: + case ITEM_DEKU_TREE_COMPASS: + mapIndex = SCENE_YDAN; + break; + case ITEM_DODONGOS_CAVERN_MAP: + case ITEM_DODONGOS_CAVERN_COMPASS: + mapIndex = SCENE_DDAN; + break; + case ITEM_JABU_JABUS_BELLY_MAP: + case ITEM_JABU_JABUS_BELLY_COMPASS: + mapIndex = SCENE_BDAN; + break; + case ITEM_FOREST_TEMPLE_MAP: + case ITEM_FOREST_TEMPLE_COMPASS: + case ITEM_FOREST_TEMPLE_SMALL_KEY: case ITEM_FOREST_TEMPLE_BOSS_KEY: mapIndex = SCENE_BMORI1; break; + case ITEM_FIRE_TEMPLE_MAP: + case ITEM_FIRE_TEMPLE_COMPASS: + case ITEM_FIRE_TEMPLE_SMALL_KEY: case ITEM_FIRE_TEMPLE_BOSS_KEY: mapIndex = SCENE_HIDAN; break; + case ITEM_WATER_TEMPLE_MAP: + case ITEM_WATER_TEMPLE_COMPASS: + case ITEM_WATER_TEMPLE_SMALL_KEY: case ITEM_WATER_TEMPLE_BOSS_KEY: mapIndex = SCENE_MIZUSIN; break; + case ITEM_SPIRIT_TEMPLE_MAP: + case ITEM_SPIRIT_TEMPLE_COMPASS: + case ITEM_SPIRIT_TEMPLE_SMALL_KEY: case ITEM_SPIRIT_TEMPLE_BOSS_KEY: mapIndex = SCENE_JYASINZOU; break; + case ITEM_SHADOW_TEMPLE_MAP: + case ITEM_SHADOW_TEMPLE_COMPASS: + case ITEM_SHADOW_TEMPLE_SMALL_KEY: case ITEM_SHADOW_TEMPLE_BOSS_KEY: mapIndex = SCENE_HAKADAN; break; - case ITEM_GANONS_CASTLE_BOSS_KEY: - mapIndex = SCENE_GANON; - break; - } - - gSaveContext.inventory.dungeonItems[mapIndex] |= gBitFlags[ITEM_KEY_BOSS - ITEM_KEY_BOSS]; - return ITEM_NONE; - } else if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY)) { - int mapIndex = gSaveContext.mapIndex; - switch (item) { - case ITEM_FOREST_TEMPLE_SMALL_KEY: - mapIndex = SCENE_BMORI1; - break; - case ITEM_FIRE_TEMPLE_SMALL_KEY: - mapIndex = SCENE_HIDAN; - break; - case ITEM_WATER_TEMPLE_SMALL_KEY: - mapIndex = SCENE_MIZUSIN; - break; - case ITEM_SPIRIT_TEMPLE_SMALL_KEY: - mapIndex = SCENE_JYASINZOU; - break; - case ITEM_SHADOW_TEMPLE_SMALL_KEY: - mapIndex = SCENE_HAKADAN; - break; + case ITEM_BOTTOM_OF_THE_WELL_MAP: + case ITEM_BOTTOM_OF_THE_WELL_COMPASS: case ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY: mapIndex = SCENE_HAKADANCH; break; + case ITEM_ICE_CAVERN_MAP: + case ITEM_ICE_CAVERN_COMPASS: + mapIndex = SCENE_ICE_DOUKUTO; + break; + case ITEM_GANONS_CASTLE_BOSS_KEY: + mapIndex = SCENE_GANON; + break; case ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY: mapIndex = SCENE_MEN; break; @@ -1805,20 +1829,26 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { mapIndex = SCENE_GANONTIKA; break; } - - if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { - gSaveContext.inventory.dungeonKeys[mapIndex] = 1; - return ITEM_NONE; + + if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY)) { + if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { + gSaveContext.inventory.dungeonKeys[mapIndex] = 1; + return ITEM_NONE; + } else { + gSaveContext.inventory.dungeonKeys[mapIndex]++; + return ITEM_NONE; + } } else { - gSaveContext.inventory.dungeonKeys[mapIndex]++; - return ITEM_NONE; - } - } else if (item == ITEM_KEY_SMALL) { - if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) { - gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1; - return ITEM_NONE; - } else { - gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]++; + int bitmask; + if ((item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP)) { + bitmask = gBitFlags[2]; + } else if ((item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS)) { + bitmask = gBitFlags[1]; + } else { + bitmask = gBitFlags[0]; + } + + gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask; return ITEM_NONE; } } else if ((item == ITEM_QUIVER_30) || (item == ITEM_BOW)) { @@ -2330,7 +2360,12 @@ u8 Item_CheckObtainability(u8 item) { } else { return ITEM_NONE; } - } else if ((item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY)) { + } else if ( + (item >= ITEM_GERUDO_FORTRESS_SMALL_KEY) && (item <= ITEM_GANONS_CASTLE_SMALL_KEY) || + (item >= ITEM_FOREST_TEMPLE_BOSS_KEY) && (item <= ITEM_GANONS_CASTLE_BOSS_KEY) || + (item >= ITEM_DEKU_TREE_MAP) && (item <= ITEM_ICE_CAVERN_MAP) || + (item >= ITEM_DEKU_TREE_COMPASS) && (item <= ITEM_ICE_CAVERN_COMPASS) + ) { return ITEM_NONE; } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { return ITEM_NONE; diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index b91da8918d..18f732717d 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -416,28 +416,64 @@ void GiveLinkDungeonReward(GetItemID getItemId) { } } -void GiveLinkSmallKey(GetItemID getItemId) { +void GiveLinkDungeonItem(GetItemID getItemId, GetItemID type) { int mapIndex; switch (getItemId) { + case GI_DEKU_TREE_MAP: + case GI_DEKU_TREE_COMPASS: + mapIndex = SCENE_YDAN; + break; + case GI_DODONGOS_CAVERN_MAP: + case GI_DODONGOS_CAVERN_COMPASS: + mapIndex = SCENE_DDAN; + break; + case GI_JABU_JABUS_BELLY_MAP: + case GI_JABU_JABUS_BELLY_COMPASS: + mapIndex = SCENE_BDAN; + break; + case GI_FOREST_TEMPLE_MAP: + case GI_FOREST_TEMPLE_COMPASS: case GI_FOREST_TEMPLE_SMALL_KEY: + case GI_FOREST_TEMPLE_BOSS_KEY: mapIndex = SCENE_BMORI1; break; + case GI_FIRE_TEMPLE_MAP: + case GI_FIRE_TEMPLE_COMPASS: case GI_FIRE_TEMPLE_SMALL_KEY: + case GI_FIRE_TEMPLE_BOSS_KEY: mapIndex = SCENE_HIDAN; break; + case GI_WATER_TEMPLE_MAP: + case GI_WATER_TEMPLE_COMPASS: case GI_WATER_TEMPLE_SMALL_KEY: + case GI_WATER_TEMPLE_BOSS_KEY: mapIndex = SCENE_MIZUSIN; break; + case GI_SPIRIT_TEMPLE_MAP: + case GI_SPIRIT_TEMPLE_COMPASS: case GI_SPIRIT_TEMPLE_SMALL_KEY: + case GI_SPIRIT_TEMPLE_BOSS_KEY: mapIndex = SCENE_JYASINZOU; break; + case GI_SHADOW_TEMPLE_MAP: + case GI_SHADOW_TEMPLE_COMPASS: case GI_SHADOW_TEMPLE_SMALL_KEY: + case GI_SHADOW_TEMPLE_BOSS_KEY: mapIndex = SCENE_HAKADAN; break; + case GI_BOTTOM_OF_THE_WELL_MAP: + case GI_BOTTOM_OF_THE_WELL_COMPASS: case GI_BOTTOM_OF_THE_WELL_SMALL_KEY: mapIndex = SCENE_HAKADANCH; break; + case GI_ICE_CAVERN_MAP: + case GI_ICE_CAVERN_COMPASS: + mapIndex = SCENE_ICE_DOUKUTO; + break; + case GI_GANONS_CASTLE_BOSS_KEY: + mapIndex = SCENE_GANON; + break; case GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY: mapIndex = SCENE_MEN; break; @@ -449,40 +485,24 @@ void GiveLinkSmallKey(GetItemID getItemId) { break; } - if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { - gSaveContext.inventory.dungeonKeys[mapIndex] = 1; - } else { - gSaveContext.inventory.dungeonKeys[mapIndex]++; + if (type == GI_MAP) { + uint32_t mapBitMask = 1 << 1; + gSaveContext.inventory.dungeonItems[mapIndex] |= mapBitMask; + } else if (type == GI_COMPASS) { + uint32_t compassBitMask = 1 << 2; + gSaveContext.inventory.dungeonItems[mapIndex] |= compassBitMask; + } else if (type == GI_KEY_SMALL) { + if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { + gSaveContext.inventory.dungeonKeys[mapIndex] = 1; + } else { + gSaveContext.inventory.dungeonKeys[mapIndex]++; + } + } else if (type == GI_KEY_BOSS) { + uint32_t bossKeyBitMask = 1 << 0; + gSaveContext.inventory.dungeonItems[mapIndex] |= bossKeyBitMask; } } -void GiveLinkBossKey(GetItemID getItemId) { - int mapIndex; - - switch (getItemId) { - case GI_FOREST_TEMPLE_BOSS_KEY: - mapIndex = SCENE_BMORI1; - break; - case GI_FIRE_TEMPLE_BOSS_KEY: - mapIndex = SCENE_HIDAN; - break; - case GI_WATER_TEMPLE_BOSS_KEY: - mapIndex = SCENE_MIZUSIN; - break; - case GI_SPIRIT_TEMPLE_BOSS_KEY: - mapIndex = SCENE_JYASINZOU; - break; - case GI_SHADOW_TEMPLE_BOSS_KEY: - mapIndex = SCENE_HAKADAN; - break; - case GI_GANONS_CASTLE_BOSS_KEY: - mapIndex = SCENE_GANON; - break; - } - - gSaveContext.inventory.dungeonItems[mapIndex] |= 1; -} - void GiveLinksPocketMedallion() { GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LINKS_POCKET, RG_NONE); @@ -754,11 +774,11 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; } - if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES)) { + if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES) == 0) { uint32_t mapBitMask = 1 << 1; uint32_t compassBitMask = 1 << 2; uint32_t startingDungeonItemsBitMask = mapBitMask | compassBitMask; - for(int scene = 0; scene <= 9; scene++) { + for(int scene = SCENE_YDAN; scene <= SCENE_ICE_DOUKUTO; scene++) { gSaveContext.inventory.dungeonItems[scene] |= startingDungeonItemsBitMask; } } @@ -856,9 +876,13 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { } else if (giid == GI_DOUBLE_DEFENSE) { GiveLinkDoubleDefense(); } else if (giid >= GI_GERUDO_FORTRESS_SMALL_KEY && giid <= GI_GANONS_CASTLE_SMALL_KEY) { - GiveLinkSmallKey(giid); + GiveLinkDungeonItem(giid, GI_KEY_SMALL); } else if (giid >= GI_FOREST_TEMPLE_BOSS_KEY && giid <= GI_GANONS_CASTLE_BOSS_KEY) { - GiveLinkBossKey(giid); + GiveLinkDungeonItem(giid, GI_KEY_BOSS); + } else if (giid >= GI_DEKU_TREE_MAP && giid <= GI_ICE_CAVERN_MAP) { + GiveLinkDungeonItem(giid, GI_MAP); + } else if (giid >= GI_DEKU_TREE_COMPASS && giid <= GI_ICE_CAVERN_COMPASS) { + GiveLinkDungeonItem(giid, GI_COMPASS); } else { s32 iid = Randomizer_GetItemIDFromGetItemID(giid); if (iid != -1) INV_CONTENT(iid) = iid; diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c index dcb0a29291..8c5914ccae 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -671,6 +671,28 @@ GetItemEntry sGetItemTable[] = { GET_ITEM(ITEM_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, 0xC7, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, 0xC7, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, 0xC7, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, 0x66, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, 0x67, 0x80, CHEST_ANIM_LONG), GET_ITEM_NONE, GET_ITEM_NONE,