diff --git a/soh/include/z64item.h b/soh/include/z64item.h index 9e78487db..3a409a705 100644 --- a/soh/include/z64item.h +++ b/soh/include/z64item.h @@ -253,6 +253,41 @@ typedef enum { /* 0xA2 */ ITEM_BOTTLE_WITH_BUGS, /* 0xA3 */ ITEM_BOTTLE_WITH_POE, /* 0xA4 */ ITEM_BOTTLE_WITH_BIG_POE, + /* 0xA5 */ ITEM_GERUDO_FORTRESS_SMALL_KEY, + /* 0xA6 */ ITEM_FOREST_TEMPLE_SMALL_KEY, + /* 0xA7 */ ITEM_FIRE_TEMPLE_SMALL_KEY, + /* 0xA8 */ ITEM_WATER_TEMPLE_SMALL_KEY, + /* 0xA9 */ ITEM_SPIRIT_TEMPLE_SMALL_KEY, + /* 0xAA */ ITEM_SHADOW_TEMPLE_SMALL_KEY, + /* 0xAB */ ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY, + /* 0xAC */ ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY, + /* 0xAD */ ITEM_GANONS_CASTLE_SMALL_KEY, + /* 0xAE */ ITEM_FOREST_TEMPLE_BOSS_KEY, + /* 0xAF */ ITEM_FIRE_TEMPLE_BOSS_KEY, + /* 0xB0 */ ITEM_WATER_TEMPLE_BOSS_KEY, + /* 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 @@ -397,39 +432,78 @@ typedef enum { /* 0x82 */ GI_MEDALLION_SHADOW, /* 0x83 */ GI_MEDALLION_SPIRIT, - /* 0x81 */ GI_STONE_KOKIRI, - /* 0x82 */ GI_STONE_GORON, - /* 0x83 */ GI_STONE_ZORA, + /* 0x84 */ GI_STONE_KOKIRI, + /* 0x85 */ GI_STONE_GORON, + /* 0x86 */ GI_STONE_ZORA, - /* 0x81 */ GI_ZELDAS_LULLABY, - /* 0x82 */ GI_SUNS_SONG, - /* 0x83 */ GI_EPONAS_SONG, - /* 0x81 */ GI_SONG_OF_STORMS, - /* 0x82 */ GI_SONG_OF_TIME, - /* 0x83 */ GI_SARIAS_SONG, + /* 0x87 */ GI_ZELDAS_LULLABY, + /* 0x88 */ GI_SUNS_SONG, + /* 0x89 */ GI_EPONAS_SONG, + /* 0x8A */ GI_SONG_OF_STORMS, + /* 0x8B */ GI_SONG_OF_TIME, + /* 0x8C */ GI_SARIAS_SONG, - /* 0x81 */ GI_MINUET_OF_FOREST, - /* 0x82 */ GI_BOLERO_OF_FIRE, - /* 0x83 */ GI_SERENADE_OF_WATER, - /* 0x81 */ GI_NOCTURNE_OF_SHADOW, - /* 0x82 */ GI_REQUIEM_OF_SPIRIT, - /* 0x83 */ GI_PRELUDE_OF_LIGHT, + /* 0x8D */ GI_MINUET_OF_FOREST, + /* 0x8E */ GI_BOLERO_OF_FIRE, + /* 0x8F */ GI_SERENADE_OF_WATER, + /* 0x90 */ GI_NOCTURNE_OF_SHADOW, + /* 0x91 */ GI_REQUIEM_OF_SPIRIT, + /* 0x92 */ GI_PRELUDE_OF_LIGHT, - GI_SINGLE_MAGIC, - GI_DOUBLE_MAGIC, - GI_DOUBLE_DEFENSE, + /* 0x93 */ GI_SINGLE_MAGIC, + /* 0x94 */ GI_DOUBLE_MAGIC, + /* 0x95 */ GI_DOUBLE_DEFENSE, - GI_BOTTLE_WITH_RED_POTION, - GI_BOTTLE_WITH_GREEN_POTION, - GI_BOTTLE_WITH_BLUE_POTION, - GI_BOTTLE_WITH_FAIRY, - GI_BOTTLE_WITH_FISH, - GI_BOTTLE_WITH_BLUE_FIRE, - GI_BOTTLE_WITH_BUGS, - GI_BOTTLE_WITH_POE, - GI_BOTTLE_WITH_BIG_POE, + /* 0x96 */ GI_BOTTLE_WITH_RED_POTION, + /* 0x97 */ GI_BOTTLE_WITH_GREEN_POTION, + /* 0x98 */ GI_BOTTLE_WITH_BLUE_POTION, + /* 0x99 */ GI_BOTTLE_WITH_FAIRY, + /* 0x9A */ GI_BOTTLE_WITH_FISH, + /* 0x9B */ GI_BOTTLE_WITH_BLUE_FIRE, + /* 0x9C */ GI_BOTTLE_WITH_BUGS, + /* 0x9D */ GI_BOTTLE_WITH_POE, + /* 0x9E */ GI_BOTTLE_WITH_BIG_POE, - /* 0x84 */ GI_MAX + /* 0x9F */ GI_GERUDO_FORTRESS_SMALL_KEY, + /* 0xA0 */ GI_FOREST_TEMPLE_SMALL_KEY, + /* 0xA1 */ GI_FIRE_TEMPLE_SMALL_KEY, + /* 0xA2 */ GI_WATER_TEMPLE_SMALL_KEY, + /* 0xA3 */ GI_SPIRIT_TEMPLE_SMALL_KEY, + /* 0xA4 */ GI_SHADOW_TEMPLE_SMALL_KEY, + /* 0xA5 */ GI_BOTTOM_OF_THE_WELL_SMALL_KEY, + /* 0xA6 */ GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, + /* 0xA7 */ GI_GANONS_CASTLE_SMALL_KEY, + + /* 0xA8 */ GI_FOREST_TEMPLE_BOSS_KEY, + /* 0xA9 */ GI_FIRE_TEMPLE_BOSS_KEY, + /* 0xAA */ GI_WATER_TEMPLE_BOSS_KEY, + /* 0xAB */ GI_SPIRIT_TEMPLE_BOSS_KEY, + /* 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; typedef enum { diff --git a/soh/include/z64player.h b/soh/include/z64player.h index 2f2ac1008..33ae4c6d9 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[160]; +extern GetItemEntry sGetItemTable[195]; typedef enum { /* 0 */ PLAYER_SWORD_NONE, diff --git a/soh/soh/Enhancements/randomizer/3drando/item.hpp b/soh/soh/Enhancements/randomizer/3drando/item.hpp index a424dbf2b..dbfb695b1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item.hpp +++ b/soh/soh/Enhancements/randomizer/3drando/item.hpp @@ -103,11 +103,11 @@ public: return false; } - if ((type == ITEMTYPE_BOSSKEY && getItemId != 0x9A) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) { + if ((type == ITEMTYPE_BOSSKEY && getItemId != 0xAD) && (BossKeysanity.Is(BOSSKEYSANITY_VANILLA) || BossKeysanity.Is(BOSSKEYSANITY_OWN_DUNGEON))) { return false; } //Ganons Castle Boss Key - if (getItemId == 0x9A && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) { + if (getItemId == 0xAD && (GanonsBossKey.Is(GANONSBOSSKEY_VANILLA) || GanonsBossKey.Is(GANONSBOSSKEY_OWN_DUNGEON))) { return false; } diff --git a/soh/soh/Enhancements/randomizer/3drando/settings.cpp b/soh/soh/Enhancements/randomizer/3drando/settings.cpp index ec6890cfb..49cb0a3c1 100644 --- a/soh/soh/Enhancements/randomizer/3drando/settings.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/settings.cpp @@ -2546,14 +2546,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]); @@ -2565,6 +2558,9 @@ namespace Settings { ItemPoolValue.SetSelectedIndex(cvarSettings[RSK_ITEM_POOL]); IceTrapValue.SetSelectedIndex(cvarSettings[RSK_ICE_TRAPS]); + Keysanity.SetSelectedIndex(cvarSettings[RSK_KEYSANITY]); + GerudoKeys.SetSelectedIndex(cvarSettings[RSK_GERUDO_KEYS]); + BossKeysanity.SetSelectedIndex(cvarSettings[RSK_BOSS_KEYSANITY]); GanonsBossKey.SetSelectedIndex(cvarSettings[RSK_GANONS_BOSS_KEY]); NumRequiredCuccos.SetSelectedIndex(cvarSettings[RSK_CUCCO_COUNT]); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 214e1d8be..79003f55e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -1004,6 +1004,41 @@ std::unordered_map itemIdToModel = { { GI_NONE, GID_MAXIMUM }, { 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 }, + { GI_WATER_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_SPIRIT_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_SHADOW_TEMPLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_BOTTOM_OF_THE_WELL_SMALL_KEY, GID_KEY_SMALL }, + { GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, GID_KEY_SMALL }, + { GI_GANONS_CASTLE_SMALL_KEY, GID_KEY_SMALL }, + { GI_FOREST_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_FIRE_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { GI_WATER_TEMPLE_BOSS_KEY, GID_KEY_BOSS }, + { 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_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 } }; @@ -1412,6 +1447,9 @@ std::unordered_map SpoilerfileSettingNameToEn { "Start with Kokiri Sword", RSK_STARTING_KOKIRI_SWORD }, { "Start with Fairy Ocarina", RSK_STARTING_OCARINA }, { "Shuffle Dungeon Items:Start with Maps/Compasses", RSK_STARTING_MAPS_COMPASSES }, + { "Shuffle Dungeon Items:Small Keys", RSK_KEYSANITY }, + { "Shuffle Dungeon Items:Gerudo Fortress Keys", RSK_GERUDO_KEYS }, + { "Shuffle Dungeon Items:Boss Keys", RSK_BOSS_KEYSANITY }, { "Shuffle Dungeon Items:Ganon's Boss Key", RSK_GANONS_BOSS_KEY }, { "Misc Settings:Gossip Stone Hints", RSK_GOSSIP_STONE_HINTS }, { "Misc Settings:Hint Clarity", RSK_HINT_CLARITY }, @@ -1648,10 +1686,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: @@ -1706,13 +1752,49 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) { gSaveContext.randoSettings[index].value = 3; } break; - case RSK_GANONS_BOSS_KEY: - if(it.value() == "Start with") { + case RSK_KEYSANITY: + 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") { + } 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_BOSS_KEYSANITY: + 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_GANONS_BOSS_KEY: + if(it.value() == "Vanilla") { + gSaveContext.randoSettings[index].value = 0; + } else if(it.value() == "Own dungeon") { + gSaveContext.randoSettings[index].value = 1; + } else if(it.value() == "Start with") { + 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_SKIP_CHILD_ZELDA: @@ -2229,50 +2311,79 @@ 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; - // todo implement dungeon-specific keys/keyrings case RG_FOREST_TEMPLE_BOSS_KEY: + return GI_FOREST_TEMPLE_BOSS_KEY; case RG_FIRE_TEMPLE_BOSS_KEY: + return GI_FIRE_TEMPLE_BOSS_KEY; case RG_WATER_TEMPLE_BOSS_KEY: + return GI_WATER_TEMPLE_BOSS_KEY; case RG_SPIRIT_TEMPLE_BOSS_KEY: + return GI_SPIRIT_TEMPLE_BOSS_KEY; case RG_SHADOW_TEMPLE_BOSS_KEY: + return GI_SHADOW_TEMPLE_BOSS_KEY; case RG_GANONS_CASTLE_BOSS_KEY: - return GI_KEY_BOSS; + return GI_GANONS_CASTLE_BOSS_KEY; case RG_FOREST_TEMPLE_SMALL_KEY: + return GI_FOREST_TEMPLE_SMALL_KEY; case RG_FIRE_TEMPLE_SMALL_KEY: + return GI_FIRE_TEMPLE_SMALL_KEY; case RG_WATER_TEMPLE_SMALL_KEY: + return GI_WATER_TEMPLE_SMALL_KEY; case RG_SPIRIT_TEMPLE_SMALL_KEY: + return GI_SPIRIT_TEMPLE_SMALL_KEY; case RG_SHADOW_TEMPLE_SMALL_KEY: + return GI_SHADOW_TEMPLE_SMALL_KEY; case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + return GI_BOTTOM_OF_THE_WELL_SMALL_KEY; case RG_GERUDO_TRAINING_GROUNDS_SMALL_KEY: + return GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY; case RG_GERUDO_FORTRESS_SMALL_KEY: + return GI_GERUDO_FORTRESS_SMALL_KEY; case RG_GANONS_CASTLE_SMALL_KEY: - return GI_KEY_SMALL; + return GI_GANONS_CASTLE_SMALL_KEY; // todo test this with keys in own dungeon case RG_TREASURE_GAME_SMALL_KEY: @@ -3431,7 +3542,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", 2); 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); @@ -3451,7 +3562,10 @@ void GenerateRandomizerImgui() { cvarSettings[RSK_GOSSIP_STONE_HINTS] = CVar_GetS32("gRandomizeGossipStoneHints", 1); cvarSettings[RSK_HINT_CLARITY] = CVar_GetS32("gRandomizeHintClarity", 2); cvarSettings[RSK_HINT_DISTRIBUTION] = CVar_GetS32("gRandomizeHintDistribution", 1); - cvarSettings[RSK_GANONS_BOSS_KEY] = CVar_GetS32("gRandomizeShuffleGanonBossKey", 0); + cvarSettings[RSK_KEYSANITY] = CVar_GetS32("gRandomizeKeysanity", 2); + cvarSettings[RSK_GERUDO_KEYS] = CVar_GetS32("gRandomizeGerudoKeys", 0); + cvarSettings[RSK_BOSS_KEYSANITY] = CVar_GetS32("gRandomizeBossKeysanity", 2); + cvarSettings[RSK_GANONS_BOSS_KEY] = CVar_GetS32("gRandomizeShuffleGanonBossKey", 1); cvarSettings[RSK_STARTING_CONSUMABLES] = CVar_GetS32("gRandomizeStartingConsumables", 0); cvarSettings[RSK_FULL_WALLETS] = CVar_GetS32("gRandomizeFullWallets", 0); @@ -3542,17 +3656,11 @@ 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* randoShuffleSmallKeys[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] = { "Own Dungeon", "Any Dungeon", "Overworld", - "Anywhere", "Start with", "Vanilla" }; - // const char* randoShuffleGanonsBossKey[12] = { "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere", - // "LACS Vanilla", "LACS Medallions", "LACS Stones", "LACS Rewards", - // "LACS Dungeons", "LACS Tokens", "Start with", "Vanilla" }; - const char* randoShuffleGanonsBossKey[3] = {"Vanilla", "Own dungeon", "Start with"}; + const char* randoShuffleBossKeys[6] = { "Start With", "Vanilla", "Own Dungeon", "Any Dungeon", "Overworld", "Anywhere" }; + const char* randoShuffleGanonsBossKey[6] = { "Vanilla", "Own dungeon", "Start with", "Any Dungeon", "Overworld", "Anywhere" }; // Timesaver Settings const char* randoSkipSongReplays[3] = { "Don't skip", "Skip (no SFX)", "Skip (Keep SFX)" }; @@ -4076,22 +4184,90 @@ void DrawRandoEditor(bool& open) { SohImGui::EnhancementCombobox("gRandomizeShuffleDungeonReward", randoShuffleDungeonRewards, 4, 0); PaddedSeparator(); - // RANDOTODO implement ganon's boss key outside of ganon's castle + // Keysanity + ImGui::Text(Settings::Keysanity.GetName().c_str()); + InsertHelpHoverText( + "Start with - You will start with all Small Keys from all dungeons.\n" + "\n" + "Vanilla - Small Keys will appear in their vanilla locations.\n" + "\n" + "Own dungeon - Small Keys can only appear in their respective dungeon.\n" + "\n" + "Any dungeon - Small Keys can only appear inside of any dungon.\n" + "\n" + "Overworld - Small Keys can only appear outside of dungeons.\n" + "\n" + "Anywhere - Small Keys can appear anywhere in the world." + ); + SohImGui::EnhancementCombobox("gRandomizeKeysanity", randoShuffleSmallKeys, 6, 2); + PaddedSeparator(); + + // Gerudo Keys + ImGui::Text(Settings::GerudoKeys.GetName().c_str()); + InsertHelpHoverText( + "Vanilla - Thieve's Hideout Keys will appear in their vanilla locations.\n" + "\n" + "Any dungeon - Thieve's Hideout Keys can only appear inside of any dungon.\n" + "\n" + "Overworld - Thieve's Hideout Keys can only appear outside of dungeons.\n" + "\n" + "Anywhere - Thieve's Hideout Keys can appear anywhere in the world." + ); + SohImGui::EnhancementCombobox("gRandomizeGerudoKeys", randoShuffleGerudoFortressKeys, 4, 0); + PaddedSeparator(); + + // Boss Keysanity + ImGui::Text(Settings::BossKeysanity.GetName().c_str()); + InsertHelpHoverText( + "Start with - You will start with Boss keys from all dungeons.\n" + "\n" + "Vanilla - Boss Keys will appear in their vanilla locations.\n" + "\n" + "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("gRandomizeBossKeysanity", randoShuffleBossKeys, 6, 2); + PaddedSeparator(); + // Ganon's Boss Key ImGui::Text(Settings::GanonsBossKey.GetName().c_str()); InsertHelpHoverText( - "Vanilla - Key will appear in the vanilla location.\n" + "Vanilla - Ganon's Boss Key will appear in the vanilla location.\n" "\n" - "Own dungeon - Key can appear anywhere inside Ganon's Castle.\n" + "Own dungeon - Ganon's Boss Key can appear anywhere inside Ganon's Castle.\n" "\n" "Start with - Places Ganon's Boss Key in your starting inventory." + "\n" + "Any dungeon - Ganon's Boss Key Key can only appear inside of any dungon.\n" + "\n" + "Overworld - Ganon's Boss Key Key can only appear outside of dungeons.\n" + "\n" + "Anywhere - Ganon's Boss Key Key can appear anywhere in the world." ); - SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 3, - 0); + SohImGui::EnhancementCombobox("gRandomizeShuffleGanonBossKey", randoShuffleGanonsBossKey, 6, 1); PaddedSeparator(); // Start with Maps & Compasses - SohImGui::EnhancementCheckbox(Settings::MapsAndCompasses.GetName().c_str(), "gRandomizeStartingMapsCompasses"); + ImGui::Text(Settings::MapsAndCompasses.GetName().c_str()); + InsertHelpHoverText( + "Start with - You will start with Maps & Compasses from all dungeons.\n" + "\n" + "Vanilla - Maps & Compasses will appear in their vanilla locations.\n" + "\n" + "Own dungeon - Maps & Compasses can only appear in their respective dungeon.\n" + "\n" + "Any dungeon - Maps & Compasses can only appear inside of any dungon.\n" + "\n" + "Overworld - Maps & Compasses can only appear outside of dungeons.\n" + "\n" + "Anywhere - Maps & Compasses can appear anywhere in the world." + ); + SohImGui::EnhancementCombobox("gRandomizeStartingMapsCompasses", randoShuffleMapsAndCompasses, 6, 2); ImGui::PopItemWidth(); ImGui::EndTable(); @@ -4460,6 +4636,45 @@ void Randomizer::CreateCustomMessages() { "You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!"), GIMESSAGE_UNTRANSLATED(GI_BOTTLE_WITH_POE, ITEM_POE, "You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this..."), + + GIMESSAGE_UNTRANSLATED(GI_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pBottom of the &Well %wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_GERUDO_TRAINING_GROUNDS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yGerudo Training Grounds &%wSmall Key!"), + GIMESSAGE_UNTRANSLATED(GI_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!"), + + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple &%wBoss Key!"), + GIMESSAGE_UNTRANSLATED(GI_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle &%wBoss Key!"), + + GIMESSAGE_UNTRANSLATED(GI_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple &%wMap!"), + GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the &Well %wMap!"), + GIMESSAGE_UNTRANSLATED(GI_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern &%wMap!"), + + GIMESSAGE_UNTRANSLATED(GI_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple &%wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS, "You found the %pBottom of the &Well %wCompass!"), + GIMESSAGE_UNTRANSLATED(GI_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern &%wCompass!"), }; CreateGetItemMessages(getItemMessages); CreateScrubMessages(); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 8b0897da1..baff15483 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, @@ -984,6 +984,9 @@ typedef enum { RSK_GOSSIP_STONE_HINTS, RSK_HINT_CLARITY, RSK_HINT_DISTRIBUTION, + RSK_KEYSANITY, + RSK_GERUDO_KEYS, + RSK_BOSS_KEYSANITY, RSK_GANONS_BOSS_KEY, RSK_SKIP_CHILD_STEALTH, RSK_SKIP_CHILD_ZELDA, diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index eb166bddd..a7f1a6c78 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -1751,29 +1751,6 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { } return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { - // Small key exceptions for rando. - if (gSaveContext.n64ddFlag) { - if (globalCtx->sceneNum == 10) { // ganon's tower -> ganon's castle - if (gSaveContext.inventory.dungeonKeys[13] < 0) { - gSaveContext.inventory.dungeonKeys[13] = 1; - return ITEM_NONE; - } else { - gSaveContext.inventory.dungeonKeys[13]++; - return ITEM_NONE; - } - } - - if (globalCtx->sceneNum == 92) { // Desert Colossus -> Spirit Temple. - if (gSaveContext.inventory.dungeonKeys[6] < 0) { - gSaveContext.inventory.dungeonKeys[6] = 1; - return ITEM_NONE; - } else { - gSaveContext.inventory.dungeonKeys[6]++; - return ITEM_NONE; - } - } - } - if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] < 0) { gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] = 1; return ITEM_NONE; @@ -1781,6 +1758,100 @@ u8 Item_Give(GlobalContext* globalCtx, u8 item) { 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_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; + case ITEM_GERUDO_FORTRESS_SMALL_KEY: + mapIndex = SCENE_GERUDOWAY; + break; + case ITEM_GANONS_CASTLE_SMALL_KEY: + mapIndex = SCENE_GANONTIKA; + break; + } + + 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 { + 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)) { if (CUR_UPG_VALUE(UPG_QUIVER) == 0) { Inventory_ChangeUpgrade(UPG_QUIVER, 1); @@ -2294,6 +2365,13 @@ u8 Item_CheckObtainability(u8 item) { } else { 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) + ) { + return ITEM_NONE; } else if ((item == ITEM_KEY_BOSS) || (item == ITEM_COMPASS) || (item == ITEM_DUNGEON_MAP)) { return ITEM_NONE; } else if (item == ITEM_KEY_SMALL) { diff --git a/soh/src/code/z_sram.c b/soh/src/code/z_sram.c index d93da4f6d..55c451d4b 100644 --- a/soh/src/code/z_sram.c +++ b/soh/src/code/z_sram.c @@ -416,6 +416,95 @@ void GiveLinkDungeonReward(GetItemID getItemId) { } } +void GiveLinkDungeonItem(GetItemID getItemId) { + 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; + case GI_GERUDO_FORTRESS_SMALL_KEY: + mapIndex = SCENE_GERUDOWAY; + break; + case GI_GANONS_CASTLE_SMALL_KEY: + mapIndex = SCENE_GANONTIKA; + break; + } + + if ((getItemId >= GI_GERUDO_FORTRESS_SMALL_KEY) && (getItemId <= GI_GANONS_CASTLE_SMALL_KEY)) { + if (gSaveContext.inventory.dungeonKeys[mapIndex] < 0) { + gSaveContext.inventory.dungeonKeys[mapIndex] = 1; + } else { + gSaveContext.inventory.dungeonKeys[mapIndex]++; + } + } else { + int bitmask; + if ((getItemId >= GI_DEKU_TREE_MAP) && (getItemId <= GI_ICE_CAVERN_MAP)) { + bitmask = gBitFlags[2]; + } else if ((getItemId >= GI_DEKU_TREE_COMPASS) && (getItemId <= GI_ICE_CAVERN_COMPASS)) { + bitmask = gBitFlags[1]; + } else { + bitmask = gBitFlags[0]; + } + + gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask; + } +} + void GiveLinksPocketMedallion() { GetItemID getItemId = Randomizer_GetItemIdFromKnownCheck(RC_LINKS_POCKET, RG_NONE); @@ -689,11 +778,12 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { INV_CONTENT(ITEM_OCARINA_FAIRY) = ITEM_OCARINA_FAIRY; } - if(Randomizer_GetSettingValue(RSK_STARTING_MAPS_COMPASSES)) { + // "Start with" == 0 for Maps and 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; } } @@ -790,6 +880,13 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { GiveLinkMagic(giid); } else if (giid == GI_DOUBLE_DEFENSE) { GiveLinkDoubleDefense(); + } else if ( + (giid >= GI_GERUDO_FORTRESS_SMALL_KEY && giid <= GI_GANONS_CASTLE_SMALL_KEY) || + (giid >= GI_FOREST_TEMPLE_BOSS_KEY && giid <= GI_GANONS_CASTLE_BOSS_KEY) || + (giid >= GI_DEKU_TREE_MAP && giid <= GI_ICE_CAVERN_MAP) || + (giid >= GI_DEKU_TREE_COMPASS && giid <= GI_ICE_CAVERN_COMPASS) + ) { + GiveLinkDungeonItem(giid); } else { s32 iid = Randomizer_GetItemIDFromGetItemID(giid); if (iid != -1) INV_CONTENT(iid) = iid; @@ -816,9 +913,31 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) { GiveLinkRupees(9001); } - // For Ganon's boss key "Start With" is 0 - if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 0) { - gSaveContext.inventory.dungeonItems[10] |= 1; + // "Start with" == 0 for Keysanity + if(Randomizer_GetSettingValue(RSK_KEYSANITY) == 0) { + // TODO: If master quest there are different key counts + gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = 5; // Forest + gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = 8; // Fire + gSaveContext.inventory.dungeonKeys[SCENE_MIZUSIN] = 6; // Water + gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 5; // Spirit + gSaveContext.inventory.dungeonKeys[SCENE_HAKADAN] = 5; // Shadow + gSaveContext.inventory.dungeonKeys[SCENE_HAKADANCH] = 2; // BotW + gSaveContext.inventory.dungeonKeys[SCENE_MEN] = 9; // GTG + gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = 2; // Ganon + } + + // "Start with" == 0 for Boss Kesanity + if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == 0) { + gSaveContext.inventory.dungeonItems[SCENE_BMORI1] |= 1; // Forest + gSaveContext.inventory.dungeonItems[SCENE_HIDAN] |= 1; // Fire + gSaveContext.inventory.dungeonItems[SCENE_MIZUSIN] |= 1; // Water + gSaveContext.inventory.dungeonItems[SCENE_JYASINZOU] |= 1; // Spirit + gSaveContext.inventory.dungeonItems[SCENE_HAKADAN] |= 1; // Shadow + } + + // "Start with" == 2 for Ganon's Boss Key + if(Randomizer_GetSettingValue(RSK_GANONS_BOSS_KEY) == 2) { + gSaveContext.inventory.dungeonItems[SCENE_GANON] |= 1; } HIGH_SCORE(HS_POE_POINTS) = 1000 - (100 * Randomizer_GetSettingValue(RSK_BIG_POE_COUNT)); 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 eac49315d..cf682a45c 100644 --- a/soh/src/overlays/actors/ovl_player_actor/z_player.c +++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c @@ -656,6 +656,45 @@ GetItemEntry sGetItemTable[] = { GET_ITEM(ITEM_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), GET_ITEM(ITEM_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_GERUDO_TRAINING_GROUNDS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + GET_ITEM(ITEM_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT), + + GET_ITEM(ITEM_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + + GET_ITEM(ITEM_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM(ITEM_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG), + GET_ITEM_NONE, GET_ITEM_NONE, };