From b76e303ceb5ee93c67bd8db263fe5639ca5214f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= <159546+serprex@users.noreply.github.com> Date: Thu, 6 Aug 2026 01:51:59 +0000 Subject: [PATCH] Shuffle Silver (#5659) Co-authored-by: Pepper0ni <93387759+Pepper0ni@users.noreply.github.com> Co-authored-by: leggettc18 --- soh/CMakeLists.txt | 1 + soh/include/z64save.h | 22 + .../vanilla-behavior/GIVanillaBehavior.h | 24 + .../Enhancements/randomizer/3drando/fill.cpp | 4 +- .../hint_list/hint_list_exclude_dungeon.cpp | 9 + .../3drando/hint_list/hint_list_item.cpp | 8 + .../randomizer/3drando/item_pool.cpp | 125 +- .../randomizer/3drando/playthrough.cpp | 14 +- .../randomizer/3drando/starting_inventory.cpp | 6 + .../Enhancements/randomizer/RCToRandInf.cpp | 154 ++ .../Enhancements/randomizer/SeedContext.cpp | 13 +- soh/soh/Enhancements/randomizer/SeedContext.h | 4 +- .../Enhancements/randomizer/ShuffleSilver.cpp | 462 +++++ .../Enhancements/randomizer/ShuffleSilver.h | 12 + soh/soh/Enhancements/randomizer/Traps.cpp | 90 + soh/soh/Enhancements/randomizer/draw.cpp | 45 +- soh/soh/Enhancements/randomizer/draw.h | 1 + .../Enhancements/randomizer/hook_handlers.cpp | 17 +- soh/soh/Enhancements/randomizer/item.h | 1 + soh/soh/Enhancements/randomizer/item_list.cpp | 47 +- .../dungeons/bottom_of_the_well.cpp | 41 +- .../dungeons/dodongos_cavern.cpp | 18 +- .../dungeons/ganons_castle.cpp | 164 +- .../dungeons/gerudo_training_ground.cpp | 120 +- .../location_access/dungeons/ice_cavern.cpp | 36 +- .../dungeons/shadow_temple.cpp | 271 ++- .../dungeons/spirit_temple.cpp | 72 +- .../overworld/gerudo_valley.cpp | 2 +- soh/soh/Enhancements/randomizer/logic.cpp | 57 +- .../randomizer/option_descriptions.cpp | 11 + .../Enhancements/randomizer/randomizer.cpp | 83 + soh/soh/Enhancements/randomizer/randomizer.h | 3 + .../Enhancements/randomizer/randomizerEnums.h | 1 + .../randomizer/randomizerEnums/LogicVal.h | 31 +- .../randomizerEnums/RandomizerCheck.h | 157 ++ .../randomizerEnums/RandomizerGet.h | 22 + .../randomizerEnums/RandomizerHintTextKey.h | 15 + .../randomizerEnums/RandomizerInf.h | 157 ++ .../randomizerEnums/RandomizerMiscEnums.h | 1 + .../randomizerEnums/RandomizerOptions.h | 8 + .../randomizerEnums/RandomizerRegion.h | 22 +- .../randomizerEnums/RandomizerSettingKey.h | 1 + .../randomizer/randomizer_check_objects.cpp | 2 + .../randomizer/randomizer_check_objects.h | 2 +- .../randomizer/randomizer_check_tracker.cpp | 194 +- .../randomizer/randomizer_check_tracker.h | 2 + .../randomizer/randomizer_entrance_tracker.h | 2 +- .../randomizer/randomizer_item_tracker.cpp | 1653 ++++++++--------- .../randomizer/randomizer_item_tracker.h | 73 +- soh/soh/Enhancements/randomizer/savefile.cpp | 6 + soh/soh/Enhancements/randomizer/settings.cpp | 3 + .../Enhancements/randomizer/static_data.cpp | 25 + soh/soh/Enhancements/randomizer/static_data.h | 4 + soh/soh/OTRGlobals.h | 3 +- soh/soh/ResourceManagerHelpers.cpp | 2 +- soh/soh/SaveManager.cpp | 56 + soh/soh/SohGui/ImGuiUtils.cpp | 8 + .../actors/ovl_En_G_Switch/z_en_g_switch.c | 49 +- 58 files changed, 3332 insertions(+), 1104 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/ShuffleSilver.cpp create mode 100644 soh/soh/Enhancements/randomizer/ShuffleSilver.h diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 9fb209d721..7e54ae8706 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -4,6 +4,7 @@ set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE) project(soh LANGUAGES C CXX) set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use") +set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_C_STANDARD 23 CACHE STRING "The C standard to use") if (CMAKE_SYSTEM_NAME STREQUAL "Darwin") diff --git a/soh/include/z64save.h b/soh/include/z64save.h index 6adad2a9fe..b920ce634a 100644 --- a/soh/include/z64save.h +++ b/soh/include/z64save.h @@ -227,6 +227,28 @@ typedef struct { typedef struct ShipRandomizerSaveContextData { u8 triforcePiecesCollected; u8 bombchuUpgradeLevel; + s8 silverShadowBlades; + s8 silverShadowPit; + s8 silverShadowSpikes; + s8 silverSpiritChild; + s8 silverSpiritSun; + s8 silverSpiritBoulders; + s8 silverBotw; + s8 silverIceCavernBlades; + s8 silverIceCavernBlock; + s8 silverGtgSlope; + s8 silverGtgLava; + s8 silverGtgWater; + s8 silverGanonLight; + s8 silverGanonForest; + s8 silverGanonFire; + s8 silverGanonSpirit; + s8 silverMqDodongosCavern; + s8 silverMqShadowInvisibleBlades; + s8 silverMqSpiritLobby; + s8 silverMqSpiritBigWall; + s8 silverMqGanonWater; + s8 silverMqGanonShadow; } ShipRandomizerSaveContextData; typedef struct ShipBossRushSaveContextData { diff --git a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h index 845053d042..abc3b3793e 100644 --- a/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h +++ b/soh/soh/Enhancements/game-interactor/vanilla-behavior/GIVanillaBehavior.h @@ -2598,6 +2598,30 @@ typedef enum { // - None VB_SHOW_TITLE_CARD, + // #### `result` + // ```c + // this->actor.xyzDistToPlayerSq < 900.0f + // ``` + // #### `args` + // - *EnGSwitch + VB_SILVER_COLLECT, + + // #### `result` + // ```c + // true + // ``` + // #### `args` + // - *EnGSwitch + VB_SILVER_COUNT_CHECK, + + // #### `result` + // ```c + // Flags_GetSwitch(play, this->switchFlag) + // ``` + // #### `args` + // - *EnGSwitch + VB_SILVER_DESPAWN, + // #### `result` // ```c // true diff --git a/soh/soh/Enhancements/randomizer/3drando/fill.cpp b/soh/soh/Enhancements/randomizer/3drando/fill.cpp index 623c1fa6d3..db60f704ef 100644 --- a/soh/soh/Enhancements/randomizer/3drando/fill.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/fill.cpp @@ -403,8 +403,8 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals RandomizerGet locItem = location->GetPlacedRandomizerGet(); RandomizerCheckQuest quest = Rando::StaticData::GetLocation(loc)->GetQuest(); assert(ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_NO_LOGIC) || quest == RCQUEST_BOTH || - (quest == RCQUEST_VANILLA && ctx->GetDungeons()->GetDungeonFromScene(parentRegion->scene)->IsVanilla()) || - (quest == RCQUEST_MQ && ctx->GetDungeons()->GetDungeonFromScene(parentRegion->scene)->IsMQ())); + (quest == RCQUEST_VANILLA && ctx->GetDungeonFromScene(parentRegion->scene)->IsVanilla()) || + (quest == RCQUEST_MQ && ctx->GetDungeonFromScene(parentRegion->scene)->IsMQ())); if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, logic->CalculatingAvailableChecks) && !logic->ShopItemNotForSale(loc)) { diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp index ce68ff495c..dccadfcfd8 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_exclude_dungeon.cpp @@ -6,6 +6,15 @@ namespace Rando { void StaticData::HintTable_Init_Exclude_Dungeon() { // clang-format off + // TODO move these to region specific sections when hint text stable + hintTextTable[RHT_DODONGOS_CAVERN_SILVER] = HintText(CustomMessage("They say that a #silver rupee in Dodongo's Cavern# holds #[[1]]#.", TODO_TRANSLATE, TODO_TRANSLATE, {QM_RED, QM_GREEN})); + hintTextTable[RHT_SHADOW_TEMPLE_SILVER] = HintText(CustomMessage("They say that a #silver rupee in the Shadow Temple# holds #[[1]]#.", TODO_TRANSLATE, TODO_TRANSLATE, {QM_RED, QM_GREEN})); + hintTextTable[RHT_SPIRIT_TEMPLE_SILVER] = HintText(CustomMessage("They say that a #silver rupee in the Spirit Temple# holds #[[1]]#.", TODO_TRANSLATE, TODO_TRANSLATE, {QM_RED, QM_GREEN})); + hintTextTable[RHT_BOTW_SILVER] = HintText(CustomMessage("They say that a #silver rupee in the Bottom of the Well# holds #[[1]]#.", TODO_TRANSLATE, TODO_TRANSLATE, {QM_RED, QM_GREEN})); + hintTextTable[RHT_ICE_CAVERN_SILVER] = HintText(CustomMessage("They say that a #silver rupee in the Ice Cavern# holds #[[1]]#.", TODO_TRANSLATE, TODO_TRANSLATE, {QM_RED, QM_GREEN})); + hintTextTable[RHT_GTG_SILVER] = HintText(CustomMessage("They say that a #silver rupee in the Gerudo Training Ground# holds #[[1]]#.", TODO_TRANSLATE, TODO_TRANSLATE, {QM_RED, QM_GREEN})); + hintTextTable[RHT_GANONS_CASTLE_SILVER] = HintText(CustomMessage("They say that a #silver rupee in Ganon's Castle# holds #[[1]]#.", TODO_TRANSLATE, TODO_TRANSLATE, {QM_RED, QM_GREEN})); + /*-------------------------- | DEKU TREE | ---------------------------*/ diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp index 2b2fd83f10..920e40c42b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list/hint_list_item.cpp @@ -2108,6 +2108,14 @@ void StaticData::HintTable_Init_Item() { }, { CustomMessage("sack of mice", /*german*/"ein Sack Mäuse", /*french*/"un Sac rempli de souris")}); + hintTextTable[RHT_SILVER_RUPEE_DODONGOS_CAVERN] = HintText(CustomMessage("a Dodongo's Cavern Silver Rupee", /*german*/ TODO_TRANSLATE, /*french*/ TODO_TRANSLATE)); + hintTextTable[RHT_SILVER_RUPEE_SHADOW_TEMPLE] = HintText(CustomMessage("a Shadow Temple Silver Rupee", /*german*/ TODO_TRANSLATE, /*french*/ TODO_TRANSLATE)); + hintTextTable[RHT_SILVER_RUPEE_SPIRIT_TEMPLE] = HintText(CustomMessage("a Spirit Temple Silver Rupee", /*german*/ TODO_TRANSLATE, /*french*/ TODO_TRANSLATE)); + hintTextTable[RHT_SILVER_RUPEE_BOTW] = HintText(CustomMessage("a Bottom of the Well Silver Rupee", /*german*/ TODO_TRANSLATE, /*french*/ TODO_TRANSLATE)); + hintTextTable[RHT_SILVER_RUPEE_ICE_CAVERN] = HintText(CustomMessage("an Ice Cavern Silver Rupee", /*german*/ TODO_TRANSLATE, /*french*/ TODO_TRANSLATE)); + hintTextTable[RHT_SILVER_RUPEE_GTG] = HintText(CustomMessage("a Gerudo Training Ground Silver Rupee", /*german*/ TODO_TRANSLATE, /*french*/ TODO_TRANSLATE)); + hintTextTable[RHT_SILVER_RUPEE_GANONS_CASTLE] = HintText(CustomMessage("a Ganon's Castle Silver Rupee", /*german*/ TODO_TRANSLATE, /*french*/ TODO_TRANSLATE)); + hintTextTable[RHT_SKELETON_KEY] = HintText(CustomMessage("a Skeleton Key", /*german*/ "der Skelettschlüssel", /*french*/ "une Clé Squelette"), // /*spanish*/una Llave Maestra { diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index d98b893a8b..f9cd7e60ca 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -126,11 +126,12 @@ static void PlaceItemsForType(RandomizerCheckType rctype, bool overworldActive = if (currentQuest == RCQUEST_BOTH) { AddFixedItemToPool(loc->GetVanillaItem(), 1, false); } else { - // Check if current item's dungeon is vanilla or MQ, and only add if quest corresponds to it. + // Check if current item's dungeon is vanilla or MQ, and only add if quest corresponds to it SceneID itemScene = loc->GetScene(); + auto dungeon = ctx->GetDungeonFromScene(itemScene); - if (itemScene >= SCENE_DEKU_TREE && itemScene <= SCENE_GERUDO_TRAINING_GROUND) { - bool isMQ = ctx->GetDungeon(itemScene)->IsMQ(); + if (dungeon != nullptr) { + bool isMQ = dungeon->IsMQ(); if ((isMQ && currentQuest == RCQUEST_MQ) || (!isMQ && currentQuest == RCQUEST_VANILLA)) { AddFixedItemToPool(loc->GetVanillaItem(), 1, false); @@ -231,7 +232,7 @@ void GenerateItemPool() { std::max(0, 1 + infiniteProgressive - startMagic)); //clang-format on - int extraWallets =(ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET) ? 1 : 0) + (ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET) ? 1 : 0); + int extraWallets = (ctx->GetOption(RSK_SHUFFLE_CHILD_WALLET) ? 1 : 0) + (ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET) ? 1 : 0); int startWallet = ctx->GetOption(RSK_STARTING_WALLET).Get(); AddItemToPool(RG_PROGRESSIVE_WALLET, std::max(0, 3 + infiniteProgressive + extraWallets - startWallet), std::max(0, 2 + infiniteProgressive + extraWallets - startWallet), @@ -913,6 +914,122 @@ void GenerateItemPool() { } } + bool silverActive = ctx->GetOption(RSK_SHUFFLE_SILVER).Get(); + if (silverActive) { + PlaceItemsForType(RCTYPE_SILVER, silverActive, silverActive); + } + + if (ctx->GetOption(RSK_SHUFFLE_SILVER).Is(RO_SHUFFLE_SILVER_ON) || + ctx->GetOption(RSK_SHUFFLE_SILVER).Is(RO_SHUFFLE_SILVER_WALLET)) { + ctx->possibleIceTrapModels.insert(RG_SHADOW_SILVER_BLADES); // ice traps reroll this into a random silver rupee + bool isWallet = ctx->GetOption(RSK_SHUFFLE_SILVER).Is(RO_SHUFFLE_SILVER_WALLET); + auto dungeons = ctx->GetDungeons(); + + if (ctx->GetOption(RSK_SHUFFLE_SILVER).Is(RO_SHUFFLE_SILVER_ON)){ + AddItemToPool(RG_SHADOW_SILVER_BLADES, 6,5,5,5, false); + AddItemToPool(RG_SHADOW_SILVER_PIT, 6,5,5,5, false); + AddItemToPool(RG_GTG_SILVER_SLOPE, 6,5,5,5, false); + AddItemToPool(RG_GANONS_CASTLE_SILVER_FIRE, 6,5,5,5, false); + + if (dungeons->GetDungeonFromScene(SCENE_DODONGOS_CAVERN)->IsMQ()) { + AddItemToPool(RG_DODONGOS_CAVERN_MQ_SILVER, 6,5,5,5, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_SHADOW_TEMPLE)->IsMQ()) { + AddItemToPool(RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES, 11,10,10,10, false); + AddItemToPool(RG_SHADOW_SILVER_SPIKES, 11,10,10,10, false); + } else { + AddItemToPool(RG_SHADOW_SILVER_SPIKES, 6,5,5,5, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla()) { + AddItemToPool(RG_SPIRIT_SILVER_CHILD, 6,5,5,5, false); + AddItemToPool(RG_SPIRIT_SILVER_SUN, 6,5,5,5, false); + AddItemToPool(RG_SPIRIT_SILVER_BOULDERS, 6,5,5,5, false); + } else { + AddItemToPool(RG_SPIRIT_MQ_SILVER_LOBBY, 6,5,5,5, false); + AddItemToPool(RG_SPIRIT_MQ_SILVER_BIG_WALL, 6,5,5,5, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL)->IsVanilla()) { + AddItemToPool(RG_BOTW_SILVER, 6,5,5,5, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_ICE_CAVERN)->IsVanilla()) { + AddItemToPool(RG_ICE_CAVERN_SILVER_BLADES, 6,5,5,5, false); + AddItemToPool(RG_ICE_CAVERN_SILVER_BLOCK, 6,5,5,5, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_GERUDO_TRAINING_GROUND)->IsVanilla()) { + AddItemToPool(RG_GTG_SILVER_LAVA, 6,5,5,5, false); + AddItemToPool(RG_GTG_SILVER_WATER, 6,5,5,5, false); + } else { + AddItemToPool(RG_GTG_SILVER_LAVA, 7,6,6,6, false); + AddItemToPool(RG_GTG_SILVER_WATER, 4,3,3,3, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_INSIDE_GANONS_CASTLE)->IsVanilla()) { + AddItemToPool(RG_GANONS_CASTLE_SILVER_LIGHT, 6,5,5,5, false); + AddItemToPool(RG_GANONS_CASTLE_SILVER_FOREST, 6,5,5,5, false); + AddItemToPool(RG_GANONS_CASTLE_SILVER_SPIRIT, 6,5,5,5, false); + } else { + AddItemToPool(RG_GANONS_CASTLE_MQ_SILVER_WATER, 6,5,5,5, false); + AddItemToPool(RG_GANONS_CASTLE_MQ_SILVER_SHADOW, 6,5,5,5, false); + } + } else { + AddItemToPool(RG_SHADOW_SILVER_BLADES, 2,1,1,1, false); + AddItemToPool(RG_SHADOW_SILVER_PIT, 2,1,1,1, false); + AddItemToPool(RG_GTG_SILVER_SLOPE, 2,1,1,1, false); + AddItemToPool(RG_GANONS_CASTLE_SILVER_FIRE, 2,1,1,1, false); + + if (dungeons->GetDungeonFromScene(SCENE_DODONGOS_CAVERN)->IsMQ()) { + AddItemToPool(RG_DODONGOS_CAVERN_MQ_SILVER, 2,1,1,1, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_SHADOW_TEMPLE)->IsMQ()) { + AddItemToPool(RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES, 2,1,1,1, false); + AddItemToPool(RG_SHADOW_SILVER_SPIKES, 2,1,1,1, false); + } else { + AddItemToPool(RG_SHADOW_SILVER_SPIKES, 2,1,1,1, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_SPIRIT_TEMPLE)->IsVanilla()) { + AddItemToPool(RG_SPIRIT_SILVER_CHILD, 2,1,1,1, false); + AddItemToPool(RG_SPIRIT_SILVER_SUN, 2,1,1,1, false); + AddItemToPool(RG_SPIRIT_SILVER_BOULDERS, 2,1,1,1, false); + } else { + AddItemToPool(RG_SPIRIT_MQ_SILVER_LOBBY, 2,1,1,1, false); + AddItemToPool(RG_SPIRIT_MQ_SILVER_BIG_WALL, 2,1,1,1, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL)->IsVanilla()) { + AddItemToPool(RG_BOTW_SILVER, 2,1,1,1, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_ICE_CAVERN)->IsVanilla()) { + AddItemToPool(RG_ICE_CAVERN_SILVER_BLADES, 2,1,1,1, false); + AddItemToPool(RG_ICE_CAVERN_SILVER_BLOCK, 2,1,1,1, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_GERUDO_TRAINING_GROUND)->IsVanilla()) { + AddItemToPool(RG_GTG_SILVER_LAVA, 2,1,1,1, false); + AddItemToPool(RG_GTG_SILVER_WATER, 2,1,1,1, false); + } else { + AddItemToPool(RG_GTG_SILVER_LAVA, 2,1,1,1, false); + AddItemToPool(RG_GTG_SILVER_WATER, 2,1,1,1, false); + } + + if (dungeons->GetDungeonFromScene(SCENE_INSIDE_GANONS_CASTLE)->IsVanilla()) { + AddItemToPool(RG_GANONS_CASTLE_SILVER_LIGHT, 2,1,1,1, false); + AddItemToPool(RG_GANONS_CASTLE_SILVER_FOREST, 2,1,1,1, false); + AddItemToPool(RG_GANONS_CASTLE_SILVER_SPIRIT, 2,1,1,1, false); + } else { + AddItemToPool(RG_GANONS_CASTLE_MQ_SILVER_WATER, 2,1,1,1, false); + AddItemToPool(RG_GANONS_CASTLE_MQ_SILVER_SHADOW, 2,1,1,1, false); + } + } + } + int maxHearts = 20; switch (ctx->GetOption(RSK_ITEM_POOL).Get()) { case RO_ITEM_POOL_PLENTIFUL: diff --git a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp index 30c81ef196..f674efd318 100644 --- a/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/playthrough.cpp @@ -71,14 +71,12 @@ int Playthrough_Init(uint32_t seed, std::set excludedLocations, GenerateHash(); - if (true) { - // TODO: Handle different types of file output (Spoiler Log, Plando Template, Patch Files, Race Files, etc.) - SPDLOG_INFO("Writing Spoiler Log..."); - StartPerformanceTimer(PT_SPOILER_LOG); - SpoilerLog_Write(); - StopPerformanceTimer(PT_SPOILER_LOG); - SPDLOG_INFO("Writing Spoiler Log Done"); - } + // TODO: Handle different types of file output (Spoiler Log, Plando Template, Patch Files, Race Files, etc.) + SPDLOG_INFO("Writing Spoiler Log..."); + StartPerformanceTimer(PT_SPOILER_LOG); + SpoilerLog_Write(); + StopPerformanceTimer(PT_SPOILER_LOG); + SPDLOG_INFO("Writing Spoiler Log Done"); ctx->playthroughLocations.clear(); ctx->playthroughBeatable = false; diff --git a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp index d48c071bf0..f9cb2ab48c 100644 --- a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp @@ -54,6 +54,12 @@ void GenerateStartingInventory() { AddItemToInventory(RG_SHADOW_TEMPLE_BOSS_KEY); } + if (ctx->GetOption(RSK_SHUFFLE_SILVER).Is(RO_SHUFFLE_SILVER_STARTWITH)) { + for (int rg = (int)RG_SHADOW_SILVER_BLADES; rg <= (int)RG_GANONS_CASTLE_MQ_SILVER_SHADOW; rg++) { + AddItemToInventory((RandomizerGet)rg); + } + } + if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_STARTWITH)) { AddItemToInventory(RG_GANONS_CASTLE_BOSS_KEY); } diff --git a/soh/soh/Enhancements/randomizer/RCToRandInf.cpp b/soh/soh/Enhancements/randomizer/RCToRandInf.cpp index 046da9dd33..3e8ebc0aef 100644 --- a/soh/soh/Enhancements/randomizer/RCToRandInf.cpp +++ b/soh/soh/Enhancements/randomizer/RCToRandInf.cpp @@ -3067,4 +3067,158 @@ std::map rcToRandomizerInf = { RAND_INF_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_4 }, { RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_5, RAND_INF_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_5 }, + { RC_SHADOW_N_UNDER_BLADE_SILVER, RAND_INF_RC_SHADOW_N_UNDER_BLADE_SILVER }, + { RC_SHADOW_TALL_BLOCK_BLADE_SILVER, RAND_INF_RC_SHADOW_TALL_BLOCK_BLADE_SILVER }, + { RC_SHADOW_N_NOOK_BLADE_SILVER, RAND_INF_RC_SHADOW_N_NOOK_BLADE_SILVER }, + { RC_SHADOW_W_NOOK_BLADE_SILVER, RAND_INF_SHADOW_W_NOOK_BLADE_SILVER }, + { RC_SHADOW_S_UNDER_BLADE_SILVER, RAND_INF_SHADOW_S_UNDER_BLADE_SILVER }, + { RC_SHADOW_N_PIT_SILVER, RAND_INF_SHADOW_N_PIT_SILVER }, + { RC_SHADOW_S_PIT_SILVER, RAND_INF_SHADOW_S_PIT_SILVER }, + { RC_SHADOW_BEAMOS_PIT_SILVER, RAND_INF_SHADOW_BEAMOS_PIT_SILVER }, + { RC_SHADOW_E_PIT_SILVER, RAND_INF_SHADOW_E_PIT_SILVER }, + { RC_SHADOW_W_PIT_SILVER, RAND_INF_SHADOW_W_PIT_SILVER }, + { RC_SHADOW_PLATFORM_SPIKES_SILVER, RAND_INF_SHADOW_PLATFORM_SPIKES_SILVER }, + { RC_SHADOW_E_TARGET_SPIKES_SILVER, RAND_INF_SHADOW_E_TARGET_SPIKES_SILVER }, + { RC_SHADOW_FLOOR_SPIKES_SILVER, RAND_INF_SHADOW_FLOOR_SPIKES_SILVER }, + { RC_SHADOW_W_TARGET_SPIKES_SILVER, RAND_INF_SHADOW_W_TARGET_SPIKES_SILVER }, + { RC_SHADOW_AIRBORNE_SPIKES_SILVER, RAND_INF_SHADOW_AIRBORNE_SPIKES_SILVER }, + { RC_SPIRIT_W_HIGH_CHILD_SILVER, RAND_INF_SPIRIT_W_HIGH_CHILD_SILVER }, + { RC_SPIRIT_W_LOW_CHILD_SILVER, RAND_INF_SPIRIT_W_LOW_CHILD_SILVER }, + { RC_SPIRIT_E_LOW_CHILD_SILVER, RAND_INF_SPIRIT_E_LOW_CHILD_SILVER }, + { RC_SPIRIT_E_HIGH_CHILD_SILVER, RAND_INF_SPIRIT_E_HIGH_CHILD_SILVER }, + { RC_SPIRIT_TORCH_CHILD_SILVER, RAND_INF_SPIRIT_TORCH_CHILD_SILVER }, + { RC_SPIRIT_NEAR_LIGHT_SUN_SILVER, RAND_INF_SPIRIT_NEAR_LIGHT_SUN_SILVER }, + { RC_SPIRIT_AIRBORNE_SUN_SILVER, RAND_INF_SPIRIT_AIRBORNE_SUN_SILVER }, + { RC_SPIRIT_MID_PLATFORM_SUN_SILVER, RAND_INF_SPIRIT_MID_PLATFORM_SUN_SILVER }, + { RC_SPIRIT_NEAR_CHEST_SUN_SILVER, RAND_INF_SPIRIT_NEAR_CHEST_SUN_SILVER }, + { RC_SPIRIT_NEAR_DOOR_SUN_SILVER, RAND_INF_SPIRIT_NEAR_DOOR_SUN_SILVER }, + { RC_SPIRIT_NW_BOULDER_SILVER, RAND_INF_SPIRIT_NW_BOULDER_SILVER }, + { RC_SPIRIT_SW_BOULDER_SILVER, RAND_INF_SPIRIT_SW_BOULDER_SILVER }, + { RC_SPIRIT_SE_BOULDER_SILVER, RAND_INF_SPIRIT_SE_BOULDER_SILVER }, + { RC_SPIRIT_NE_BOULDER_SILVER, RAND_INF_SPIRIT_NE_BOULDER_SILVER }, + { RC_SPIRIT_AIRBORNE_BOULDER_SILVER, RAND_INF_SPIRIT_AIRBORNE_BOULDER_SILVER }, + { RC_BOTW_B1_LADDER_SILVER, RAND_INF_BOTW_B1_LADDER_SILVER }, + { RC_BOTW_B2_LADDER_SILVER, RAND_INF_BOTW_B2_LADDER_SILVER }, + { RC_BOTW_B3_LADDER_SILVER, RAND_INF_BOTW_B3_LADDER_SILVER }, + { RC_BOTW_NW_OOZE_SILVER, RAND_INF_BOTW_NW_OOZE_SILVER }, + { RC_BOTW_SE_OOZE_SILVER, RAND_INF_BOTW_SE_OOZE_SILVER }, + { RC_ICE_CAVERN_ICICLES_BLADE_SILVER, RAND_INF_ICE_CAVERN_ICICLES_BLADE_SILVER }, + { RC_ICE_CAVERN_W_INNER_BLADE_SILVER, RAND_INF_ICE_CAVERN_W_INNER_BLADE_SILVER }, + { RC_ICE_CAVERN_OUTER_BLADE_SILVER, RAND_INF_ICE_CAVERN_OUTER_BLADE_SILVER }, + { RC_ICE_CAVERN_E_INNER_BLADE_SILVER, RAND_INF_ICE_CAVERN_E_INNER_BLADE_SILVER }, + { RC_ICE_CAVERN_AIRBORNE_BLADE_SILVER, RAND_INF_ICE_CAVERN_AIRBORNE_BLADE_SILVER }, + { RC_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER, RAND_INF_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER }, + { RC_ICE_CAVERN_LOWER_BLOCK_SILVER, RAND_INF_ICE_CAVERN_LOWER_BLOCK_SILVER }, + { RC_ICE_CAVERN_NEAR_BLOCK_SILVER, RAND_INF_ICE_CAVERN_NEAR_BLOCK_SILVER }, + { RC_ICE_CAVERN_FROZEN_BLOCK_SILVER, RAND_INF_ICE_CAVERN_FROZEN_BLOCK_SILVER }, + { RC_ICE_CAVERN_NEAR_GS_BLOCK_SILVER, RAND_INF_ICE_CAVERN_NEAR_GS_BLOCK_SILVER }, + { RC_GTG_FIRE_WALL_SLOPE_SILVER, RAND_INF_GTG_FIRE_WALL_SLOPE_SILVER }, + { RC_GTG_LOWER_BOULDER_SLOPE_SILVER, RAND_INF_GTG_LOWER_BOULDER_SLOPE_SILVER }, + { RC_GTG_TARGET_SLOPE_SILVER, RAND_INF_GTG_TARGET_SLOPE_SILVER }, + { RC_GTG_JUMPDOWN_SLOPE_SILVER, RAND_INF_GTG_JUMPDOWN_SLOPE_SILVER }, + { RC_GTG_UPPER_BOULDER_SLOPE_SILVER, RAND_INF_GTG_UPPER_BOULDER_SLOPE_SILVER }, + { RC_GTG_NEAR_SWITCH_LAVA_SILVER, RAND_INF_GTG_NEAR_SWITCH_LAVA_SILVER }, + { RC_GTG_NEAR_BARRED_DOOR_LAVA_SILVER, RAND_INF_GTG_NEAR_BARRED_DOOR_LAVA_SILVER }, + { RC_GTG_FIRE_RING_LAVA_SILVER, RAND_INF_GTG_FIRE_RING_LAVA_SILVER }, + { RC_GTG_UPPER_LAVA_SILVER, RAND_INF_GTG_UPPER_LAVA_SILVER }, + { RC_GTG_UNDER_LEDGE_LAVA_SILVER, RAND_INF_GTG_UNDER_LEDGE_LAVA_SILVER }, + { RC_GTG_MIDDLE_WATER_SILVER, RAND_INF_GTG_MIDDLE_WATER_SILVER }, + { RC_GTG_ABOVE_TARGET_WATER_SILVER, RAND_INF_GTG_ABOVE_TARGET_WATER_SILVER }, + { RC_GTG_LEFT_WATER_SILVER, RAND_INF_GTG_LEFT_WATER_SILVER }, + { RC_GTG_UNDER_TARGET_WATER_SILVER, RAND_INF_GTG_UNDER_TARGET_WATER_SILVER }, + { RC_GTG_RIGHT_WATER_SILVER, RAND_INF_GTG_RIGHT_WATER_SILVER }, + { RC_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER, RAND_INF_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER }, + { RC_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER, RAND_INF_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER }, + { RC_GANONS_CASTLE_UPPER_LIGHT_SILVER, RAND_INF_GANONS_CASTLE_UPPER_LIGHT_SILVER }, + { RC_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER, RAND_INF_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER }, + { RC_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER, RAND_INF_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER }, + { RC_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER, RAND_INF_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER }, + { RC_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER, RAND_INF_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER }, + { RC_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER, RAND_INF_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER }, + { RC_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER, RAND_INF_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER }, + { RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, RAND_INF_GANONS_CASTLE_ON_TARGET_FOREST_SILVER }, + { RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER, RAND_INF_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER }, + { RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER, RAND_INF_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER }, + { RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, RAND_INF_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER }, + { RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER, RAND_INF_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER }, + { RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER, RAND_INF_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER }, + { RC_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER, RAND_INF_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER }, + { RC_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER, RAND_INF_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER }, + { RC_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER, RAND_INF_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER }, + { RC_GANONS_CASTLE_CORNER_SPIRIT_SILVER, RAND_INF_GANONS_CASTLE_CORNER_SPIRIT_SILVER }, + { RC_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER, RAND_INF_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER }, + { RC_DODONGOS_CAVERN_MQ_BEAMOS_SILVER, RAND_INF_DODONGOS_CAVERN_MQ_BEAMOS_SILVER }, + { RC_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER, RAND_INF_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER }, + { RC_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER, RAND_INF_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER }, + { RC_DODONGOS_CAVERN_MQ_VINES_SILVER, RAND_INF_DODONGOS_CAVERN_MQ_VINES_SILVER }, + { RC_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER, RAND_INF_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER }, + { RC_SHADOW_MQ_W_NOOK_SILVER, RAND_INF_SHADOW_MQ_W_NOOK_SILVER }, + { RC_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER, RAND_INF_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER }, + { RC_SHADOW_MQ_NE_UNDER_BLADE_SILVER, RAND_INF_SHADOW_MQ_NE_UNDER_BLADE_SILVER }, + { RC_SHADOW_MQ_S_UNDER_BLADE_SILVER, RAND_INF_SHADOW_MQ_S_UNDER_BLADE_SILVER }, + { RC_SHADOW_MQ_N_NOOK_BLADE_SILVER, RAND_INF_SHADOW_MQ_N_NOOK_BLADE_SILVER }, + { RC_SHADOW_MQ_W_PIT_SILVER, RAND_INF_SHADOW_MQ_W_PIT_SILVER }, + { RC_SHADOW_MQ_HIGH_PIT_SILVER, RAND_INF_SHADOW_MQ_HIGH_PIT_SILVER }, + { RC_SHADOW_MQ_HIGHEST_PIT_SILVER, RAND_INF_SHADOW_MQ_HIGHEST_PIT_SILVER }, + { RC_SHADOW_MQ_N_PIT_SILVER, RAND_INF_SHADOW_MQ_N_PIT_SILVER }, + { RC_SHADOW_MQ_E_PIT_SILVER, RAND_INF_SHADOW_MQ_E_PIT_SILVER }, + { RC_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER, RAND_INF_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER }, + { RC_SHADOW_MQ_PLATFORM_SPIKES_SILVER, RAND_INF_SHADOW_MQ_PLATFORM_SPIKES_SILVER }, + { RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, RAND_INF_SHADOW_MQ_W_TARGET_SPIKES_SILVER }, + { RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER, RAND_INF_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER }, + { RC_SHADOW_MQ_N_TARGET_SPIKES_SILVER, RAND_INF_SHADOW_MQ_N_TARGET_SPIKES_SILVER }, + { RC_SHADOW_MQ_CENTRAL_SPIKES_SILVER, RAND_INF_SHADOW_MQ_CENTRAL_SPIKES_SILVER }, + { RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER, RAND_INF_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER }, + { RC_SHADOW_MQ_S_TARGET_SPIKES_SILVER, RAND_INF_SHADOW_MQ_S_TARGET_SPIKES_SILVER }, + { RC_SHADOW_MQ_INSIDE_SPIKES_SILVER, RAND_INF_SHADOW_MQ_INSIDE_SPIKES_SILVER }, + { RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER, RAND_INF_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER }, + { RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER, RAND_INF_SHADOW_MQ_E_TARGET_SPIKES_SILVER }, + { RC_SPIRIT_MQ_STAIRS_LOBBY_SILVER, RAND_INF_SPIRIT_MQ_STAIRS_LOBBY_SILVER }, + { RC_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER, RAND_INF_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER }, + { RC_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER, RAND_INF_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER }, + { RC_SPIRIT_MQ_CORNER_LOBBY_SILVER, RAND_INF_SPIRIT_MQ_CORNER_LOBBY_SILVER }, + { RC_SPIRIT_MQ_JET_LOBBY_SILVER, RAND_INF_SPIRIT_MQ_JET_LOBBY_SILVER }, + { RC_SPIRIT_MQ_LOWEST_WALL_SILVER, RAND_INF_SPIRIT_MQ_LOWEST_WALL_SILVER }, + { RC_SPIRIT_MQ_MID_LOW_WALL_SILVER, RAND_INF_SPIRIT_MQ_MID_LOW_WALL_SILVER }, + { RC_SPIRIT_MQ_MID_HIGH_WALL_SILVER, RAND_INF_SPIRIT_MQ_MID_HIGH_WALL_SILVER }, + { RC_SPIRIT_MQ_HIGHEST_WALL_SILVER, RAND_INF_SPIRIT_MQ_HIGHEST_WALL_SILVER }, + { RC_SPIRIT_MQ_MIDDLE_WALL_SILVER, RAND_INF_SPIRIT_MQ_MIDDLE_WALL_SILVER }, + { RC_GTG_MQ_ICICLES_SLOPE_SILVER, RAND_INF_GTG_MQ_ICICLES_SLOPE_SILVER }, + { RC_GTG_MQ_JUMPDOWN_SLOPE_SILVER, RAND_INF_GTG_MQ_JUMPDOWN_SLOPE_SILVER }, + { RC_GTG_MQ_HIGH_SLOPE_SILVER, RAND_INF_GTG_MQ_HIGH_SLOPE_SILVER }, + { RC_GTG_MQ_FREEZARD_SLOPE_SILVER, RAND_INF_GTG_MQ_FREEZARD_SLOPE_SILVER }, + { RC_GTG_MQ_PIT_SLOPE_SILVER, RAND_INF_GTG_MQ_PIT_SLOPE_SILVER }, + { RC_GTG_MQ_NEAR_SWITCH_LAVA_SILVER, RAND_INF_GTG_MQ_NEAR_SWITCH_LAVA_SILVER }, + { RC_GTG_MQ_FAR_LAVA_SILVER, RAND_INF_GTG_MQ_FAR_LAVA_SILVER }, + { RC_GTG_MQ_MIDDLE_LAVA_SILVER, RAND_INF_GTG_MQ_MIDDLE_LAVA_SILVER }, + { RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, RAND_INF_GTG_MQ_SILVER_LAVA_4 }, + { RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, RAND_INF_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER }, + { RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, RAND_INF_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER }, + { RC_GTG_MQ_BACK_WATER_SILVER, RAND_INF_GTG_MQ_BACK_WATER_SILVER }, + { RC_GTG_MQ_MIDDLE_WATER_SILVER, RAND_INF_GTG_MQ_MIDDLE_WATER_SILVER }, + { RC_GTG_MQ_FRONT_WATER_SILVER, RAND_INF_GTG_MQ_FRONT_WATER_SILVER }, + { RC_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER, RAND_INF_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER }, + { RC_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER, RAND_INF_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER }, + { RC_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER, RAND_INF_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER }, + { RC_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER, RAND_INF_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER }, + { RC_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER, RAND_INF_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER }, + { RC_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER, RAND_INF_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER }, + { RC_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER, RAND_INF_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER }, + { RC_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER, RAND_INF_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER }, + { RC_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER, RAND_INF_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER }, + { RC_GANONS_CASTLE_MQ_NOOK_WATER_SILVER, RAND_INF_GANONS_CASTLE_MQ_NOOK_WATER_SILVER }, + { RC_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER, RAND_INF_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER }, + { RC_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER, RAND_INF_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER }, + { RC_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER, RAND_INF_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER }, + { RC_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER, RAND_INF_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER }, + { RC_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER, RAND_INF_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER }, }; \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/SeedContext.cpp b/soh/soh/Enhancements/randomizer/SeedContext.cpp index ae663c9d87..c4ca7b1140 100644 --- a/soh/soh/Enhancements/randomizer/SeedContext.cpp +++ b/soh/soh/Enhancements/randomizer/SeedContext.cpp @@ -14,6 +14,7 @@ #include "../kaleido.h" #include "soh/Enhancements/randomizer/Traps.h" #include "soh/Enhancements/randomizer/rng.h" +#include "soh/Enhancements/randomizer/randomizer_check_tracker.h" #include "soh/Enhancements/randomizer/randomizer.h" #include @@ -209,6 +210,7 @@ void Context::GenerateLocationPool() { mOptions[RSK_SHUFFLE_WONDER_ITEMS].Is(RO_SHUFFLE_WONDER_ITEMS_OFF)) || (location.GetRCType() == RCTYPE_FREESTANDING && mOptions[RSK_SHUFFLE_FREESTANDING].Is(RO_SHUFFLE_FREESTANDING_OFF)) || + (location.GetRCType() == RCTYPE_SILVER && !mOptions[RSK_SHUFFLE_SILVER]) || (location.GetRCType() == RCTYPE_BEEHIVE && !mOptions[RSK_SHUFFLE_BEEHIVES])) { continue; } @@ -367,8 +369,8 @@ void Context::SetSpoilerLoaded(const bool spoilerLoaded) { mSpoilerLoaded = spoilerLoaded; } -GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool checkObtainability, - const GetItemID ogItemId) { +GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool checkObtainability, const GetItemID ogItemId, + bool spoilAreas) { const auto itemLoc = GetItemLocation(rc); if (itemLoc->GetPlacedRandomizerGet() == RG_NONE) { if (ogItemId != GI_NONE) { @@ -379,6 +381,9 @@ GetItemEntry Context::GetFinalGIEntry(const RandomizerCheck rc, const bool check } if (checkObtainability && OTRGlobals::Instance->gRandomizer->GetItemObtainabilityFromRandomizerGet( itemLoc->GetPlacedRandomizerGet()) != CAN_OBTAIN) { + if (spoilAreas) { + CheckTracker::SpoilAreaFromCantObtain(itemLoc->GetPlacedRandomizerGet()); + } return ItemTableManager::Instance->RetrieveItemEntry(MOD_NONE, GI_RUPEE_BLUE); } GetItemEntry giEntry = itemLoc->GetPlacedItem().GetGIEntry_Copy(); @@ -496,6 +501,10 @@ DungeonInfo* Context::GetDungeon(size_t key) const { return mDungeons->GetDungeon(static_cast(key)); } +DungeonInfo* Context::GetDungeonFromScene(SceneID scene) const { + return mDungeons->GetDungeonFromScene(scene); +} + std::shared_ptr Context::GetLogic() { if (mLogic.get() == nullptr) { mLogic = std::make_shared(); diff --git a/soh/soh/Enhancements/randomizer/SeedContext.h b/soh/soh/Enhancements/randomizer/SeedContext.h index cc87f66cfc..5dc7d6ee25 100644 --- a/soh/soh/Enhancements/randomizer/SeedContext.h +++ b/soh/soh/Enhancements/randomizer/SeedContext.h @@ -89,6 +89,7 @@ class Context { std::shared_ptr GetDungeons(); std::shared_ptr GetFishsanity(); DungeonInfo* GetDungeon(size_t key) const; + DungeonInfo* GetDungeonFromScene(SceneID key) const; std::shared_ptr GetLogic(); std::shared_ptr GetTrials(); std::shared_ptr GetKaleido(); @@ -119,7 +120,8 @@ class Context { void GanonsSoulCondition(RandoOptionCheckTrigger condition); void WinCondition(RandoOptionWincon condition); - GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE); + GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE, + bool spoilAreas = false); void ParseSpoiler(const char* spoilerFileName); void ParseHashIconIndexesJson(const nlohmann::json& spoilerFileJson); void ParseItemLocationsJson(const nlohmann::json& spoilerFileJson); diff --git a/soh/soh/Enhancements/randomizer/ShuffleSilver.cpp b/soh/soh/Enhancements/randomizer/ShuffleSilver.cpp new file mode 100644 index 0000000000..337f8cee8b --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ShuffleSilver.cpp @@ -0,0 +1,462 @@ +#include +#include "dungeon.h" +#include "SeedContext.h" +#include "draw.h" +#include "static_data.h" +#include "randomizer.h" // IWYU pragma: keep +#include "ShuffleSilver.h" + +extern "C" { +#include "overlays/actors/ovl_En_G_Switch/z_en_g_switch.h" +extern PlayState* gPlayState; +extern SaveContext gSaveContext; +} + +extern void EnItem00_DrawRandomizedItem(EnItem00* enItem00, PlayState* play); + +bool IsSilverInPool(RandomizerGet rg) { + auto ctx = Rando::Context::GetInstance(); + switch (rg) { + case RG_SHADOW_SILVER_BLADES: + case RG_SHADOW_SILVER_PIT: + case RG_SHADOW_SILVER_SPIKES: + case RG_GTG_SILVER_SLOPE: + case RG_GTG_SILVER_LAVA: + case RG_GTG_SILVER_WATER: + case RG_GANONS_CASTLE_SILVER_FIRE: + return true; + case RG_SPIRIT_SILVER_CHILD: + case RG_SPIRIT_SILVER_SUN: + case RG_SPIRIT_SILVER_BOULDERS: + return ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->IsVanilla(); + case RG_BOTW_SILVER: + return ctx->GetDungeon(Rando::BOTTOM_OF_THE_WELL)->IsVanilla(); + case RG_ICE_CAVERN_SILVER_BLADES: + case RG_ICE_CAVERN_SILVER_BLOCK: + return ctx->GetDungeon(Rando::ICE_CAVERN)->IsVanilla(); + case RG_GANONS_CASTLE_SILVER_LIGHT: + case RG_GANONS_CASTLE_SILVER_FOREST: + case RG_GANONS_CASTLE_SILVER_SPIRIT: + return ctx->GetDungeon(Rando::GANONS_CASTLE)->IsVanilla(); + case RG_DODONGOS_CAVERN_MQ_SILVER: + return ctx->GetDungeon(Rando::DODONGOS_CAVERN)->IsMQ(); + case RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES: + return ctx->GetDungeon(Rando::SHADOW_TEMPLE)->IsMQ(); + case RG_SPIRIT_MQ_SILVER_LOBBY: + case RG_SPIRIT_MQ_SILVER_BIG_WALL: + return ctx->GetDungeon(Rando::SPIRIT_TEMPLE)->IsMQ(); + case RG_GANONS_CASTLE_MQ_SILVER_WATER: + case RG_GANONS_CASTLE_MQ_SILVER_SHADOW: + return ctx->GetDungeon(Rando::GANONS_CASTLE)->IsMQ(); + default: + assert(false); + return false; + } +} + +std::set Rando::StaticData::constantSilvers = { RG_SHADOW_SILVER_BLADES, RG_SHADOW_SILVER_PIT, + RG_SHADOW_SILVER_SPIKES, RG_GTG_SILVER_SLOPE, + RG_GTG_SILVER_LAVA, RG_GTG_SILVER_WATER, + RG_GANONS_CASTLE_SILVER_FIRE }; + +std::unordered_map Rando::StaticData::silverToArea = { + { RG_DODONGOS_CAVERN_MQ_SILVER, RCAREA_DODONGOS_CAVERN }, + { RG_SPIRIT_SILVER_CHILD, RCAREA_SPIRIT_TEMPLE }, + { RG_SPIRIT_SILVER_SUN, RCAREA_SPIRIT_TEMPLE }, + { RG_SPIRIT_SILVER_BOULDERS, RCAREA_SPIRIT_TEMPLE }, + { RG_SPIRIT_MQ_SILVER_LOBBY, RCAREA_SPIRIT_TEMPLE }, + { RG_SPIRIT_MQ_SILVER_BIG_WALL, RCAREA_SPIRIT_TEMPLE }, + { RG_SHADOW_SILVER_BLADES, RCAREA_SHADOW_TEMPLE }, + { RG_SHADOW_SILVER_PIT, RCAREA_SHADOW_TEMPLE }, + { RG_SHADOW_SILVER_SPIKES, RCAREA_SHADOW_TEMPLE }, + { RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES, RCAREA_SHADOW_TEMPLE }, + { RG_GANONS_CASTLE_SILVER_LIGHT, RCAREA_GANONS_CASTLE }, + { RG_GANONS_CASTLE_SILVER_FOREST, RCAREA_GANONS_CASTLE }, + { RG_GANONS_CASTLE_SILVER_FIRE, RCAREA_GANONS_CASTLE }, + { RG_GANONS_CASTLE_SILVER_SPIRIT, RCAREA_GANONS_CASTLE }, + { RG_GANONS_CASTLE_MQ_SILVER_WATER, RCAREA_GANONS_CASTLE }, + { RG_GANONS_CASTLE_MQ_SILVER_SHADOW, RCAREA_GANONS_CASTLE }, + { RG_ICE_CAVERN_SILVER_BLADES, RCAREA_ICE_CAVERN }, + { RG_ICE_CAVERN_SILVER_BLOCK, RCAREA_ICE_CAVERN }, + { RG_BOTW_SILVER, RCAREA_BOTTOM_OF_THE_WELL }, + { RG_GTG_SILVER_SLOPE, RCAREA_GERUDO_TRAINING_GROUND }, + { RG_GTG_SILVER_LAVA, RCAREA_GERUDO_TRAINING_GROUND }, + { RG_GTG_SILVER_WATER, RCAREA_GERUDO_TRAINING_GROUND } +}; + +RandomizerGet SilverFromSwitchFlag(s16 switchFlag) { + bool isMQ = Rando::Context::GetInstance()->GetDungeonFromScene((SceneID)gPlayState->sceneNum)->IsMQ(); + switch (gPlayState->sceneNum) { + case SCENE_DODONGOS_CAVERN: + return RG_DODONGOS_CAVERN_MQ_SILVER; + case SCENE_SHADOW_TEMPLE: + switch (switchFlag) { + case 1: + return RG_SHADOW_SILVER_BLADES; + case 3: + return RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES; + case 8: + return RG_SHADOW_SILVER_SPIKES; + case 9: + case 17: + return RG_SHADOW_SILVER_PIT; + } + break; + case SCENE_SPIRIT_TEMPLE: + switch (switchFlag) { + case 0: + return RG_SPIRIT_MQ_SILVER_BIG_WALL; + case 2: + return RG_SPIRIT_SILVER_BOULDERS; + case 5: + return RG_SPIRIT_SILVER_CHILD; + case 10: + return RG_SPIRIT_SILVER_SUN; + case 55: // Likely error + return RG_SPIRIT_MQ_SILVER_LOBBY; + } + break; + case SCENE_BOTTOM_OF_THE_WELL: + return RG_BOTW_SILVER; + case SCENE_ICE_CAVERN: + switch (switchFlag) { + case 8: + case 9: + return RG_ICE_CAVERN_SILVER_BLOCK; + case 31: + return RG_ICE_CAVERN_SILVER_BLADES; + } + break; + case SCENE_GERUDO_TRAINING_GROUND: + switch (switchFlag) { + case 12: + return RG_GTG_SILVER_LAVA; + case 27: + return RG_GTG_SILVER_WATER; + case 28: + return RG_GTG_SILVER_SLOPE; + } + break; + case SCENE_INSIDE_GANONS_CASTLE: + switch (switchFlag) { + case 1: + return RG_GANONS_CASTLE_SILVER_FIRE; + case 2: + return RG_GANONS_CASTLE_MQ_SILVER_WATER; + case 9: + return RG_GANONS_CASTLE_SILVER_FIRE; + case 11: + return isMQ ? RG_GANONS_CASTLE_MQ_SILVER_SHADOW : RG_GANONS_CASTLE_SILVER_SPIRIT; + case 14: + return RG_GANONS_CASTLE_SILVER_FOREST; + case 18: + return RG_GANONS_CASTLE_SILVER_LIGHT; + } + break; + default: + break; + } + assert(false); // no matching silver found + return RG_NONE; +} + +s8* Randomizer::SilverFieldFromSaveContext(SaveContext* saveContext, RandomizerGet rg) { + switch (rg) { + case RG_SHADOW_SILVER_BLADES: + return &saveContext->ship.quest.data.randomizer.silverShadowBlades; + case RG_SHADOW_SILVER_PIT: + return &saveContext->ship.quest.data.randomizer.silverShadowPit; + case RG_SHADOW_SILVER_SPIKES: + return &saveContext->ship.quest.data.randomizer.silverShadowSpikes; + case RG_SPIRIT_SILVER_CHILD: + return &saveContext->ship.quest.data.randomizer.silverSpiritChild; + case RG_SPIRIT_SILVER_SUN: + return &saveContext->ship.quest.data.randomizer.silverSpiritSun; + case RG_SPIRIT_SILVER_BOULDERS: + return &saveContext->ship.quest.data.randomizer.silverSpiritBoulders; + case RG_BOTW_SILVER: + return &saveContext->ship.quest.data.randomizer.silverBotw; + case RG_ICE_CAVERN_SILVER_BLADES: + return &saveContext->ship.quest.data.randomizer.silverIceCavernBlades; + case RG_ICE_CAVERN_SILVER_BLOCK: + return &saveContext->ship.quest.data.randomizer.silverIceCavernBlock; + case RG_GTG_SILVER_SLOPE: + return &saveContext->ship.quest.data.randomizer.silverGtgSlope; + case RG_GTG_SILVER_LAVA: + return &saveContext->ship.quest.data.randomizer.silverGtgLava; + case RG_GTG_SILVER_WATER: + return &saveContext->ship.quest.data.randomizer.silverGtgWater; + case RG_GANONS_CASTLE_SILVER_LIGHT: + return &saveContext->ship.quest.data.randomizer.silverGanonLight; + case RG_GANONS_CASTLE_SILVER_FOREST: + return &saveContext->ship.quest.data.randomizer.silverGanonForest; + case RG_GANONS_CASTLE_SILVER_FIRE: + return &saveContext->ship.quest.data.randomizer.silverGanonFire; + case RG_GANONS_CASTLE_SILVER_SPIRIT: + return &saveContext->ship.quest.data.randomizer.silverGanonSpirit; + case RG_DODONGOS_CAVERN_MQ_SILVER: + return &saveContext->ship.quest.data.randomizer.silverMqDodongosCavern; + case RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES: + return &saveContext->ship.quest.data.randomizer.silverMqShadowInvisibleBlades; + case RG_SPIRIT_MQ_SILVER_LOBBY: + return &saveContext->ship.quest.data.randomizer.silverMqSpiritLobby; + case RG_SPIRIT_MQ_SILVER_BIG_WALL: + return &saveContext->ship.quest.data.randomizer.silverMqSpiritBigWall; + case RG_GANONS_CASTLE_MQ_SILVER_WATER: + return &saveContext->ship.quest.data.randomizer.silverMqGanonWater; + case RG_GANONS_CASTLE_MQ_SILVER_SHADOW: + return &saveContext->ship.quest.data.randomizer.silverMqGanonShadow; + default: + return nullptr; + } +} + +s8 Randomizer::SilverTotal(RandomizerGet rg) { + auto ctx = Rando::Context::GetInstance(); + return rg == RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES || + (rg == RG_SHADOW_SILVER_SPIKES && ctx->GetDungeon(Rando::SHADOW_TEMPLE)->IsMQ()) + ? 10 + : (rg == RG_GTG_SILVER_LAVA && ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUND)->IsMQ()) ? 6 + : (rg == RG_GTG_SILVER_WATER && ctx->GetDungeon(Rando::GERUDO_TRAINING_GROUND)->IsMQ()) ? 3 + : 5; +} + +bool IsSilverCleared(s16 switchFlag) { + RandomizerGet rg = SilverFromSwitchFlag(switchFlag); + return *Randomizer::SilverFieldFromSaveContext(&gSaveContext, rg) >= Randomizer::SilverTotal(rg); +} + +bool IsSilverCleared(RandomizerGet rg) { + auto test = *Randomizer::SilverFieldFromSaveContext(&gSaveContext, rg); + auto test2 = Randomizer::SilverTotal(rg); + return *Randomizer::SilverFieldFromSaveContext(&gSaveContext, rg) >= Randomizer::SilverTotal(rg); +} + +bool IsSilver(RandomizerGet rg) { + return rg >= RG_SHADOW_SILVER_BLADES && rg <= RG_GANONS_CASTLE_MQ_SILVER_SHADOW; +} + +extern "C" void EnGSwitch_RandomizerDraw(Actor* thisx, PlayState* play) { + EnGSwitch* silver = reinterpret_cast(thisx); + Matrix_Push(); + Matrix_Scale(17.5f, 17.5f, 17.5f, MTXMODE_APPLY); + if (silver->type == ENGSWITCH_SILVER_RUPEE) { + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { + GetItemEntry_Draw(play, GET_ITEM_MYSTERY); + } else { + auto silverIdentity = + OTRGlobals::Instance->gRandomizer->IdentifySilver(gPlayState->sceneNum, silver->actor.world.pos); + auto itemEntry = + Rando::Context::GetInstance()->GetFinalGIEntry(silverIdentity.randomizerCheck, true, GI_NONE); + GetItemEntry_Draw(play, itemEntry); + } + Matrix_Pop(); + } +} + +void RegisterShuffleSilver() { + bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_SILVER); + + COND_VB_SHOULD(VB_SILVER_COLLECT, shouldRegister, { + if (*should) { + EnGSwitch* silver = va_arg(args, EnGSwitch*); + auto silverIdentity = + OTRGlobals::Instance->gRandomizer->IdentifySilver(gPlayState->sceneNum, silver->actor.world.pos); + Flags_SetRandomizerInf(silverIdentity.randomizerInf); + Actor_Kill(&silver->actor); + *should = false; + } + }); + + COND_VB_SHOULD(VB_SILVER_COUNT_CHECK, shouldRegister, { + EnGSwitch* silver = va_arg(args, EnGSwitch*); + *should = false; + if (IsSilverCleared(silver->switchFlag)) { + Flags_SetSwitch(gPlayState, silver->switchFlag); + Actor_Kill(&silver->actor); + } + }); + + COND_VB_SHOULD(VB_SILVER_DESPAWN, shouldRegister, { + EnGSwitch* silver = va_arg(args, EnGSwitch*); + if (silver->type == ENGSWITCH_SILVER_RUPEE) { + auto silverIdentity = + OTRGlobals::Instance->gRandomizer->IdentifySilver(gPlayState->sceneNum, silver->actor.world.pos); + *should = silverIdentity.randomizerCheck == RC_UNKNOWN_CHECK || + Flags_GetRandomizerInf(silverIdentity.randomizerInf); + if (!*should) { + *should = false; + silver->actor.draw = EnGSwitch_RandomizerDraw; + } + } else if (silver->type == ENGSWITCH_SILVER_TRACKER && IsSilverCleared(silver->switchFlag)) { + Flags_SetSwitch(gPlayState, silver->switchFlag); + *should = true; + } + }); +} + +void Rando::StaticData::RegisterSilverLocations() { + static bool registered = false; + if (registered) + return; + registered = true; + // clang-format off + locationTable[RC_SHADOW_N_UNDER_BLADE_SILVER] = Location::Collectable(RC_SHADOW_N_UNDER_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3243, -1061), "North Under Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_RC_SHADOW_N_UNDER_BLADE_SILVER)); + locationTable[RC_SHADOW_TALL_BLOCK_BLADE_SILVER] = Location::Collectable(RC_SHADOW_TALL_BLOCK_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3007, -1222), "Tall Block Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_RC_SHADOW_TALL_BLOCK_BLADE_SILVER)); + locationTable[RC_SHADOW_N_NOOK_BLADE_SILVER] = Location::Collectable(RC_SHADOW_N_NOOK_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3554, -1432), "North Nook Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_RC_SHADOW_N_NOOK_BLADE_SILVER)); + locationTable[RC_SHADOW_W_NOOK_BLADE_SILVER] = Location::Collectable(RC_SHADOW_W_NOOK_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2869, -948), "West Nook Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_W_NOOK_BLADE_SILVER)); + locationTable[RC_SHADOW_S_UNDER_BLADE_SILVER] = Location::Collectable(RC_SHADOW_S_UNDER_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3399, -838), "South Under Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_S_UNDER_BLADE_SILVER)); + locationTable[RC_SHADOW_N_PIT_SILVER] = Location::Collectable(RC_SHADOW_N_PIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2131, 3030), "North Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_N_PIT_SILVER)); + locationTable[RC_SHADOW_S_PIT_SILVER] = Location::Collectable(RC_SHADOW_S_PIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2115, 3738), "South Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_S_PIT_SILVER)); + locationTable[RC_SHADOW_BEAMOS_PIT_SILVER] = Location::Collectable(RC_SHADOW_BEAMOS_PIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2110, 3368), "Beamos Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_BEAMOS_PIT_SILVER)); + locationTable[RC_SHADOW_E_PIT_SILVER] = Location::Collectable(RC_SHADOW_E_PIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2243, 3361), "East Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_E_PIT_SILVER)); + locationTable[RC_SHADOW_W_PIT_SILVER] = Location::Collectable(RC_SHADOW_W_PIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(1998, 3358), "West Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_W_PIT_SILVER)); + locationTable[RC_SHADOW_PLATFORM_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_PLATFORM_SPIKES_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2042, 849), "Platform Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_PLATFORM_SPIKES_SILVER)); + locationTable[RC_SHADOW_E_TARGET_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_E_TARGET_SPIKES_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2940, 1069), "East Target Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_E_TARGET_SPIKES_SILVER)); + locationTable[RC_SHADOW_FLOOR_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_FLOOR_SPIKES_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1208), "Floor Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_FLOOR_SPIKES_SILVER)); + locationTable[RC_SHADOW_W_TARGET_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_W_TARGET_SPIKES_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2135, 1297), "West Target Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_W_TARGET_SPIKES_SILVER)); + locationTable[RC_SHADOW_AIRBORNE_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_AIRBORNE_SPIKES_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2254, 988), "Airborne Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_AIRBORNE_SPIKES_SILVER)); + locationTable[RC_SPIRIT_W_HIGH_CHILD_SILVER] = Location::Collectable(RC_SPIRIT_W_HIGH_CHILD_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-766, -1075), "West High Child Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_W_HIGH_CHILD_SILVER)); + locationTable[RC_SPIRIT_W_LOW_CHILD_SILVER] = Location::Collectable(RC_SPIRIT_W_LOW_CHILD_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-672, -1075), "West Low Child Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_W_LOW_CHILD_SILVER)); + locationTable[RC_SPIRIT_E_LOW_CHILD_SILVER] = Location::Collectable(RC_SPIRIT_E_LOW_CHILD_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-511, -1075), "East Low Child Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_E_LOW_CHILD_SILVER)); + locationTable[RC_SPIRIT_E_HIGH_CHILD_SILVER] = Location::Collectable(RC_SPIRIT_E_HIGH_CHILD_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-347, -1075), "East High Child Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_E_HIGH_CHILD_SILVER)); + locationTable[RC_SPIRIT_TORCH_CHILD_SILVER] = Location::Collectable(RC_SPIRIT_TORCH_CHILD_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-335, -1409), "Torch Child Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TORCH_CHILD_SILVER)); + locationTable[RC_SPIRIT_NEAR_LIGHT_SUN_SILVER] = Location::Collectable(RC_SPIRIT_NEAR_LIGHT_SUN_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1836, -446), "Near Light Sun Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_NEAR_LIGHT_SUN_SILVER)); + locationTable[RC_SPIRIT_AIRBORNE_SUN_SILVER] = Location::Collectable(RC_SPIRIT_AIRBORNE_SUN_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1433, -283), "Airborne Sun Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_AIRBORNE_SUN_SILVER)); + locationTable[RC_SPIRIT_MID_PLATFORM_SUN_SILVER] = Location::Collectable(RC_SPIRIT_MID_PLATFORM_SUN_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1275, -247), "Middle Platform Sun Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MID_PLATFORM_SUN_SILVER)); + locationTable[RC_SPIRIT_NEAR_CHEST_SUN_SILVER] = Location::Collectable(RC_SPIRIT_NEAR_CHEST_SUN_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-1123, 428), "Near Chest Sun Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_NEAR_CHEST_SUN_SILVER)); + locationTable[RC_SPIRIT_NEAR_DOOR_SUN_SILVER] = Location::Collectable(RC_SPIRIT_NEAR_DOOR_SUN_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-984, -450), "Near Door Sun Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_NEAR_DOOR_SUN_SILVER)); + locationTable[RC_SPIRIT_NW_BOULDER_SILVER] = Location::Collectable(RC_SPIRIT_NW_BOULDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1284, -1355), "Northwest Boulder Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_NW_BOULDER_SILVER)); + locationTable[RC_SPIRIT_SW_BOULDER_SILVER] = Location::Collectable(RC_SPIRIT_SW_BOULDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1284, -813), "Southwest Boulder Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_SW_BOULDER_SILVER)); + locationTable[RC_SPIRIT_SE_BOULDER_SILVER] = Location::Collectable(RC_SPIRIT_SE_BOULDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1856, -944), "Southeast Boulder Super", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_SE_BOULDER_SILVER)); + locationTable[RC_SPIRIT_NE_BOULDER_SILVER] = Location::Collectable(RC_SPIRIT_NE_BOULDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1856, -1219), "Notheast Boulder Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_NE_BOULDER_SILVER)); + locationTable[RC_SPIRIT_AIRBORNE_BOULDER_SILVER] = Location::Collectable(RC_SPIRIT_AIRBORNE_BOULDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1573, -920), "Airborne Boulder Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_AIRBORNE_BOULDER_SILVER)); + locationTable[RC_BOTW_B1_LADDER_SILVER] = Location::Collectable(RC_BOTW_B1_LADDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-796, -150), "B1 Ladder Silver", RHT_BOTW_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_B1_LADDER_SILVER)); + locationTable[RC_BOTW_B2_LADDER_SILVER] = Location::Collectable(RC_BOTW_B2_LADDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-614, -297), "B2 Ladder Silver", RHT_BOTW_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_B2_LADDER_SILVER)); + locationTable[RC_BOTW_B3_LADDER_SILVER] = Location::Collectable(RC_BOTW_B3_LADDER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-560, -291), "B3 Ladder Silver", RHT_BOTW_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_B3_LADDER_SILVER)); + locationTable[RC_BOTW_NW_OOZE_SILVER] = Location::Collectable(RC_BOTW_NW_OOZE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-402, -401), "Northwest Ooze Silver", RHT_BOTW_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_NW_OOZE_SILVER)); + locationTable[RC_BOTW_SE_OOZE_SILVER] = Location::Collectable(RC_BOTW_SE_OOZE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_BOTTOM_OF_THE_WELL, TWO_ACTOR_PARAMS(-259, -234), "Southeast Ooze Silver", RHT_BOTW_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_BOTW_SE_OOZE_SILVER)); + locationTable[RC_ICE_CAVERN_ICICLES_BLADE_SILVER] = Location::Collectable(RC_ICE_CAVERN_ICICLES_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(1, -143), "Icicles Blade Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_ICICLES_BLADE_SILVER)); + locationTable[RC_ICE_CAVERN_W_INNER_BLADE_SILVER] = Location::Collectable(RC_ICE_CAVERN_W_INNER_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(198, -388), "West Inner Blade Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_W_INNER_BLADE_SILVER)); + locationTable[RC_ICE_CAVERN_OUTER_BLADE_SILVER] = Location::Collectable(RC_ICE_CAVERN_OUTER_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(278, -637), "Outer Blade Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_OUTER_BLADE_SILVER)); + locationTable[RC_ICE_CAVERN_E_INNER_BLADE_SILVER] = Location::Collectable(RC_ICE_CAVERN_E_INNER_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(389, -382), "East Inner Blade Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_E_INNER_BLADE_SILVER)); + locationTable[RC_ICE_CAVERN_AIRBORNE_BLADE_SILVER] = Location::Collectable(RC_ICE_CAVERN_AIRBORNE_BLADE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(414, -579), "Airborne Blade Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_AIRBORNE_BLADE_SILVER)); + locationTable[RC_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER] = Location::Collectable(RC_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1676, -552), "Near Fire Block Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER)); + locationTable[RC_ICE_CAVERN_LOWER_BLOCK_SILVER] = Location::Collectable(RC_ICE_CAVERN_LOWER_BLOCK_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1558, -951), "Lower Block Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_LOWER_BLOCK_SILVER)); + locationTable[RC_ICE_CAVERN_NEAR_BLOCK_SILVER] = Location::Collectable(RC_ICE_CAVERN_NEAR_BLOCK_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1294, -899), "Near Block Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_NEAR_BLOCK_SILVER)); + locationTable[RC_ICE_CAVERN_FROZEN_BLOCK_SILVER] = Location::Collectable(RC_ICE_CAVERN_FROZEN_BLOCK_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1120, -1577), "Frozen Block Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_FROZEN_BLOCK_SILVER)); + locationTable[RC_ICE_CAVERN_NEAR_GS_BLOCK_SILVER] = Location::Collectable(RC_ICE_CAVERN_NEAR_GS_BLOCK_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_ICE_CAVERN, TWO_ACTOR_PARAMS(-1040, -485), "Near GS Block Silver", RHT_ICE_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_ICE_CAVERN_NEAR_GS_BLOCK_SILVER)); + locationTable[RC_GTG_FIRE_WALL_SLOPE_SILVER] = Location::Collectable(RC_GTG_FIRE_WALL_SLOPE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1332, -992), "Fire Wall Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_FIRE_WALL_SLOPE_SILVER)); + locationTable[RC_GTG_LOWER_BOULDER_SLOPE_SILVER] = Location::Collectable(RC_GTG_LOWER_BOULDER_SLOPE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1886, -956), "Lower Boulder Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_LOWER_BOULDER_SLOPE_SILVER)); + locationTable[RC_GTG_TARGET_SLOPE_SILVER] = Location::Collectable(RC_GTG_TARGET_SLOPE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1579, -999), "Target Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_TARGET_SLOPE_SILVER)); + locationTable[RC_GTG_JUMPDOWN_SLOPE_SILVER] = Location::Collectable(RC_GTG_JUMPDOWN_SLOPE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1627, -1462), "Jumpdown Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_JUMPDOWN_SLOPE_SILVER)); + locationTable[RC_GTG_UPPER_BOULDER_SLOPE_SILVER] = Location::Collectable(RC_GTG_UPPER_BOULDER_SLOPE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1887, -2134), "Upper Boulder Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_UPPER_BOULDER_SLOPE_SILVER)); + locationTable[RC_GTG_NEAR_SWITCH_LAVA_SILVER] = Location::Collectable(RC_GTG_NEAR_SWITCH_LAVA_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1320, -1248), "Near Switch Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_NEAR_SWITCH_LAVA_SILVER)); + locationTable[RC_GTG_NEAR_BARRED_DOOR_LAVA_SILVER] = Location::Collectable(RC_GTG_NEAR_BARRED_DOOR_LAVA_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1558, -1370), "Near Barred Door Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_NEAR_BARRED_DOOR_LAVA_SILVER)); + locationTable[RC_GTG_FIRE_RING_LAVA_SILVER] = Location::Collectable(RC_GTG_FIRE_RING_LAVA_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1134, -1841), "Fire Ring Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_FIRE_RING_LAVA_SILVER)); + locationTable[RC_GTG_UPPER_LAVA_SILVER] = Location::Collectable(RC_GTG_UPPER_LAVA_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1437, -2193), "Upper Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_UPPER_LAVA_SILVER)); + locationTable[RC_GTG_UNDER_LEDGE_LAVA_SILVER] = Location::Collectable(RC_GTG_UNDER_LEDGE_LAVA_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1560, -1861), "Under Ledge Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_UNDER_LEDGE_LAVA_SILVER)); + locationTable[RC_GTG_MIDDLE_WATER_SILVER] = Location::Collectable(RC_GTG_MIDDLE_WATER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2308, -1464), "Middle Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MIDDLE_WATER_SILVER)); + locationTable[RC_GTG_ABOVE_TARGET_WATER_SILVER] = Location::Collectable(RC_GTG_ABOVE_TARGET_WATER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2497, -1465), "Above Target Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_ABOVE_TARGET_WATER_SILVER)); + locationTable[RC_GTG_LEFT_WATER_SILVER] = Location::Collectable(RC_GTG_LEFT_WATER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2453, -1612), "Left Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_LEFT_WATER_SILVER)); + locationTable[RC_GTG_UNDER_TARGET_WATER_SILVER] = Location::Collectable(RC_GTG_UNDER_TARGET_WATER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2078, -1458), "Under Target Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_UNDER_TARGET_WATER_SILVER)); + locationTable[RC_GTG_RIGHT_WATER_SILVER] = Location::Collectable(RC_GTG_RIGHT_WATER_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2160, -1315), "Right Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_RIGHT_WATER_SILVER)); + locationTable[RC_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2509, -1091), "Outer Right Light Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER)); + locationTable[RC_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2649, -545), "Outer Left Light Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER)); + locationTable[RC_GANONS_CASTLE_UPPER_LIGHT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_UPPER_LIGHT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2646, -839), "Upper Light Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_UPPER_LIGHT_SILVER)); + locationTable[RC_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2680, -893), "Inner Right Light Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER)); + locationTable[RC_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2674, -777), "Inner Left Light Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER)); + locationTable[RC_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER] = Location::Collectable(RC_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1247, 1787), "Large Platform Forest Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER)); + locationTable[RC_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER] = Location::Collectable(RC_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1361, 1222), "SoT Block Forest Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER)); + locationTable[RC_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER] = Location::Collectable(RC_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1538, 2225), "Small Platform Forest Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER)); + locationTable[RC_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER] = Location::Collectable(RC_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1651, 2021), "Under Ledge Forest Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER)); + locationTable[RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER] = Location::Collectable(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1634, 1550), "On Target Forest Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_ON_TARGET_FOREST_SILVER)); + locationTable[RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-854, -3679), "Torch Slug Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1555, -2317), "Flame Jets Fire Temple Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-515, -3253), "Distant Platform Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-604, -2592), "Close Platform Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER)); + locationTable[RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER] = Location::Collectable(RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1867, -2754), "Under Pillar Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-829, 591), "Airborne Spirit Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER)); + locationTable[RC_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-940, 270), "Near Doormat Spirit Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER)); + locationTable[RC_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-865, 656), "Lower Middle Spirit Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER)); + locationTable[RC_GANONS_CASTLE_CORNER_SPIRIT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_CORNER_SPIRIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-725, 942), "Corner Spirit Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_CORNER_SPIRIT_SILVER)); + locationTable[RC_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER] = Location::Collectable(RC_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER, RCQUEST_VANILLA, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1142, 639), "Near Barred Door Spirit Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER)); + locationTable[RC_DODONGOS_CAVERN_MQ_BEAMOS_SILVER] = Location::Collectable(RC_DODONGOS_CAVERN_MQ_BEAMOS_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-2277, -1362), "MQ Beamos Silver", RHT_DODONGOS_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_BEAMOS_SILVER)); + locationTable[RC_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER] = Location::Collectable(RC_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-2189, -1834), "MQ 1F Crate Silver", RHT_DODONGOS_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER)); + locationTable[RC_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER] = Location::Collectable(RC_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-2411, -1836), "MQ Lower 2F Crate Silver", RHT_DODONGOS_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER)); + locationTable[RC_DODONGOS_CAVERN_MQ_VINES_SILVER] = Location::Collectable(RC_DODONGOS_CAVERN_MQ_VINES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-1907, -1243), "MQ Vines Silver", RHT_DODONGOS_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_VINES_SILVER)); + locationTable[RC_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER] = Location::Collectable(RC_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_DODONGOS_CAVERN, TWO_ACTOR_PARAMS(-1512, -1083), "MQ Upper 2F Crate Silver", RHT_DODONGOS_CAVERN_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER)); + locationTable[RC_SHADOW_MQ_W_NOOK_SILVER] = Location::Collectable(RC_SHADOW_MQ_W_NOOK_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2810, -961 ), "MQ West Nook Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_W_NOOK_SILVER)); + locationTable[RC_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3007, -1222), "MQ Tall Block Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_NE_UNDER_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_NE_UNDER_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3243, -1061), "MQ Northwest Under Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_NE_UNDER_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_S_UNDER_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_S_UNDER_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3399, -838 ), "MQ South Under Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_S_UNDER_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_N_NOOK_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_N_NOOK_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(3558, -1490), "MQ North Nook Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_N_NOOK_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_W_PIT_SILVER] = Location::Collectable(RC_SHADOW_MQ_W_PIT_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(1970, 3372), "MQ West Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_W_PIT_SILVER)); + locationTable[RC_SHADOW_MQ_HIGH_PIT_SILVER] = Location::Collectable(RC_SHADOW_MQ_HIGH_PIT_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2110, -970), "MQ High Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_HIGH_PIT_SILVER)); + locationTable[RC_SHADOW_MQ_HIGHEST_PIT_SILVER] = Location::Collectable(RC_SHADOW_MQ_HIGHEST_PIT_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2110, -1092), "MQ Highest Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_HIGHEST_PIT_SILVER)); + locationTable[RC_SHADOW_MQ_N_PIT_SILVER] = Location::Collectable(RC_SHADOW_MQ_N_PIT_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2131, 3030), "MQ North Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_N_PIT_SILVER)); + locationTable[RC_SHADOW_MQ_E_PIT_SILVER] = Location::Collectable(RC_SHADOW_MQ_E_PIT_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2250, 3372), "MQ East Pit Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_E_PIT_SILVER)); + locationTable[RC_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5089, 2049), "MQ West Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5158, 2315), "MQ Southwest Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5217, 1852), "MQ Northwest Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5270, 2453), "MQ South Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5404, 1977), "MQ Inner Northeast Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5466, 2243), "MQ Southeast Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5489, 2476), "MQ Outside Circle Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5601, 1898), "MQ Outer Northeast Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5637, 2134), "MQ East Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER] = Location::Collectable(RC_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(5667, 2686), "MQ SoT Block Invisible Blade Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER)); + locationTable[RC_SHADOW_MQ_PLATFORM_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_PLATFORM_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2042, 849), "MQ Platform Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_PLATFORM_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2135, 1297), "MQ West Target Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_W_TARGET_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2254, 988), "MQ West Airborne Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_N_TARGET_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_N_TARGET_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 893), "MQ North Target Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_N_TARGET_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_CENTRAL_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_CENTRAL_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1208), "MQ Central Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_CENTRAL_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1200), "MQ Central Target Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_S_TARGET_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_S_TARGET_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2478, 1404), "MQ South Target Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_S_TARGET_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_INSIDE_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_INSIDE_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2705, 1089), "MQ Inside Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_INSIDE_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2730, 876), "MQ East Airborne Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER)); + locationTable[RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER] = Location::Collectable(RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SHADOW_TEMPLE, TWO_ACTOR_PARAMS(2940, 1069), "MQ East Target Spikes Silver", RHT_SHADOW_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SHADOW_MQ_E_TARGET_SPIKES_SILVER)); + locationTable[RC_SPIRIT_MQ_STAIRS_LOBBY_SILVER] = Location::Collectable(RC_SPIRIT_MQ_STAIRS_LOBBY_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(1016, -73), "MQ Stairs Lobby Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_STAIRS_LOBBY_SILVER)); + locationTable[RC_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER] = Location::Collectable(RC_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(160, 268), "MQ East Boulder Lobby Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER)); + locationTable[RC_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER] = Location::Collectable(RC_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(-160, 270), "MQ West Boulder Lobby Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER)); + locationTable[RC_SPIRIT_MQ_CORNER_LOBBY_SILVER] = Location::Collectable(RC_SPIRIT_MQ_CORNER_LOBBY_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(967, -547), "MQ Corner Lobby Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_CORNER_LOBBY_SILVER)); + locationTable[RC_SPIRIT_MQ_JET_LOBBY_SILVER] = Location::Collectable(RC_SPIRIT_MQ_JET_LOBBY_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(744, 4), "MQ Jet Lobby Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_JET_LOBBY_SILVER)); + locationTable[RC_SPIRIT_MQ_LOWEST_WALL_SILVER] = Location::Collectable(RC_SPIRIT_MQ_LOWEST_WALL_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(723, -75), "MQ Lowest Big Wall Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_LOWEST_WALL_SILVER)); + locationTable[RC_SPIRIT_MQ_MID_LOW_WALL_SILVER] = Location::Collectable(RC_SPIRIT_MQ_MID_LOW_WALL_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(582, -75), "MQ Mid-Low Wall Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_MID_LOW_WALL_SILVER)); + locationTable[RC_SPIRIT_MQ_MID_HIGH_WALL_SILVER] = Location::Collectable(RC_SPIRIT_MQ_MID_HIGH_WALL_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(754, -75), "MQ Mid-High Wall Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_MID_HIGH_WALL_SILVER)); + locationTable[RC_SPIRIT_MQ_HIGHEST_WALL_SILVER] = Location::Collectable(RC_SPIRIT_MQ_HIGHEST_WALL_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(644, -75), "MQ Highest Wall Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_HIGHEST_WALL_SILVER)); + locationTable[RC_SPIRIT_MQ_MIDDLE_WALL_SILVER] = Location::Collectable(RC_SPIRIT_MQ_MIDDLE_WALL_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(681, -75), "MQ Middle Wall Silver", RHT_SPIRIT_TEMPLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_MQ_MIDDLE_WALL_SILVER)); + locationTable[RC_GTG_MQ_ICICLES_SLOPE_SILVER] = Location::Collectable(RC_GTG_MQ_ICICLES_SLOPE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1245, -2112), "MQ Icicles Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_ICICLES_SLOPE_SILVER)); + locationTable[RC_GTG_MQ_JUMPDOWN_SLOPE_SILVER] = Location::Collectable(RC_GTG_MQ_JUMPDOWN_SLOPE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1542, -1467), "MQ Jumpdown Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_JUMPDOWN_SLOPE_SILVER)); + locationTable[RC_GTG_MQ_HIGH_SLOPE_SILVER] = Location::Collectable(RC_GTG_MQ_HIGH_SLOPE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1480, -1000), "MQ High Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_HIGH_SLOPE_SILVER)); + locationTable[RC_GTG_MQ_FREEZARD_SLOPE_SILVER] = Location::Collectable(RC_GTG_MQ_FREEZARD_SLOPE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1886, -956), "MQ Freezard Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_FREEZARD_SLOPE_SILVER)); + locationTable[RC_GTG_MQ_PIT_SLOPE_SILVER] = Location::Collectable(RC_GTG_MQ_PIT_SLOPE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(-1261, -923), "MQ Pit Slope Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_PIT_SLOPE_SILVER)); + locationTable[RC_GTG_MQ_NEAR_SWITCH_LAVA_SILVER] = Location::Collectable(RC_GTG_MQ_NEAR_SWITCH_LAVA_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1560, -1861), "MQ Near Switch Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_NEAR_SWITCH_LAVA_SILVER)); + locationTable[RC_GTG_MQ_FAR_LAVA_SILVER] = Location::Collectable(RC_GTG_MQ_FAR_LAVA_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1134, -1841), "MQ Far Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_FAR_LAVA_SILVER)); + locationTable[RC_GTG_MQ_MIDDLE_LAVA_SILVER] = Location::Collectable(RC_GTG_MQ_MIDDLE_LAVA_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1404, -1653), "MQ Middle Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_MIDDLE_LAVA_SILVER)); + locationTable[RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER] = Location::Collectable(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1560, -1380), "MQ Near Barred Door Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_SILVER_LAVA_4)); + locationTable[RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER] = Location::Collectable(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1083, -1374), "MQ Near Maze Ledge Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER)); + locationTable[RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER] = Location::Collectable(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(1317, -1243), "MQ Near Lit Torch Lava Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER)); + locationTable[RC_GTG_MQ_BACK_WATER_SILVER] = Location::Collectable(RC_GTG_MQ_BACK_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2453, -1612), "MQ Back Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_BACK_WATER_SILVER)); + locationTable[RC_GTG_MQ_MIDDLE_WATER_SILVER] = Location::Collectable(RC_GTG_MQ_MIDDLE_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2302, -1464), "MQ Middle Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_MIDDLE_WATER_SILVER)); + locationTable[RC_GTG_MQ_FRONT_WATER_SILVER] = Location::Collectable(RC_GTG_MQ_FRONT_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_GERUDO_TRAINING_GROUND, TWO_ACTOR_PARAMS(2160, -1315), "MQ Front Water Silver", RHT_GTG_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GTG_MQ_FRONT_WATER_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-970, -3747), "MQ Under Pillar Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1891, -2753), "MQ Near Target Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-2044, -3354), "MQ On Pillar Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-686, -2945), "MQ Launch Platform Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(-1655, -2133), "MQ Jet Platform Fire Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2757, -765), "MQ In Hole Water Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2912, -971), "MQ Airborne Water Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2905, -1478), "MQ Frozen Water Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(3253, -649), "MQ Over Pit Water Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_NOOK_WATER_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_NOOK_WATER_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(2905, -1263), "MQ Nook Water Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_NOOK_WATER_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1322, -2262), "MQ Bomb Flower Shadow Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1279, -3111), "MQ Near Torch Shadow Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1529, -4117), "MQ Beamos Platform Shadow Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1829, -4071), "MQ Guillotine Shadow Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER)); + locationTable[RC_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER] = Location::Collectable(RC_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER, RCQUEST_MQ, RCTYPE_SILVER, ACTOR_EN_G_SWITCH, SCENE_INSIDE_GANONS_CASTLE, TWO_ACTOR_PARAMS(1100, -2554), "MQ Moving Platform Shadow Trial Silver", RHT_GANONS_CASTLE_SILVER, RG_BLUE_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER)); + // clang-format on +} + +static RegisterShipInitFunc registerShuffleSilver(RegisterShuffleSilver, { "IS_RANDO" }); +static RegisterShipInitFunc registerShuffleSilverLocations(Rando::StaticData::RegisterSilverLocations); diff --git a/soh/soh/Enhancements/randomizer/ShuffleSilver.h b/soh/soh/Enhancements/randomizer/ShuffleSilver.h new file mode 100644 index 0000000000..d0fff9e542 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ShuffleSilver.h @@ -0,0 +1,12 @@ +#pragma once + +#include +#include "randomizerEnums.h" +#include +#include + +bool IsSilverInPool(RandomizerGet rg); +RandomizerGet SilverFromSwitchFlag(s16 switchFlag); +bool IsSilverCleared(s16 switchFlag); +bool IsSilverCleared(RandomizerGet rg); +bool IsSilver(RandomizerGet rg); diff --git a/soh/soh/Enhancements/randomizer/Traps.cpp b/soh/soh/Enhancements/randomizer/Traps.cpp index 964eef8236..5fb9326967 100644 --- a/soh/soh/Enhancements/randomizer/Traps.cpp +++ b/soh/soh/Enhancements/randomizer/Traps.cpp @@ -1231,6 +1231,94 @@ static void InitTrickNames() { Text{ "Squid-Hunt Key", "Squid-Hunt Key", "Squid-Hunt Key" }, }; + trickNameTable[RG_SHADOW_SILVER_BLADES] = { + // TODO_TRANSLATE + Text{ "Shadow Silver: Bladders" }, + }; + trickNameTable[RG_SHADOW_SILVER_PIT] = { + // TODO_TRANSLATE + Text{ "Shadow Silver: Bit" }, + }; + trickNameTable[RG_SHADOW_SILVER_SPIKES] = { + // TODO_TRANSLATE + Text{ "Shadow Silver: Spines" }, + }; + trickNameTable[RG_SPIRIT_SILVER_CHILD] = { + // TODO_TRANSLATE + Text{ "Spirit Silver: Chill" }, + }; + trickNameTable[RG_SPIRIT_SILVER_SUN] = { + // TODO_TRANSLATE + Text{ "Spirit Silver: Son" }, + }; + trickNameTable[RG_SPIRIT_SILVER_BOULDERS] = { + // TODO_TRANSLATE + Text{ "Spirit Silver: Bounders" }, + }; + trickNameTable[RG_BOTW_SILVER] = { + // TODO_TRANSLATE + Text{ "Bottom of the Well Slipper" }, + }; + trickNameTable[RG_ICE_CAVERN_SILVER_BLADES] = { + // TODO_TRANSLATE + Text{ "Ice Cavern Silver: Blaze" }, + }; + trickNameTable[RG_ICE_CAVERN_SILVER_BLOCK] = { + // TODO_TRANSLATE + Text{ "Ice Cavern Silver: Black" }, + }; + trickNameTable[RG_GTG_SILVER_SLOPE] = { + // TODO_TRANSLATE + Text{ "Training Ground Silver: Snope" }, + }; + trickNameTable[RG_GTG_SILVER_LAVA] = { + // TODO_TRANSLATE + Text{ "Traning Ground Silver: Love" }, + }; + trickNameTable[RG_GTG_SILVER_WATER] = { + // TODO_TRANSLATE + Text{ "Training Pound Silver: Water" }, + }; + trickNameTable[RG_GANONS_CASTLE_SILVER_LIGHT] = { + // TODO_TRANSLATE + Text{ "Ganon's Castle Silver: Lighter" }, + }; + trickNameTable[RG_GANONS_CASTLE_SILVER_FOREST] = { + // TODO_TRANSLATE + Text{ "Ganon's Castle Silver: Frost" }, + }; + trickNameTable[RG_GANONS_CASTLE_SILVER_FIRE] = { + // TODO_TRANSLATE + Text{ "Ganon's Castle Silver: Free" }, + }; + trickNameTable[RG_GANONS_CASTLE_SILVER_SPIRIT] = { + // TODO_TRANSLATE + Text{ "Ganon's Castle Silver: Sprite" }, + }; + trickNameTable[RG_DODONGOS_CAVERN_MQ_SILVER] = { + // TODO_TRANSLATE + Text{ "Dodongo's Cave Silver" }, + }; + trickNameTable[RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES] = { + // TODO_TRANSLATE + Text{ "Shadow Silver: Invisible" }, + }; + trickNameTable[RG_SPIRIT_MQ_SILVER_LOBBY] = { + // TODO_TRANSLATE + Text{ "Spirit Silver: Foyer" }, + }; + trickNameTable[RG_SPIRIT_MQ_SILVER_BIG_WALL] = { + // TODO_TRANSLATE + Text{ "Spirit Silver: Brick" }, + }; + trickNameTable[RG_GANONS_CASTLE_MQ_SILVER_WATER] = { + // TODO_TRANSLATE + Text{ "Ganon's Castle Silver: Wheat" }, + }; + trickNameTable[RG_GANONS_CASTLE_MQ_SILVER_SHADOW] = { + // TODO_TRANSLATE + Text{ "Ganon's Castle Silver: Shabom" }, + }; /* //Names for individual upgrades, in case progressive names are replaced trickNameTable[GI_HOOKSHOT] = { @@ -1451,6 +1539,8 @@ RandomizerGet Rando::Traps::GetTrapTrickModel(uint64_t* state) { trickModel = ShipUtils::RandomElement(Rando::StaticData::overworldKeys, state); } else if (trickModel == RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL) { trickModel = ShipUtils::RandomElement(Rando::StaticData::beanSouls, state); + } else if (trickModel == RG_SHADOW_SILVER_BLADES) { + trickModel = ShipUtils::RandomElement(Rando::StaticData::silverRupees); } return trickModel; diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp index 50678184c4..10eaa8ce69 100644 --- a/soh/soh/Enhancements/randomizer/draw.cpp +++ b/soh/soh/Enhancements/randomizer/draw.cpp @@ -11,11 +11,13 @@ extern "C" { #include "functions.h" #include "variables.h" #include "dungeon.h" +#include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_gi_key/object_gi_key.h" #include "objects/object_gi_bosskey/object_gi_bosskey.h" #include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_map/object_gi_map.h" #include "objects/object_gi_hearts/object_gi_hearts.h" +#include "objects/object_gi_rupy/object_gi_rupy.h" #include "objects/object_gi_scale/object_gi_scale.h" #include "objects/object_gi_fire/object_gi_fire.h" #include "objects/object_toki_objects/object_toki_objects.h" @@ -28,9 +30,10 @@ extern "C" { #include "objects/object_mamenoki/object_mamenoki.h" #include "objects/object_mo/object_mo.h" #include "objects/object_sst/object_sst.h" -#include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h" #include "objects/object_tw/object_tw.h" #include "objects/object_ganon2/object_ganon2.h" +#include "objects/object_mo/object_mo.h" +#include "overlays/actors/ovl_Boss_Goma/z_boss_goma.h" extern PlayState* gPlayState; extern SaveContext gSaveContext; } @@ -1235,6 +1238,46 @@ extern "C" void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemE CLOSE_DISPS(play->state.gfxCtx); } +extern "C" void Randomizer_DrawSilverRupee(PlayState* play, GetItemEntry* getItemEntry) { + OPEN_DISPS(play->state.gfxCtx); + Gfx_SetupDL_25Opa(play->state.gfxCtx); + Color_RGB8 defaultColor = { 255, 255, 255 }; + if (CVarGetInteger("gEnhancements.NewDrops", 0) != 0) { + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + Color_RGB8 silverRupeeColor = CVarGetColor24("gCosmetics.Consumable_SilverRupee.Value", defaultColor); + Gfx_SetupDL_25Opa(play->state.gfxCtx); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0x80, silverRupeeColor.r, silverRupeeColor.g, silverRupeeColor.b, 255); + gDPSetEnvColor(POLY_OPA_DISP++, silverRupeeColor.r / 5, silverRupeeColor.g / 5, silverRupeeColor.b / 5, 255); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gGiRupeeInnerDL); + Gfx_SetupDL_25Xlu(play->state.gfxCtx); + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_MODELVIEW | G_MTX_LOAD); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, 255); + gDPSetEnvColor(POLY_XLU_DISP++, silverRupeeColor.r * 0.75f, silverRupeeColor.g * 0.75f, + silverRupeeColor.b * 0.75f, 255); + gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gGiRupeeOuterDL); + } else { + Matrix_Scale(0.05f, 0.05f, 0.05f, MTXMODE_APPLY); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__), + G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + if (CVarGetInteger("gCosmetics.Consumable_SilverRupee.Changed", 0)) { + Color_RGB8 rupeeColor = CVarGetColor24("gCosmetics.Consumable_SilverRupee.Value", defaultColor); + gDPSetGrayscaleColor(POLY_OPA_DISP++, rupeeColor.r, rupeeColor.g, rupeeColor.b, 255); + gSPGrayscale(POLY_OPA_DISP++, true); + gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL((uintptr_t)gRupeeSilverTex)); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gRupeeDL); + gSPGrayscale(POLY_OPA_DISP++, false); + } else { + gSPSegment(POLY_OPA_DISP++, 0x08, SEGMENTED_TO_VIRTUAL((uintptr_t)gRupeeSilverTex)); + gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gRupeeDL); + } + } + CLOSE_DISPS(play->state.gfxCtx); +} + extern "C" void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry) { OPEN_DISPS(play->state.gfxCtx); diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h index 8c27526e8a..a9937afad9 100644 --- a/soh/soh/Enhancements/randomizer/draw.h +++ b/soh/soh/Enhancements/randomizer/draw.h @@ -27,6 +27,7 @@ void Randomizer_DrawLadder(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawKneePads(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawJabberNut(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawOpenChest(PlayState* play, GetItemEntry* getItemEntry); +void Randomizer_DrawSilverRupee(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawFishingPoleGI(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry); void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry* getItemEntry); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index c9b8de0fe3..d71876e5ae 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -86,7 +86,7 @@ bool LocMatchesQuest(Rando::Location loc) { if (loc.GetQuest() == RCQUEST_BOTH) { return true; } else { - auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc.GetScene()); + auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(loc.GetScene()); return (dungeon->IsMQ() && loc.GetQuest() == RCQUEST_MQ) || (dungeon->IsVanilla() && loc.GetQuest() == RCQUEST_VANILLA); } @@ -324,7 +324,7 @@ void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) { void RandomizerOnSceneFlagSetHandler(int16_t sceneNum, int16_t flagType, int16_t flag) { if (flagType == FLAG_SCENE_SWITCH) { - auto dungeonInfo = Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(sceneNum); + auto dungeonInfo = Rando::Context::GetInstance()->GetDungeonFromScene((SceneID)sceneNum); bool isVanilla = dungeonInfo == nullptr || dungeonInfo->IsVanilla(); switch (sceneNum) { @@ -414,7 +414,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { RandomizerGet vanillaRandomizerGet = Rando::StaticData::GetLocation(rc)->GetVanillaItem(); GetItemID vanillaItem = (GetItemID)Rando::StaticData::RetrieveItem(vanillaRandomizerGet).GetItemID(); GetItemEntry getItemEntry = - Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet); + Rando::Context::GetInstance()->GetFinalGIEntry(rc, true, (GetItemID)vanillaRandomizerGet, true); GetItemCategory getItemCategory = Randomizer_AdjustItemCategory(getItemEntry); if (loc->HasObtained()) { @@ -1705,8 +1705,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l } case VB_OKARINA_TAG_COMPLETE: { if (gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL) { - auto dungeon = - OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); if (dungeon->IsVanilla()) { EnOkarinaTag* enOkarinaTag = va_arg(args, EnOkarinaTag*); if (enOkarinaTag->switchFlag >= 0 && Flags_GetSwitch(gPlayState, enOkarinaTag->switchFlag)) { @@ -1719,8 +1718,7 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l } case VB_OKARINA_TAG_COMPLETED: { if (gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL) { - auto dungeon = - OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); if (dungeon->IsVanilla()) { *should = false; } @@ -2287,7 +2285,7 @@ void RandomizerOnActorInitHandler(void* actorRef) { Actor* actor = static_cast(actorRef); if (actor->id == ACTOR_PLAYER) { - auto dungeonInfo = Rando::Context::GetInstance()->GetDungeons()->GetDungeonFromScene(gPlayState->sceneNum); + auto dungeonInfo = Rando::Context::GetInstance()->GetDungeonFromScene((SceneID)gPlayState->sceneNum); bool isVanilla = dungeonInfo == nullptr || dungeonInfo->IsVanilla(); switch (gPlayState->sceneNum) { case SCENE_DEKU_TREE: @@ -2676,8 +2674,7 @@ void RandomizerOnActorInitHandler(void* actorRef) { // Turn MQ switch into toggle if (actor->id == ACTOR_OBJ_SWITCH && gPlayState->sceneNum == SCENE_BOTTOM_OF_THE_WELL && (actor->params & 0x3f07) == 0x303) { - auto dungeon = - OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); + auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(SCENE_BOTTOM_OF_THE_WELL); if (dungeon->IsMQ()) { actor->params |= 0x10; } diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index a0c7b68e4f..ef6208e40a 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -17,6 +17,7 @@ enum ItemType { ITEMTYPE_SMALLKEY, ITEMTYPE_TOKEN, ITEMTYPE_FORTRESS_SMALLKEY, + ITEMTYPE_SILVER, ITEMTYPE_EVENT, ITEMTYPE_DROP, ITEMTYPE_REFILL, diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 3f8ab70871..b5004410ac 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -165,7 +165,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "une ", "einen "}, "%p").CustomIcon(gQuestIconSmallKeyTex, ICON_SIZE_24); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "une ", "einen "}, "%y").CustomIcon(gQuestIconSmallKeyTex, ICON_SIZE_24); + itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "une ", "einen "}, "%y").CustomIcon(gQuestIconSmallKeyTex, ICON_SIZE_24); itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "une ", "einen "}, "%y").CustomIcon(gQuestIconSmallKeyTex, ICON_SIZE_24); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); @@ -241,6 +241,51 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "le ", "den "}); itemTable[RG_TREASURE_GAME_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); + // Silver Rupees + itemTable[RG_SHADOW_SILVER_BLADES] = Item(RG_SHADOW_SILVER_BLADES, Text{ "Shadow Silver: Blades", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SHADOW_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SHADOW_SILVER_BLADES].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_SILVER_PIT] = Item(RG_SHADOW_SILVER_PIT, Text{ "Shadow Silver: Pit", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SHADOW_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SHADOW_SILVER_PIT].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_SILVER_SPIKES] = Item(RG_SHADOW_SILVER_SPIKES, Text{ "Shadow Silver: Spikes", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SHADOW_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SHADOW_SILVER_SPIKES].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_SILVER_CHILD] = Item(RG_SPIRIT_SILVER_CHILD, Text{ "Spirit Silver: Child", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SPIRIT_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_SILVER_CHILD].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_SILVER_SUN] = Item(RG_SPIRIT_SILVER_SUN, Text{ "Spirit Silver: Sun", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SPIRIT_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_SILVER_SUN].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_SILVER_BOULDERS] = Item(RG_SPIRIT_SILVER_BOULDERS, Text{ "Spirit Silver: Boulders", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SPIRIT_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_SILVER_BOULDERS].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_BOTW_SILVER] = Item(RG_BOTW_SILVER, Text{ "Bottom of the Well Silver", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_BOTW, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOTW_SILVER].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_ICE_CAVERN_SILVER_BLADES] = Item(RG_ICE_CAVERN_SILVER_BLADES, Text{ "Ice Cavern Silver: Blades", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_ICE_CAVERN, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_SILVER_BLADES].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_ICE_CAVERN_SILVER_BLOCK] = Item(RG_ICE_CAVERN_SILVER_BLOCK, Text{ "Ice Cavern Silver: Block", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_ICE_CAVERN, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_SILVER_BLOCK].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GTG_SILVER_SLOPE] = Item(RG_GTG_SILVER_SLOPE, Text{ "Training Ground Silver: Slope", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GTG, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GTG_SILVER_SLOPE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GTG_SILVER_LAVA] = Item(RG_GTG_SILVER_LAVA, Text{ "Training Ground Silver: Lava", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GTG, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GTG_SILVER_LAVA].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GTG_SILVER_WATER] = Item(RG_GTG_SILVER_WATER, Text{ "Training Ground Silver: Water", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GTG, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GTG_SILVER_WATER].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GANONS_CASTLE_SILVER_LIGHT] = Item(RG_GANONS_CASTLE_SILVER_LIGHT, Text{ "Ganon's Castle Silver: Light", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GANONS_CASTLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_SILVER_LIGHT].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GANONS_CASTLE_SILVER_FOREST] = Item(RG_GANONS_CASTLE_SILVER_FOREST, Text{ "Ganon's Castle Silver: Forest", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GANONS_CASTLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_SILVER_FOREST].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GANONS_CASTLE_SILVER_FIRE] = Item(RG_GANONS_CASTLE_SILVER_FIRE, Text{ "Ganon's Castle Silver: Fire", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GANONS_CASTLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_SILVER_FIRE].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GANONS_CASTLE_SILVER_SPIRIT] = Item(RG_GANONS_CASTLE_SILVER_SPIRIT, Text{ "Ganon's Castle Silver: Spirit", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GANONS_CASTLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_SILVER_SPIRIT].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_DODONGOS_CAVERN_MQ_SILVER] = Item(RG_DODONGOS_CAVERN_MQ_SILVER, Text{ "Dodongo's Cavern Silver", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_DODONGOS_CAVERN, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_MQ_SILVER].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES] = Item(RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES, Text{ "Shadow Silver: Invisible Blades", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SHADOW_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_MQ_SILVER_LOBBY] = Item(RG_SPIRIT_MQ_SILVER_LOBBY, Text{ "Spirit Silver: Lobby", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SPIRIT_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_MQ_SILVER_LOBBY].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_SPIRIT_MQ_SILVER_BIG_WALL] = Item(RG_SPIRIT_MQ_SILVER_BIG_WALL, Text{ "Spirit Silver: Big Wall", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_SPIRIT_TEMPLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_MQ_SILVER_BIG_WALL].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GANONS_CASTLE_MQ_SILVER_WATER] = Item(RG_GANONS_CASTLE_MQ_SILVER_WATER, Text{ "Ganon's Castle Silver: Water", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GANONS_CASTLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_MQ_SILVER_WATER].SetCustomDrawFunc(Randomizer_DrawSilverRupee); + itemTable[RG_GANONS_CASTLE_MQ_SILVER_SHADOW] = Item(RG_GANONS_CASTLE_MQ_SILVER_SHADOW, Text{ "Ganon's Castle Silver: Shadow", TODO_TRANSLATE, TODO_TRANSLATE }, ITEMTYPE_SILVER, GI_RUPEE_GOLD, true, LOGIC_NONE, RHT_SILVER_RUPEE_GANONS_CASTLE, RG_NONE, OBJECT_GI_RUPY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_MQ_SILVER_SHADOW].SetCustomDrawFunc(Randomizer_DrawSilverRupee); // Dungeon Rewards itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "l'", "den "}, "%g"); itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "le ", "den "}, "%r"); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp index e264c9d310..5ed22840e9 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/bottom_of_the_well.cpp @@ -187,16 +187,16 @@ void RegionTable_Init_BottomOfTheWell() { areaTable[RR_BOTW_B3_OOZE] = Region("Bottom of the Well B3 Ooze", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_1, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_2, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_3, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_4, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_5, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_6, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_7, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_8, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_9, logic->CanBreakPots()), - LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_10, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_1, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_2, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_3, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_4, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_5, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_6, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_7, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_8, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_9, logic->CanBreakPots()), + LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_10, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_11, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_POT_12, logic->CanBreakPots()), LOCATION(RC_BOTTOM_OF_THE_WELL_BASEMENT_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), @@ -206,13 +206,17 @@ void RegionTable_Init_BottomOfTheWell() { LOCATION(RC_BOTW_BOULDER_1, logic->BlastOrSmash()), LOCATION(RC_BOTW_BOULDER_2, logic->BlastOrSmash()), LOCATION(RC_BOTW_BOULDER_3, logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (logic->CanUse(RG_STICKS) && ctx->GetTrickOption(RT_BOTW_BASEMENT)) || - (ctx->GetTrickOption(RT_BOULDER_COLLISION) && logic->CanUse(RG_FAIRY_BOW))), + (ctx->GetTrickOption(RT_BOULDER_COLLISION) && logic->CanUse(RG_FAIRY_BOW))), LOCATION(RC_BOTW_BOULDER_4, logic->BlastOrSmash()), LOCATION(RC_BOTW_BOULDER_5, logic->BlastOrSmash()), LOCATION(RC_BOTW_BOULDER_6, logic->BlastOrSmash()), + LOCATION(RC_BOTW_B2_LADDER_SILVER, logic->CanClimbLadder()), + LOCATION(RC_BOTW_B3_LADDER_SILVER, true), + LOCATION(RC_BOTW_NW_OOZE_SILVER, true), + LOCATION(RC_BOTW_SE_OOZE_SILVER, true), }, { //Exits - ENTRANCE(RR_BOTW_HIDDEN_POTS, logic->CanClimbHighLadder()), + ENTRANCE(RR_BOTW_LADDER_DOOR, logic->CanClimbHighLadder()), //It's possible to abuse boulder's limited range of collision detection to detonate the flowers through the boulder with bow, but this is a glitch //the exact range is just past the furthest away plank in the green goo section ENTRANCE(RR_BOTW_B3_BOMB_FLOWERS, AnyAgeTime([]{return logic->BlastOrSmash() || logic->CanUse(RG_DINS_FIRE) || (ctx->GetTrickOption(RT_BOTW_BASEMENT) && logic->CanUse(RG_STICKS)) || (ctx->GetTrickOption(RT_BOULDER_COLLISION) && logic->CanUse(RG_FAIRY_BOW));})), @@ -220,6 +224,19 @@ void RegionTable_Init_BottomOfTheWell() { ENTRANCE(RR_BOTW_B3_CHEST_AREA, AnyAgeTime([]{return logic->BlastOrSmash();})), }); + areaTable[RR_BOTW_LADDER_DOOR] = Region("Bottom of the Well Ladder Door", SCENE_BOTTOM_OF_THE_WELL, { + // Events + EVENT_ACCESS(LOGIC_BOTW_SILVER, true), + }, { + //Locations + LOCATION(RC_BOTW_B1_LADDER_SILVER, true), + LOCATION(RC_BOTW_B2_LADDER_SILVER, true), + }, { + //Exits + ENTRANCE(RR_BOTW_B3_OOZE, true), + ENTRANCE(RR_BOTW_HIDDEN_POTS, logic->HasItem(RG_BOTW_SILVER)), + }); + areaTable[RR_BOTW_B3_BOMB_FLOWERS] = Region("Bottom of the Well B3 Bomb Flowers", SCENE_BOTTOM_OF_THE_WELL, {}, { //Locations LOCATION(RC_BOTW_BOULDER_1, logic->HasItem(RG_GORONS_BRACELET)), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp index 51c26b6c52..a505291099 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/dodongos_cavern.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/randomizer/location_access.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" using namespace Rando; @@ -356,6 +357,8 @@ void RegionTable_Init_DodongosCavern() { LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_POT_4, logic->CanBreakPots()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_LOWER_CRATE_2, logic->CanBreakCrates()), + LOCATION(RC_DODONGOS_CAVERN_MQ_BEAMOS_SILVER, true), + LOCATION(RC_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER, logic->CanBreakCrates() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->IsChild)), }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_LOBBY, true), @@ -378,26 +381,33 @@ void RegionTable_Init_DodongosCavern() { areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER] = Region("Dodongos Cavern MQ Stairs Upper", SCENE_DODONGOS_CAVERN, { //Events - EVENT_ACCESS(LOGIC_DC_MQ_STAIRS_SILVER_RUPEES, logic->HasItem(RG_CLIMB)), + EVENT_ACCESS(LOGIC_DODONGOS_CAVERN_MQ_SILVER, (logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->CanUse(RG_HOVER_BOOTS)) && + logic->HasItem(RG_CLIMB) && (logic->CanBreakCrates() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->IsChild))), }, { //Locations //Jump from vines can reach stairs without climb - LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), + LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_STAIRCASE, logic->CanStunDeku() && logic->HasItem(RG_SPEAK_DEKU) && GetCheckPrice() <= GetWalletCapacity()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_UPPER_CRATE_1, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_UPPER_CRATE_2, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_UPPER_CRATE_3, logic->CanBreakCrates()), LOCATION(RC_DODONGOS_CAVERN_MQ_STAIRCASE_UPPER_CRATE_4, logic->CanBreakCrates()), + LOCATION(RC_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER, logic->CanBreakCrates() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && (logic->IsChild || logic->CanUse(RG_HOOKSHOT)))), + // possible with the hookshot method and longshot, but precise and would be it's own trick + LOCATION(RC_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER, logic->CanBreakCrates() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->IsChild)), }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, true), ENTRANCE(RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_BIG_SKULLTULAS, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->CanUse(RG_HOVER_BOOTS)), }); - areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_BIG_SKULLTULAS] = Region("Dodongos Cavern MQ Past Big Skulltulas", SCENE_DODONGOS_CAVERN, {}, {}, { + areaTable[RR_DODONGOS_CAVERN_MQ_STAIRS_PAST_BIG_SKULLTULAS] = Region("Dodongos Cavern MQ Past Big Skulltulas", SCENE_DODONGOS_CAVERN, {}, { + //Locations + LOCATION(RC_DODONGOS_CAVERN_MQ_VINES_SILVER, logic->HasItem(RG_CLIMB)), + }, { //Exits ENTRANCE(RR_DODONGOS_CAVERN_MQ_STAIRS_UPPER, logic->CanPassEnemy(RE_BIG_SKULLTULA) || logic->CanUse(RG_HOVER_BOOTS)), ENTRANCE(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, logic->TakeDamage()), - ENTRANCE(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, logic->Get(LOGIC_DC_MQ_STAIRS_SILVER_RUPEES)), + ENTRANCE(RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM, logic->HasItem(RG_DODONGOS_CAVERN_MQ_SILVER)), }); areaTable[RR_DODONGOS_CAVERN_MQ_DODONGO_ROOM] = Region("Dodongos Cavern MQ Dodongo Room", SCENE_DODONGOS_CAVERN, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp index 8fa1c73ef9..bc87ba430a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ganons_castle.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/randomizer/location_access.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" using namespace Rando; @@ -72,23 +73,36 @@ void RegionTable_Init_GanonsCastle() { }); areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM] = Region("Ganon's Castle Forest Trial Beamos Room", SCENE_INSIDE_GANONS_CASTLE, { - EVENT_ACCESS(LOGIC_FOREST_TRIAL_SILVER_RUPEES, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || (logic->IsChild && ctx->GetTrickOption(RT_VOIDOUT_COLLECTION))), // child can get these by voiding after switch - }, {}, { + EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_FOREST, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || (logic->IsChild && ctx->GetTrickOption(RT_VOIDOUT_COLLECTION))), // child can get these by voiding after switch + }, { + //Locations + LOCATION(RC_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER, true), + //Assumes RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_END access + LOCATION(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, (bool)ctx->GetTrickOption(RT_VOIDOUT_COLLECTION)), + }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_WOLFOS_ROOM, true), - ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_END, true), + ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_WOLFOS_ROOM, true), + ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_MIDDLE, true), }); - areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_END] = Region("Ganon's Castle Forest Trial Beamos Room End", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { + areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_MIDDLE] = Region("Ganon's Castle Forest Trial Beamos Room Middle", SCENE_INSIDE_GANONS_CASTLE, {}, { + //Locations + LOCATION(RC_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER, true), + LOCATION(RC_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER, true), + LOCATION(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || (logic->IsChild && ctx->GetTrickOption(RT_VOIDOUT_COLLECTION))), + }, { //Exits ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM, logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_FINAL_DOOR, logic->IsAdult || logic->CanGroundJump() || ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)), }); - areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_FINAL_DOOR] = Region("Ganon's Castle Forest Trial Beamos Room Final Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { + areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_FINAL_DOOR] = Region("Ganon's Castle Forest Trial Beamos Room Final Door", SCENE_INSIDE_GANONS_CASTLE, {}, { + //Locations + LOCATION(RC_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER, true), + }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_END, true), - ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_FINAL_ROOM, logic->Get(LOGIC_FOREST_TRIAL_SILVER_RUPEES)), + ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_MIDDLE, true), + ENTRANCE(RR_GANONS_CASTLE_FOREST_TRIAL_FINAL_ROOM, logic->HasItem(RG_GANONS_CASTLE_SILVER_FOREST)), }); areaTable[RR_GANONS_CASTLE_FOREST_TRIAL_FINAL_ROOM] = Region("Ganon's Castle Forest Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { @@ -110,10 +124,15 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_FIRE_TRIAL_FROM_OPEN] = Region("Ganon's Castle Fire Trial From Open Door", SCENE_INSIDE_GANONS_CASTLE, { // backwalking hoverboots with backflip reaches silver rupee without needing str3 - EVENT_ACCESS(LOGIC_FIRE_TRIAL_SILVER_RUPEES, logic->FireTimer() >= 48 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), + EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_FIRE, logic->FireTimer() >= 48 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { //Locations - LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER, logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER, logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, logic->FireTimer() >= 32 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), + LOCATION(RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER, logic->FireTimer() >= 8), + LOCATION(RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER, logic->FireTimer() >= 24 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_FIRE_TRIAL_OPEN_DOOR, true), @@ -122,10 +141,15 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_FIRE_TRIAL_FROM_BARRED] = Region("Ganon's Castle Fire Trial From Barred Door", SCENE_INSIDE_GANONS_CASTLE, { // backwalking hoverboots with backflip reaches silver rupee without needing str3 - EVENT_ACCESS(LOGIC_FIRE_TRIAL_SILVER_RUPEES, logic->FireTimer() >= 56 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), + EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_FIRE, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 56 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { //Locations - LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_FIRE_TRIAL_HEART, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 8), + LOCATION(RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 32 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), + LOCATION(RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 16), + LOCATION(RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 24 && logic->CanUse(RG_GOLDEN_GAUNTLETS)), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_FIRE_TRIAL_OPEN_DOOR, logic->CanUse(RG_LONGSHOT) && logic->FireTimer() >= 24), @@ -134,7 +158,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_FIRE_TRIAL_BARRED_DOOR] = Region("Ganon's Castle Fire Trial Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { //Exits - ENTRANCE(RR_GANONS_CASTLE_FIRE_TRIAL_FINAL_ROOM, logic->Get(LOGIC_FIRE_TRIAL_SILVER_RUPEES)), + ENTRANCE(RR_GANONS_CASTLE_FIRE_TRIAL_FINAL_ROOM, logic->HasItem(RG_GANONS_CASTLE_SILVER_FIRE)), }); areaTable[RR_GANONS_CASTLE_FIRE_TRIAL_FINAL_ROOM] = Region("Ganon's Castle Fire Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { @@ -298,14 +322,21 @@ void RegionTable_Init_GanonsCastle() { ENTRANCE(RR_GANONS_CASTLE_SHADOW_TRIAL_END, true), }); - areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL_BEAMOS_ROOM] = Region("Ganon's Castle Spirit Trial Beamos Room", SCENE_INSIDE_GANONS_CASTLE, {}, { + areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL_BEAMOS_ROOM] = Region("Ganon's Castle Spirit Trial Beamos Room", SCENE_INSIDE_GANONS_CASTLE, { + EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_SPIRIT, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslash() && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOOKSHOT)), + }, { //Locations - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), - LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_HEART, true), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)), + LOCATION(RC_GANONS_CASTLE_SPIRIT_TRIAL_HEART, true), + LOCATION(RC_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER, (ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) && logic->CanJumpslash() && logic->HasItem(RG_POWER_BRACELET)) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER, true), + LOCATION(RC_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER, true), + LOCATION(RC_GANONS_CASTLE_CORNER_SPIRIT_SILVER, true), + LOCATION(RC_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER, true), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_MAIN, true), - ENTRANCE(RR_GANONS_CASTLE_SPIRIT_TRIAL_BEFORE_SWITCH, ctx->GetTrickOption(RT_GANON_SPIRIT_TRIAL_HOOKSHOT) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_GANONS_CASTLE_SPIRIT_TRIAL_BEFORE_SWITCH, logic->HasItem(RG_GANONS_CASTLE_SILVER_SPIRIT)), }); areaTable[RR_GANONS_CASTLE_SPIRIT_TRIAL_BEFORE_SWITCH] = Region("Ganon's Castle Spirit Trial Before Switch", SCENE_INSIDE_GANONS_CASTLE, {}, { @@ -364,13 +395,21 @@ void RegionTable_Init_GanonsCastle() { ENTRANCE(RR_GANONS_CASTLE_LIGHT_TRIAL_BOULDER_ROOM, logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2)), }); - areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL_BOULDER_ROOM] = Region("Ganon's Castle Light Trial Boulder Room", SCENE_INSIDE_GANONS_CASTLE, {}, { + areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL_BOULDER_ROOM] = Region("Ganon's Castle Light Trial Boulder Room", SCENE_INSIDE_GANONS_CASTLE, { + //Events + EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_LIGHT, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())), + }, { //Locations LOCATION(RC_GANONS_CASTLE_LIGHT_TRIAL_BOULDER_POT_1, logic->CanBreakPots()), + LOCATION(RC_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER, true), + LOCATION(RC_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER, true), + LOCATION(RC_GANONS_CASTLE_UPPER_LIGHT_SILVER, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())), + LOCATION(RC_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER, true), + LOCATION(RC_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER, true), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_LIGHT_TRIAL_TRIFORCE_ROOM, logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 2)), - ENTRANCE(RR_GANONS_CASTLE_LIGHT_TRIAL_FINAL_ROOM, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanGroundJump())), + ENTRANCE(RR_GANONS_CASTLE_LIGHT_TRIAL_FINAL_ROOM, logic->HasItem(RG_GANONS_CASTLE_SILVER_LIGHT)), }); areaTable[RR_GANONS_CASTLE_LIGHT_TRIAL_FINAL_ROOM] = Region("Ganon's Castle Light Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { @@ -494,15 +533,22 @@ void RegionTable_Init_GanonsCastle() { ENTRANCE(RR_GANONS_CASTLE_MQ_FOREST_TRIAL_BEAMOS_ROOM_END, true), }); - areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR] = Region("Ganon's Castle MQ Fire Trial Open Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { + areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR] = Region("Ganon's Castle MQ Fire Trial Open Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true), + ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true), }); areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FROM_OPEN] = Region("Ganon's Castle MQ Fire Trial From Open Door", SCENE_INSIDE_GANONS_CASTLE, { //Events - EVENT_ACCESS(LOGIC_FIRE_TRIAL_SILVER_RUPEES, logic->FireTimer() >= 72 && logic->CanUse(RG_GOLDEN_GAUNTLETS);), - }, {}, { + EVENT_ACCESS(LOGIC_GANONS_CASTLE_SILVER_FIRE, logic->FireTimer() >= 80 && (logic->CanUse(RG_GOLDEN_GAUNTLETS) || ctx->GetTrickOption(RT_VOIDOUT_COLLECTION));), + }, { + //Locations + LOCATION(RC_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER, logic->FireTimer() >= 24), + LOCATION(RC_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER, logic->FireTimer() >= 32), + LOCATION(RC_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER, (logic->FireTimer() >= 48 && logic->CanUse(RG_GOLDEN_GAUNTLETS)) || (logic->FireTimer() >= 32 && ctx->GetTrickOption(RT_VOIDOUT_COLLECTION))), + LOCATION(RC_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER, logic->FireTimer() >= 16), + LOCATION(RC_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER, logic->FireTimer() >= 40), + }, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_OPEN_DOOR, true), ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR, logic->FireTimer() >= 32 && (logic->CanUse(RG_LONGSHOT) || @@ -516,7 +562,7 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_BARRED_DOOR] = Region("Ganon's Castle MQ Fire Trial Barred Door", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FINAL_ROOM, logic->Get(LOGIC_FIRE_TRIAL_SILVER_RUPEES)), + ENTRANCE(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FINAL_ROOM, logic->HasItem(RG_GANONS_CASTLE_SILVER_FIRE)), }); areaTable[RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Fire Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { @@ -568,23 +614,37 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM] = Region("Ganon's Castle MQ Water Trial Block Room", SCENE_INSIDE_GANONS_CASTLE, { //Events - EVENT_ACCESS(LOGIC_WATER_TRIAL_MQ_SILVER_RUPEES, logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || logic->CanMiddairGroundJump()) && logic->BlueFire()), + EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_WATER, logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || logic->CanMiddairGroundJump()) && (logic->BlueFire() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash()))), EVENT_ACCESS(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE, (ctx->GetOption(RSK_BLUE_FIRE_ARROWS) && logic->CanUse(RG_ICE_ARROWS)) || ((logic->IsAdult || logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && logic->CanUse(RG_ROLL)*/)) && logic->HasItem(RG_POWER_BRACELET) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE))), }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SILVER_RUPEE_RED_ICE, logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || logic->CanMiddairGroundJump()) && logic->BlueFire()), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_1, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_2, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_3, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_4, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_5, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER, true), + LOCATION(RC_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER, logic->IsAdult || logic->CanUse(RG_POWER_BRACELET) || (/*CanUse(RG_ROLL) && */ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS))), + LOCATION(RC_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER, true), + LOCATION(RC_GANONS_CASTLE_MQ_NOOK_WATER_SILVER, true), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3)), - ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && (logic->IsAdult || ((logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && logic->CanUse(RG_ROLL)*/)) && logic->HasItem(RG_POWER_BRACELET)) || logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP))), + ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM, logic->SmallKeys(SCENE_INSIDE_GANONS_CASTLE, 3)), + ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_HIGH, logic->IsAdult && (logic->HasItem(RG_POWER_BRACELET) || logic->CanMiddairGroundJump())), + ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) && (logic->IsAdult || ((logic->CanUse(RG_HOVER_BOOTS) || (ctx->GetTrickOption(RT_UNINTUITIVE_JUMPS)/* && logic->CanUse(RG_ROLL)*/)) && logic->HasItem(RG_POWER_BRACELET)) || logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP))), + }); + + areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_HIGH] = Region("Ganon's Castle MQ Water Trial Block Room High", SCENE_INSIDE_GANONS_CASTLE, {}, { + //Locations + LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SILVER_RUPEE_RED_ICE, logic->BlueFire()), + LOCATION(RC_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER, (logic->BlueFire() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash()))), + }, { + //Exits + ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM, true), }); areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END] = Region("Ganon's Castle MQ Water Trial Block Room End", SCENE_INSIDE_GANONS_CASTLE, { + //Events EVENT_ACCESS(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE, logic->BlueFire()), }, { //Locations @@ -594,8 +654,9 @@ void RegionTable_Init_GanonsCastle() { LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_4, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE)), LOCATION(RC_GANONS_CASTLE_MQ_WATER_TRIAL_SECOND_DOOR_RED_ICE_5, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE)), }, { + //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM, logic->Get(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE)), - ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_FINAL_ROOM, logic->Get(LOGIC_WATER_TRIAL_MQ_SILVER_RUPEES)), + ENTRANCE(RR_GANONS_CASTLE_MQ_WATER_TRIAL_FINAL_ROOM, logic->HasItem(RG_GANONS_CASTLE_MQ_SILVER_WATER)), }); areaTable[RR_GANONS_CASTLE_MQ_WATER_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Water Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { @@ -613,6 +674,9 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE] = Region("Ganon's Castle MQ Shadow Trial Starting Ledge", SCENE_INSIDE_GANONS_CASTLE, { //Events EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanUse(RG_FAIRY_BOW)), + EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && + (logic->IsAdult && ctx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL) && logic->CanUse(RG_FAIRY_BOW)) && + (logic->Get(LOGIC_SHADOW_TRIAL_FIRST_CHEST) && logic->CanUse(RG_HOOKSHOT)) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS))), }, {}, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_MAIN, true), @@ -634,10 +698,14 @@ void RegionTable_Init_GanonsCastle() { areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM] = Region("Ganon's Castle MQ Shadow Trial Moving Platform", SCENE_INSIDE_GANONS_CASTLE, { //Events //A torch run from RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE is possible but tight, so would be a trick - EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanDetonateUprightBombFlower()), + EVENT_ACCESS(LOGIC_SHADOW_TRIAL_FIRST_CHEST, logic->CanDetonateUprightBombFlower()), + EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && + (logic->HasFireSource() || logic->CanUse(RG_HOVER_BOOTS))), }, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_WONDER_SHADOW_TRIAL, (logic->CanDetonateBombFlowers() || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE))) && (logic->TakeDamage() || logic->CanUse(RG_NAYRUS_LOVE))), + LOCATION(RC_GANONS_CASTLE_MQ_WONDER_SHADOW_TRIAL, (logic->CanDetonateBombFlowers() || (ctx->GetTrickOption(RT_BLUE_FIRE_MUD_WALLS) && logic->CanUse(RG_BOTTLE_WITH_BLUE_FIRE))) && (logic->TakeDamage() || logic->CanUse(RG_NAYRUS_LOVE))), + LOCATION(RC_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER, true), + LOCATION(RC_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER, true), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM, logic->IsAdult || logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS)), @@ -645,29 +713,43 @@ void RegionTable_Init_GanonsCastle() { }); - areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH] = Region("Ganon's Castle MQ Shadow Trial Beamos Torch", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH] = Region("Ganon's Castle MQ Shadow Trial Beamos Torch", SCENE_INSIDE_GANONS_CASTLE, {}, { + //Locations + LOCATION(RC_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER, true), + }, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), //A torch run from RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE is possible but very tight, so would be a trick //The bow trick assumes RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE access, if you can somehow void warp directly here it will need handling properly //Hovers is possible as child but a bit tight, requires good rolls - ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_SIDE, logic->HasFireSource() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL) && logic->CanUse(RG_FAIRY_BOW))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, logic->HasFireSource() || logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_GANON_MQ_SHADOW_TRIAL) && logic->CanUse(RG_FAIRY_BOW))), }); - areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_SIDE] = Region("Ganon's Castle MQ Shadow Trial Far Side", SCENE_INSIDE_GANONS_CASTLE, {}, { + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST] = Region("Ganon's Castle MQ Shadow Trial Beamos Chest", SCENE_INSIDE_GANONS_CASTLE, {}, { //Locations - LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_EYE_SWITCH_CHEST, logic->CanHitEyeTargets() && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER, ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || + logic->CanUse(RG_HOVER_BOOTS)), }, { //Exits ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS)), - //Modelling the silver rupees properly will require a way to check temp flags in different regions. - //It may be tempting to use a Here-like command for this but it could cause sphere skipping in playthroughs - //So a system like event access which sets based on TimeAge would be preferable, as the application of these can be tracked and accounted for, unlike Here-like commands - //For Now I am assuming the player has made it all the way from RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE, which logically means every rupee is available - //with no extra requirements except the lens logic needed to reach the door, which also enables the beamos-platform rupee ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), }); + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BARRED_DOOR] = Region("Ganon's Castle MQ Shadow Trial Barred Door", SCENE_INSIDE_GANONS_CASTLE, { + //Events + EVENT_ACCESS(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && + logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_HOVER_BOOTS)), + }, { + //Locations + LOCATION(RC_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) || + (ctx->GetTrickOption(RT_VOIDOUT_COLLECTION) && logic->CanUse(RG_HOVER_BOOTS))), + }, { + //Exits + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM, logic->HasItem(RG_GANONS_CASTLE_MQ_SILVER_SHADOW)), + }); + areaTable[RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM] = Region("Ganon's Castle MQ Shadow Trial Final Room", SCENE_INSIDE_GANONS_CASTLE, { //Events EVENT_ACCESS(LOGIC_SHADOW_TRIAL_CLEAR, logic->CanUse(RG_LIGHT_ARROWS)), @@ -677,7 +759,7 @@ void RegionTable_Init_GanonsCastle() { LOCATION(RC_GANONS_CASTLE_MQ_SHADOW_TRIAL_POT_2, logic->CanBreakPots()), }, { //Exits - ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_SIDE, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), + ENTRANCE(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BARRED_DOOR, (ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH))), }); areaTable[RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM] = Region("Ganon's Castle MQ Spirit Trial Chairs Room", SCENE_INSIDE_GANONS_CASTLE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp index 37becd5ff9..178caf5089 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/gerudo_training_ground.cpp @@ -38,9 +38,20 @@ void RegionTable_Init_GerudoTrainingGround() { ENTRANCE(RR_GERUDO_TRAINING_GROUND_BOULDER_ROOM, AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2, true);})), }); - areaTable[RR_GERUDO_TRAINING_GROUND_BOULDER_ROOM] = Region("Gerudo Training Ground Boulder Room", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { + areaTable[RR_GERUDO_TRAINING_GROUND_BOULDER_ROOM] = Region("Gerudo Training Ground Boulder Room", SCENE_GERUDO_TRAINING_GROUND, { + //Events + EVENT_ACCESS(LOGIC_GTG_SILVER_SLOPE, logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT) || ctx->GetTrickOption(RT_GTG_WITHOUT_HOOKSHOT)), + }, { + //Locations + LOCATION(RC_GTG_FIRE_WALL_SLOPE_SILVER, true), + LOCATION(RC_GTG_LOWER_BOULDER_SLOPE_SILVER, true), + LOCATION(RC_GTG_TARGET_SLOPE_SILVER, logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT) || ctx->GetTrickOption(RT_GTG_WITHOUT_HOOKSHOT)), + LOCATION(RC_GTG_JUMPDOWN_SLOPE_SILVER, true), + LOCATION(RC_GTG_UPPER_BOULDER_SLOPE_SILVER, true), + }, { + //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_SAND_ROOM, true), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM, AnyAgeTime([]{return logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT) || ctx->GetTrickOption(RT_GTG_WITHOUT_HOOKSHOT);})), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_HEAVY_BLOCK_ROOM, logic->HasItem(RG_GTG_SILVER_SLOPE)), }); areaTable[RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE] = Region("Gerudo Training Ground Central Maze", SCENE_GERUDO_TRAINING_GROUND, {}, { @@ -61,6 +72,7 @@ void RegionTable_Init_GerudoTrainingGround() { LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_FREESTANDING_KEY, true), + LOCATION(RC_GTG_UNDER_LEDGE_LAVA_SILVER, true), }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, true), @@ -148,24 +160,43 @@ void RegionTable_Init_GerudoTrainingGround() { }); areaTable[RR_GERUDO_TRAINING_GROUND_LAVA_ROOM] = Region("Gerudo Training Ground Lava Room", SCENE_GERUDO_TRAINING_GROUND, { - EVENT_ACCESS(LOGIC_GTG_PLATFORM_SILVER_RUPEES, logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild)), - }, {}, { + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild)), + }, { + //Locations + LOCATION(RC_GTG_NEAR_SWITCH_LAVA_SILVER, true), + LOCATION(RC_GTG_NEAR_BARRED_DOOR_LAVA_SILVER, true), + LOCATION(RC_GTG_FIRE_RING_LAVA_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + LOCATION(RC_GTG_UNDER_LEDGE_LAVA_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), + }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_DINALFOS, true), ENTRANCE(RR_GERUDO_TRAINING_GROUND_CENTRAL_MAZE_RIGHT, logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild), ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM_UPPER_LEDGE, logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage())))), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_UNDERWATER, logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES)), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_UNDERWATER, logic->HasItem(RG_GTG_SILVER_LAVA)), }); - areaTable[RR_GERUDO_TRAINING_GROUND_LAVA_ROOM_UPPER_LEDGE] = Region("Gerudo Training Ground Lava Room", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { + areaTable[RR_GERUDO_TRAINING_GROUND_LAVA_ROOM_UPPER_LEDGE] = Region("Gerudo Training Ground Lava Room", SCENE_GERUDO_TRAINING_GROUND, {}, { + //Locations + LOCATION(RC_GTG_UPPER_LAVA_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_GTG_UNDER_LEDGE_LAVA_SILVER, true), + }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_SONG_OF_TIME) || logic->IsChild || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage())), ENTRANCE(RR_GERUDO_TRAINING_GROUND_HAMMER_ROOM, true), }); - areaTable[RR_GERUDO_TRAINING_GROUND_UNDERWATER] = Region("Gerudo Training Ground Underwater", SCENE_GERUDO_TRAINING_GROUND, {}, { + areaTable[RR_GERUDO_TRAINING_GROUND_UNDERWATER] = Region("Gerudo Training Ground Underwater", SCENE_GERUDO_TRAINING_GROUND, { + //Events + EVENT_ACCESS(LOGIC_GTG_SILVER_WATER, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 24), + }, { //Locations - LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->HasItem(RG_BRONZE_SCALE) && logic->WaterTimer() >= 24 && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_UNDERWATER_SILVER_RUPEE_CHEST, logic->HasItem(RG_GTG_SILVER_WATER) && logic->HasItem(RG_OPEN_CHEST)), + // 3 & 5 can be retrieved with only iron boots by attempting to backflip underwater + LOCATION(RC_GTG_MIDDLE_WATER_SILVER, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16), + LOCATION(RC_GTG_ABOVE_TARGET_WATER_SILVER, logic->CanUse(RG_SONG_OF_TIME) && ((logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16) || logic->HasItem(RG_GOLDEN_SCALE))), + LOCATION(RC_GTG_LEFT_WATER_SILVER, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16), + LOCATION(RC_GTG_UNDER_TARGET_WATER_SILVER, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && (logic->HasItem(RG_BRONZE_SCALE) || logic->CanUse(RG_HOOKSHOT)) && logic->WaterTimer() >= 16), + LOCATION(RC_GTG_RIGHT_WATER_SILVER, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 16), }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_LAVA_ROOM, true), @@ -245,7 +276,10 @@ void RegionTable_Init_GerudoTrainingGround() { ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM, AnyAgeTime([]{return logic->CanKillEnemy(RE_IRON_KNUCKLE);})), }); - areaTable[RR_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM] = Region("Gerudo Training Ground MQ Left Side", SCENE_GERUDO_TRAINING_GROUND, {}, { + areaTable[RR_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM] = Region("Gerudo Training Ground MQ Left Side", SCENE_GERUDO_TRAINING_GROUND, { + //Events + EVENT_ACCESS(LOGIC_GTG_SILVER_SLOPE, logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_GTG_MQ_WITHOUT_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_MQ_WITH_HOOKSHOT) && logic->IsAdult && logic->CanJumpslash() && logic->CanUse(RG_HOOKSHOT))), + }, { //Locations LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM_STALAGMITE_1, logic->CanClearStalagmite()), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM_STALAGMITE_2, logic->CanClearStalagmite()), @@ -260,10 +294,15 @@ void RegionTable_Init_GerudoTrainingGround() { LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM_TOP_RIGHT_STALACTITE_1, true), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM_TOP_RIGHT_STALACTITE_2, true), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_BOULDER_ROOM_TOP_RIGHT_STALACTITE_3, true), - }, { + LOCATION(RC_GTG_MQ_ICICLES_SLOPE_SILVER, true), + LOCATION(RC_GTG_MQ_JUMPDOWN_SLOPE_SILVER, true), + LOCATION(RC_GTG_MQ_HIGH_SLOPE_SILVER, logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_GTG_MQ_WITHOUT_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_MQ_WITH_HOOKSHOT) && logic->IsAdult && logic->CanJumpslash() && logic->CanUse(RG_HOOKSHOT))), + LOCATION(RC_GTG_MQ_FREEZARD_SLOPE_SILVER, true), + LOCATION(RC_GTG_MQ_PIT_SLOPE_SILVER, true), + }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_SAND_ROOM, true), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM, AnyAgeTime([]{return logic->CanUse(RG_LONGSHOT) || ctx->GetTrickOption(RT_GTG_MQ_WITHOUT_HOOKSHOT) || (ctx->GetTrickOption(RT_GTG_MQ_WITH_HOOKSHOT) && logic->IsAdult && logic->CanJumpslash() && logic->CanUse(RG_HOOKSHOT));})), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM, logic->HasItem(RG_GTG_SILVER_SLOPE)), }); areaTable[RR_GERUDO_TRAINING_GROUND_MQ_STALFOS_ROOM] = Region("Gerudo Training Ground MQ Stalfos Room", SCENE_GERUDO_TRAINING_GROUND, { @@ -344,30 +383,31 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_SWITCH_LEDGE] = Region("Gerudo Training Ground MQ Switch Ledge", SCENE_GERUDO_TRAINING_GROUND, { //Events - EVENT_ACCESS(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH, logic->CanUse(RG_MEGATON_HAMMER)), - EVENT_ACCESS(LOGIC_GTG_PLATFORM_SILVER_RUPEES, logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS)), + EVENT_ACCESS(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH, logic->CanUse(RG_MEGATON_HAMMER)), + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS)), }, {}, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->CanUse(RG_FIRE_ARROWS)), //the fire bubble here is a jerk if you are aiming for the nearest hook platform, you have to aim to the right hand side with hook to dodge it - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_LONGSHOT) || (logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES) && logic->CanUse(RG_HOOKSHOT)) || ((logic->CanUse(RG_FIRE_ARROWS) && logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES)) && logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_LONGSHOT) || (logic->HasItem(RG_GTG_SILVER_LAVA) && logic->CanUse(RG_HOOKSHOT)) || (logic->CanUse(RG_FIRE_ARROWS) && logic->HasItem(RG_GTG_SILVER_LAVA) && logic->CanUse(RG_HOVER_BOOTS))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_LONGSHOT)), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SLUG_ROOM, true), }); - //this region exists to place silver rupee items on later, normally it's all on fire and cannot be stood on without access from another area - //This covers the 2 platforms that can be jumped to directly from RR_GERUDO_TRAINING_GROUND_MQ_SWITCH_LEDGE - //the unshuffled rupee collection is handled by the event GTGPlatformSilverRupees - areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS] = Region("Gerudo Training Ground MQ Ledge Side Platforms", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { + //This covers the 2 platforms that can be jumped to directly from RR_GERUDO_TRAINING_GROUND_MQ_SWITCH_LEDGE, without flame circles + areaTable[RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS] = Region("Gerudo Training Ground MQ Ledge Side Platforms", SCENE_GERUDO_TRAINING_GROUND, {}, { + LOCATION(RC_GTG_MQ_NEAR_SWITCH_LAVA_SILVER, true), + LOCATION(RC_GTG_MQ_MIDDLE_LAVA_SILVER, true), + }, { //Exits //This is merely to extend this region's logic if you have hovers ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)), }); - //this region exists to place silver rupee items on later, normally it's all on fire and cannot be stood on without access from another area - //This covers the platform that needs hover boots or the spawned targets to reach from any starting point other than RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT - //the unshuffled rupee collection is handled by the event GTGPlatformSilverRupees - areaTable[RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM] = Region("Gerudo Training Ground MQ Furthest Platform", SCENE_GERUDO_TRAINING_GROUND, {}, {}, { + //This covers the platform that needs hover boots or the spawned targets to reach from any starting point other than RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, without flame circles + areaTable[RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM] = Region("Gerudo Training Ground MQ Furthest Platform", SCENE_GERUDO_TRAINING_GROUND, {}, { + LOCATION(RC_GTG_MQ_FAR_LAVA_SILVER, true), + }, { //Exits //This is merely to extend this region's logic if you have hovers ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->CanUse(RG_HOVER_BOOTS)), @@ -375,10 +415,14 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH] = Region("Gerudo Training Ground MQ Platforms Unlit Torch", SCENE_GERUDO_TRAINING_GROUND, { //Events - EVENT_ACCESS(LOGIC_GTG_PLATFORM_SILVER_RUPEES, logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS)), - }, {}, { + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS)), + }, { + LOCATION(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, logic->HasFireSource()), + LOCATION(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, logic->HasFireSource()), + LOCATION(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, logic->HasFireSource()), + }, { //Exits - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER, logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES)), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER, logic->HasItem(RG_GTG_SILVER_LAVA)), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->HasFireSource() && logic->CanUse(RG_HOVER_BOOTS)), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, logic->HasFireSource() || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT, logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && (logic->CanUse(RG_LONGSHOT) || (logic->CanUse(RG_HOOKSHOT) && logic->HasFireSource()))), @@ -387,8 +431,13 @@ void RegionTable_Init_GerudoTrainingGround() { areaTable[RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS] = Region("Gerudo Training Ground MQ Torch Side Platforms", SCENE_GERUDO_TRAINING_GROUND, { //Events //this torch shot is possible as child but tight and obtuse enough to be a trick - EVENT_ACCESS(LOGIC_GTG_PLATFORM_SILVER_RUPEES, ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && logic->CanUse(RG_HOVER_BOOTS)), - }, {}, { + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && logic->CanUse(RG_HOVER_BOOTS)), + }, { + //Locations + LOCATION(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)), + LOCATION(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)), + LOCATION(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)), + }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, ((logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS)) && (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && ctx->GetTrickOption(RT_GTG_LAVA_JUMP)) || (ctx->GetTrickOption(RT_DAMAGE_BOOST_SIMPLE) && logic->CanUse(RG_BOMB_BAG) && logic->TakeDamage()))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, (logic->CanUse(RG_FAIRY_BOW) && logic->IsAdult) || logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), @@ -396,28 +445,35 @@ void RegionTable_Init_GerudoTrainingGround() { ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_DINOLFOS_ROOM, true), }); - areaTable[RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER] = Region("Gerudo Training Ground MQ Underwater", SCENE_GERUDO_TRAINING_GROUND, {}, { + areaTable[RR_GERUDO_TRAINING_GROUND_MQ_UNDERWATER] = Region("Gerudo Training Ground MQ Underwater", SCENE_GERUDO_TRAINING_GROUND, { + EVENT_ACCESS(LOGIC_GTG_SILVER_WATER, logic->HasFireSource() && logic->HasItem(RG_BRONZE_SCALE) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->TakeDamage()), + }, { //Locations //it is possible to snipe the stingers with bow or sling before dropping in, or just get really lucky, and avoid needing to take damage, but that might be trick worthy - LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, (logic->HasFireSource() && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->HasItem(RG_BRONZE_SCALE) && logic->TakeDamage()) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_UNDERWATER_SILVER_RUPEE_CHEST, logic->HasItem(RG_GTG_SILVER_WATER) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GTG_MQ_BACK_WATER_SILVER, logic->HasFireSource() && logic->HasItem(RG_BRONZE_SCALE) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->TakeDamage()), + LOCATION(RC_GTG_MQ_MIDDLE_WATER_SILVER, logic->HasFireSource() && logic->HasItem(RG_BRONZE_SCALE) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->TakeDamage()), + LOCATION(RC_GTG_MQ_FRONT_WATER_SILVER, logic->HasFireSource() && logic->HasItem(RG_BRONZE_SCALE) && logic->CanUse(RG_IRON_BOOTS) && logic->WaterTimer() >= 24 && logic->TakeDamage()), }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, true), }); - areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT] = Region("Gerudo Training Ground MQ Maze Right", SCENE_GERUDO_TRAINING_GROUND, { //Events - EVENT_ACCESS(LOGIC_GTG_PLATFORM_SILVER_RUPEES, logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS)), + EVENT_ACCESS(LOGIC_GTG_SILVER_LAVA, logic->CanUse(RG_FIRE_ARROWS) && logic->CanUse(RG_HOVER_BOOTS)), }, { //Locations LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_CENTRAL_CHEST, logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_GERUDO_TRAINING_GROUND_MQ_MAZE_RIGHT_SIDE_CHEST, logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER, logic->CanUse(RG_FIRE_ARROWS)), + LOCATION(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER, logic->CanUse(RG_FIRE_ARROWS)), + LOCATION(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER, logic->CanUse(RG_FIRE_ARROWS)), }, { //Exits ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LOBBY, true), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_TORCH_SIDE_PLATFORMS, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), - ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(logic->Get(LOGIC_GTG_PLATFORM_SILVER_RUPEES) ? RG_HOOKSHOT : RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), + ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_PLATFORMS_UNLIT_TORCH, logic->CanUse(RG_FIRE_ARROWS) || logic->CanUse(logic->HasItem(RG_GTG_SILVER_LAVA) ? RG_HOOKSHOT : RG_LONGSHOT) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->Get(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanUse(RG_MEGATON_HAMMER))), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_LEDGE_SIDE_PLATFORMS, logic->CanUse(RG_FIRE_ARROWS)), ENTRANCE(RR_GERUDO_TRAINING_GROUND_MQ_FURTHEST_PLATFORM, logic->CanUse(RG_FIRE_ARROWS)), }); diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp index e9725caaba..9d0a6b3189 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/ice_cavern.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/randomizer/location_access.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" using namespace Rando; @@ -39,7 +40,10 @@ void RegionTable_Init_IceCavern() { ENTRANCE(RR_ICE_CAVERN_ABOVE_BEGINNING, false), }); - areaTable[RR_ICE_CAVERN_HUB] = Region("Ice Cavern Hub", SCENE_ICE_CAVERN, {}, { + areaTable[RR_ICE_CAVERN_HUB] = Region("Ice Cavern Hub", SCENE_ICE_CAVERN, { + //Events + EVENT_ACCESS(LOGIC_ICE_CAVERN_SILVER_BLADES, (logic->IsAdult /*|| (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())*/) && logic->CanClearStalagmite()), + }, { //Locations LOCATION(RC_ICE_CAVERN_GS_SPINNING_SCYTHE_ROOM, logic->HookshotOrBoomerang()), LOCATION(RC_ICE_CAVERN_HALL_POT_1, logic->CanBreakPots()), @@ -57,11 +61,16 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_SPINNING_BLADE_RIGHT_STALAGMITE, logic->CanClearStalagmite()), LOCATION(RC_ICE_CAVERN_SPINNING_BLADE_EAST_RED_ICE, logic->BlueFire()), LOCATION(RC_ICE_CAVERN_SPINNING_BLADE_WEST_RED_ICE, logic->BlueFire()), + LOCATION(RC_ICE_CAVERN_ICICLES_BLADE_SILVER, logic->CanClearStalagmite()), + LOCATION(RC_ICE_CAVERN_W_INNER_BLADE_SILVER, true), + LOCATION(RC_ICE_CAVERN_OUTER_BLADE_SILVER, true), + LOCATION(RC_ICE_CAVERN_E_INNER_BLADE_SILVER, true), + LOCATION(RC_ICE_CAVERN_AIRBORNE_BLADE_SILVER, logic->IsAdult /*|| (ctx->GetTrickOption(RT_GROUND_JUMP_HARD) && logic->CanGroundJump())*/), }, { //Exits ENTRANCE(RR_ICE_CAVERN_BEGINNING, true), //child can make this with a ground jump for the first step, and a glitchless jump for the second, but it's a separate trick - ENTRANCE(RR_ICE_CAVERN_MAP_ROOM, (logic->IsAdult /*|| logic->CanGroundJump()*/) && logic->CanClearStalagmite()), + ENTRANCE(RR_ICE_CAVERN_MAP_ROOM, (logic->IsAdult /*|| logic->CanGroundJump()*/) && logic->HasItem(RG_ICE_CAVERN_SILVER_BLADES)), ENTRANCE(RR_ICE_CAVERN_COMPASS_ROOM, AnyAgeTime([]{return logic->BlueFire();})), ENTRANCE(RR_ICE_CAVERN_BLOCK_ROOM, AnyAgeTime([]{return logic->BlueFire();}) && (logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP))), }); @@ -144,22 +153,29 @@ void RegionTable_Init_IceCavern() { LOCATION(RC_ICE_CAVERN_PUSH_BLOCK_HALL_STALACTITE_1, true), LOCATION(RC_ICE_CAVERN_PUSH_BLOCK_HALL_STALACTITE_2, true), LOCATION(RC_ICE_CAVERN_PUSH_BLOCK_HALL_STALACTITE_3, true), - LOCATION(RC_ICE_CAVERN_SILVER_RUPEE_RED_ICE, (logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))) && logic->BlueFire()), + LOCATION(RC_ICE_CAVERN_LOWER_BLOCK_SILVER, true), + LOCATION(RC_ICE_CAVERN_NEAR_BLOCK_SILVER, logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)), + LOCATION(RC_ICE_CAVERN_NEAR_GS_BLOCK_SILVER, logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)), }, { //Exits - ENTRANCE(RR_ICE_CAVERN_HUB, logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)), - ENTRANCE(RR_ICE_CAVERN_BLOCK_ROOM_BLUE_FIRE, logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))), - ENTRANCE(RR_ICE_CAVERN_AFTER_BLOCK_ROOM, (logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))) && AnyAgeTime([]{return logic->BlueFire();})), + ENTRANCE(RR_ICE_CAVERN_HUB, logic->CanClearStalagmite() || ctx->GetTrickOption(RT_ICE_STALAGMITE_CLIP)), + ENTRANCE(RR_ICE_CAVERN_BLOCK_ROOM_NOOKS, logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))), + ENTRANCE(RR_ICE_CAVERN_AFTER_BLOCK_ROOM, (logic->HasItem(RG_POWER_BRACELET) || (logic->IsAdult && (logic->CanGroundJump() || ctx->GetTrickOption(RT_SLIDE_JUMP)))) && logic->HasItem(RG_ICE_CAVERN_SILVER_BLOCK)), }); - areaTable[RR_ICE_CAVERN_BLOCK_ROOM_BLUE_FIRE] = Region("Ice Cavern Block Room Blue Fire", SCENE_ICE_CAVERN, { + areaTable[RR_ICE_CAVERN_BLOCK_ROOM_NOOKS] = Region("Ice Cavern Block Room Nooks", SCENE_ICE_CAVERN, { //Events EVENT_ACCESS(LOGIC_BLUE_FIRE_ACCESS, true), + EVENT_ACCESS(LOGIC_ICE_CAVERN_SILVER_BLOCK, (logic->IsAdult || logic->HasItem(RG_POWER_BRACELET) || logic->CanUse(RG_HOVER_BOOTS)) && + (logic->BlueFire() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash()))), }, { //Locations - LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->CanUse(RG_SONG_OF_TIME)), - LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->CanUse(RG_SONG_OF_TIME)), - LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_1, logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_2, logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_ICE_CAVERN_SLIDING_BLOCK_RUPEE_3, logic->CanUse(RG_SONG_OF_TIME)), + LOCATION(RC_ICE_CAVERN_SILVER_RUPEE_RED_ICE, logic->BlueFire()), + LOCATION(RC_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER, true), + LOCATION(RC_ICE_CAVERN_FROZEN_BLOCK_SILVER, logic->BlueFire() || (ctx->GetTrickOption(RT_VISIBLE_COLLISION) && logic->CanJumpslash())), }, { //Exits ENTRANCE(RR_ICE_CAVERN_BLOCK_ROOM, true), diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp index ce7e5db948..d38c63cef0 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/shadow_temple.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/randomizer/location_access.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" using namespace Rando; @@ -103,9 +104,17 @@ void RegionTable_Init_ShadowTemple() { ENTRANCE(RR_SHADOW_TEMPLE_FIRST_BEAMOS, AnyAgeTime([]{return logic->CanKillEnemy(RE_GIBDO);})), }); - areaTable[RR_SHADOW_TEMPLE_SPINNING_BLADES] = Region("Shadow Temple Spinning Blades", SCENE_SHADOW_TEMPLE, {}, { + areaTable[RR_SHADOW_TEMPLE_SPINNING_BLADES] = Region("Shadow Temple Spinning Blades", SCENE_SHADOW_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_SILVER_BLADES, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), + }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, ((logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_EARLY_SILVER_RUPEE_CHEST, logic->HasItem(RG_SHADOW_SILVER_BLADES) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_N_UNDER_BLADE_SILVER, true), + LOCATION(RC_SHADOW_TALL_BLOCK_BLADE_SILVER, (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_N_NOOK_BLADE_SILVER, true), + LOCATION(RC_SHADOW_W_NOOK_BLADE_SILVER, true), + LOCATION(RC_SHADOW_S_UNDER_BLADE_SILVER, true), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_FIRST_BEAMOS, true), @@ -141,11 +150,21 @@ void RegionTable_Init_ShadowTemple() { ENTRANCE(RR_SHADOW_TEMPLE_INVISIBLE_SPINNING_BLADES, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2)), }); - areaTable[RR_SHADOW_TEMPLE_LOWER_HUGE_PIT] = Region("Shadow Temple Lower Huge Pit", SCENE_SHADOW_TEMPLE, {}, {},{ + areaTable[RR_SHADOW_TEMPLE_LOWER_HUGE_PIT] = Region("Shadow Temple Lower Huge Pit", SCENE_SHADOW_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_SILVER_PIT, true), + }, { + //Locations + LOCATION(RC_SHADOW_N_PIT_SILVER, true), + LOCATION(RC_SHADOW_S_PIT_SILVER, true), + LOCATION(RC_SHADOW_BEAMOS_PIT_SILVER, true), + LOCATION(RC_SHADOW_E_PIT_SILVER, true), + LOCATION(RC_SHADOW_W_PIT_SILVER, true), + },{ //Exits ENTRANCE(RR_SHADOW_TEMPLE_UPPER_HUGE_PIT, logic->IsAdult || logic->CanJumpslash()), ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT_DOOR_LEDGE, (ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)), - ENTRANCE(RR_SHADOW_TEMPLE_STONE_UMBRELLA, true), + ENTRANCE(RR_SHADOW_TEMPLE_STONE_UMBRELLA, logic->HasItem(RG_SHADOW_SILVER_PIT)), }); // See MQ for comments @@ -178,8 +197,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_LOWER_HUGE_PIT_DOOR_LEDGE] = Region("Shadow Temple Lower Huge Pit Door Ledge", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT, (ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)), - ENTRANCE(RR_SHADOW_TEMPLE_INVISIBLE_SPIKES, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2)), + ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT, (ctx->GetTrickOption(RT_LENS_SHADOW_PLATFORM) && ctx->GetTrickOption(RT_LENS_SHADOW)) || logic->CanUse(RG_LENS_OF_TRUTH)), + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_S_DOOR, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2)), }); areaTable[RR_SHADOW_TEMPLE_INVISIBLE_SPINNING_BLADES] = Region("Shadow Temple Invisible Spinning Blades", SCENE_SHADOW_TEMPLE, {}, { @@ -195,21 +214,61 @@ void RegionTable_Init_ShadowTemple() { ENTRANCE(RR_SHADOW_TEMPLE_UPPER_HUGE_PIT_DOOR_LEDGE, true), }); - areaTable[RR_SHADOW_TEMPLE_INVISIBLE_SPIKES] = Region("Shadow Temple Invisible Spikes", SCENE_SHADOW_TEMPLE, {}, { + areaTable[RR_SHADOW_TEMPLE_FLOOR_SPIKES_S_DOOR] = Region("Shadow Temple Floor Spikes South Door", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_E_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT_DOOR_LEDGE, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 2)), - ENTRANCE(RR_SHADOW_TEMPLE_SKULL_JAR, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanMiddairGroundJump()))), - ENTRANCE(RR_SHADOW_TEMPLE_INVISIBLE_SPIKES_PLATFORM, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && ((logic->IsAdult && logic->CanMiddairGroundJump()) || - logic->CanUse(AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->TakeDamage() || logic->CanUse(RG_GORON_TUNIC));}) ? RG_HOOKSHOT : RG_LONGSHOT))), + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), }); - areaTable[RR_SHADOW_TEMPLE_INVISIBLE_SPIKES_PLATFORM] = Region("Shadow Temple Invisible Spikes Platform", SCENE_SHADOW_TEMPLE, {}, {}, { + //Assumes logic for navigating around spikes is checked on entry + areaTable[RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM] = Region("Shadow Temple Floor Spikes Room", SCENE_SHADOW_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_SILVER_SPIKES, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT))), + }, { + //Locations + LOCATION(RC_SHADOW_TEMPLE_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_E_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_FLOOR_SPIKES_SILVER, true), + LOCATION(RC_SHADOW_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_INVISIBLE_SPIKES, true), - ENTRANCE(RR_SHADOW_TEMPLE_UPPER_WIND_TUNNEL, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_S_DOOR, true), + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_W_DOOR, true), + ENTRANCE(RR_SHADOW_TEMPLE_SPIKES_CORNER_PLATFORM, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->IsAdult && logic->CanMiddairGroundJump() || logic->CanUse(RG_HOOKSHOT))), + ENTRANCE(RR_SHADOW_TEMPLE_SPIKES_DOOR_PLATFORM, (ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && ((logic->IsAdult && logic->CanMiddairGroundJump()) || + (logic->CanUse(logic->IsAdult && AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);}) ? RG_HOOKSHOT : RG_LONGSHOT)))), + }); + + areaTable[RR_SHADOW_TEMPLE_FLOOR_SPIKES_W_DOOR] = Region("Shadow Temple Floor Spikes West Door", SCENE_SHADOW_TEMPLE, {}, { + //Locations + LOCATION(RC_SHADOW_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + }, { + //Exits + ENTRANCE(RR_SHADOW_TEMPLE_SKULL_JAR, logic->HasItem(RG_SHADOW_SILVER_SPIKES)), + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + }); + + areaTable[RR_SHADOW_TEMPLE_SPIKES_CORNER_PLATFORM] = Region("Shadow Temple Spikes Corner Platform", SCENE_SHADOW_TEMPLE, {}, { + //Locations + LOCATION(RC_SHADOW_PLATFORM_SPIKES_SILVER, true), + LOCATION(RC_SHADOW_AIRBORNE_SPIKES_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + }, { + //Exits + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + }); + + areaTable[RR_SHADOW_TEMPLE_SPIKES_DOOR_PLATFORM] = Region("Shadow Temple Spikes Door Platform", SCENE_SHADOW_TEMPLE, {}, { + //Locations + LOCATION(RC_SHADOW_AIRBORNE_SPIKES_SILVER, true), + }, { + //Exits + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + ENTRANCE(RR_SHADOW_TEMPLE_SPIKES_CORNER_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)/* && logic->CanUse(RG_ROLL)*/), + ENTRANCE(RR_SHADOW_TEMPLE_UPPER_WIND_TUNNEL, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), }); areaTable[RR_SHADOW_TEMPLE_SKULL_JAR] = Region("Shadow Temple Skull Jar", SCENE_SHADOW_TEMPLE, {}, { @@ -218,13 +277,13 @@ void RegionTable_Init_ShadowTemple() { LOCATION(RC_SHADOW_TEMPLE_GS_SINGLE_GIANT_POT, logic->CanKillEnemy(RE_GOLD_SKULLTULA)), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_INVISIBLE_SPIKES, AnyAgeTime([]{return logic->CanKillEnemy(RE_KEESE);})), + ENTRANCE(RR_SHADOW_TEMPLE_FLOOR_SPIKES_W_DOOR, AnyAgeTime([]{return logic->CanKillEnemy(RE_KEESE);})), }); areaTable[RR_SHADOW_TEMPLE_UPPER_WIND_TUNNEL] = Region("Shadow Temple Upper Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_INVISIBLE_SPIKES_PLATFORM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), - ENTRANCE(RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL, (logic->CanUse(RG_HOVER_BOOTS) && logic->CanPassEnemy(RE_BIG_SKULLTULA)) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SHADOW_TEMPLE_SPIKES_DOOR_PLATFORM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), + ENTRANCE(RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL, (logic->CanUse(RG_HOVER_BOOTS) && logic->CanPassEnemy(RE_BIG_SKULLTULA)) || logic->CanUse(RG_HOOKSHOT)), }); areaTable[RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL] = Region("Shadow Temple Lower Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { @@ -467,12 +526,20 @@ void RegionTable_Init_ShadowTemple() { ENTRANCE(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, AnyAgeTime([]{return logic->CanKillEnemy(RE_GIBDO);})), }); - areaTable[RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM] = Region("Shadow Temple MQ B2 Spinning Blade Room", SCENE_SHADOW_TEMPLE, {}, { + areaTable[RR_SHADOW_TEMPLE_MQ_B2_SPINNING_BLADE_ROOM] = Region("Shadow Temple MQ B2 Spinning Blade Room", SCENE_SHADOW_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_SILVER_BLADES, logic->CanKillEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump())))), + }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump()))) && logic->CanOpenLargeChest()), + LOCATION(RC_SHADOW_TEMPLE_MQ_MAP_CHEST, logic->CanPassEnemy(RE_BIG_SKULLTULA) && logic->HasItem(RG_SHADOW_SILVER_BLADES) && logic->CanOpenLargeChest()), + LOCATION(RC_SHADOW_MQ_W_NOOK_SILVER, logic->CanPassEnemy(RE_BIG_SKULLTULA)), + LOCATION(RC_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER, logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanGroundJump()))), + LOCATION(RC_SHADOW_MQ_NE_UNDER_BLADE_SILVER, true), + LOCATION(RC_SHADOW_MQ_S_UNDER_BLADE_SILVER, true), + LOCATION(RC_SHADOW_MQ_N_NOOK_BLADE_SILVER, logic->CanPassEnemy(RE_BIG_SKULLTULA)), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, AnyAgeTime([]{return logic->CanKillEnemy(RE_BIG_SKULLTULA) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));})), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FIRST_BEAMOS, logic->HasItem(RG_SHADOW_SILVER_BLADES)), ENTRANCE(RR_SHADOW_TEMPLE_MQ_SHORTCUT_PATH, logic->CanPassEnemy(RE_BIG_SKULLTULA)), }); @@ -516,26 +583,46 @@ void RegionTable_Init_ShadowTemple() { ENTRANCE(RR_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_ROOM, true), }); - areaTable[RR_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_ROOM] = Region("Shadow Temple MQ Invisible Blades Room", SCENE_SHADOW_TEMPLE, {}, { + areaTable[RR_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_ROOM] = Region("Shadow Temple MQ Invisible Blades Room", SCENE_SHADOW_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_MQ_SILVER_INVISIBLE_BLADES, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && + (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH))), + }, { //Locations //RT_SHADOW_MQ_INVISIBLE_BLADES does not work with NL as like-likes will not swallow you, likewise like-likes will not spit you with a fairy revive //you take half a heart base from a spit out, double check EffectiveHealth when damage logic gets reworked //Child is too small to get hit by the blades doesn't need the trick or lens for dodging them - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, (logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)) && - ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE))) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_VISIBLE_CHEST, logic->HasItem(RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_INVISIBLE_CHEST, logic->HasItem(RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_LEFT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_BLADES_RIGHT_HEART, (logic->CanUse(RG_SONG_OF_TIME) && logic->IsAdult) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1) || logic->CanUse(RG_BOOMERANG)), + LOCATION(RC_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER, ctx->GetTrickOption(RT_LENS_SHADOW_MQ_INVISIBLE_BLADES) || logic->IsChild || logic->CanUse(RG_NAYRUS_LOVE) || logic->CanUse(RG_LENS_OF_TRUTH)), + LOCATION(RC_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER, logic->CanUse(RG_SONG_OF_TIME) || (ctx->GetTrickOption(RT_SHADOW_MQ_INVISIBLE_BLADES) && logic->EffectiveHealth() > 1)), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_UPPER_HUGE_PIT, true), }); - areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Region("Shadow Temple MQ Lower Huge Pit", SCENE_SHADOW_TEMPLE, {}, { + areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT] = Region("Shadow Temple MQ Lower Huge Pit", SCENE_SHADOW_TEMPLE, { + //Events + EVENT_ACCESS(LOGIC_SHADOW_SILVER_PIT, logic->CanUse(RG_LONGSHOT)), + }, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_TEMPLE_MQ_BEAMOS_SILVER_RUPEES_CHEST, logic->HasItem(RG_SHADOW_SILVER_PIT) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SHADOW_TEMPLE_MQ_LOWER_PIT_RECTANGLE_SIGN, logic->CanRead()), + LOCATION(RC_SHADOW_MQ_W_PIT_SILVER, true), + LOCATION(RC_SHADOW_MQ_HIGH_PIT_SILVER, logic->HasItem(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_HIGHEST_PIT_SILVER, logic->HasItem(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_N_PIT_SILVER, true), + LOCATION(RC_SHADOW_MQ_E_PIT_SILVER, true), }, { //Exits ENTRANCE(RR_SHADOW_TEMPLE_MQ_B2_TO_B3_CORRIDOR_B3, logic->CanUse(RG_LONGSHOT)), @@ -545,8 +632,8 @@ void RegionTable_Init_ShadowTemple() { }); areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT_DOOR_LEDGE] = Region("Shadow Temple MQ Lower Huge Pit Door Ledge", SCENE_SHADOW_TEMPLE, {}, {}, { - ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM) || logic->CanUse(RG_LENS_OF_TRUTH)) && ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ_PLATFORM) || logic->CanUse(RG_LENS_OF_TRUTH)) && ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_S_DOOR, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), }); areaTable[RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM] = Region("Shadow Temple MQ Stone Umbrella Room", SCENE_SHADOW_TEMPLE, {}, { @@ -577,32 +664,114 @@ void RegionTable_Init_ShadowTemple() { ENTRANCE(RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM, true), }); - //while the spikes here are annoying, they don't really stop you doing anything, so I'll assume either lens trick, lens to see them, or taking damage from them. Not hovers though as a new player won't see the threat without lens to react properly - areaTable[RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM] = Region("Shadow Temple MQ Floor Spikes Room", SCENE_SHADOW_TEMPLE, { - //Events //lens or trick is always required for hookshot targets. We handle it here to not complicate the RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_UPPER_DOOR logic - EVENT_ACCESS(LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && - //Upper door side high rupee needs (hookshot and redead kill(as either age) for chest and adult) or longshot. hovers can cross from the left side with a backflip but that would be a trick - //East midair rupee needs (hookshot and(hover boots or jumpslash from the upper door platform)) or longshot. - //Combined these are longshot or (IsAdult && hookshot && (CanJumpslash || (Hover Boots && Here(CanKillRedeads)))) - (logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && (logic->CanJumpslash() || (logic->CanUse(RG_HOVER_BOOTS) && AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);}))))) && - //1 rupee is in spikes, needs hovers or damage - (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC))), - }, { + //For this room, logic assumes you can either take damage, wear passive spike resistence (Goron tunic or hovers) or see the spikes to navigate across the floor + //As this only matters with 1 heart/OHKO logic, which is already a trick-level setting, using Hook and Longshot to reach rupees without moving is allowed + areaTable[RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_S_DOOR] = Region("Shadow Temple MQ Floor Spikes South Door", SCENE_SHADOW_TEMPLE, {}, { //Locations - LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->TakeDamage() || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_GORON_TUNIC)) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM, logic->Get(LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES)), - //We need to assume we can get here with or without the glass platforms - ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_PLATFORM, ((logic->CanUse(RG_LONGSHOT) || (logic->IsAdult && logic->CanUse(RG_HOOKSHOT) && (logic->Get(LOGIC_SHADOW_MQ_FLOOR_SPIKES_RUPEES) || AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);})))) && (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))) || - ((ctx->GetTrickOption(RT_LENS_SHADOW) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->IsAdult && logic->CanMiddairGroundJump()))), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 3)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS, logic->HasItem(RG_SHADOW_SILVER_SPIKES) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_LONGSHOT)), }); - areaTable[RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_PLATFORM] = Region("Shadow Temple MQ Floor Spikes Platform", SCENE_SHADOW_TEMPLE, {}, {}, { + //Assumes logic for navigating around spikes is checked on entry + areaTable[RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM] = Region("Shadow Temple MQ Floor Spikes Room", SCENE_SHADOW_TEMPLE, { + //Events //(lens or trick) & (adult & hookshot) or longshot is always required for rupees below hookshot targets and the corner platform. + EVENT_ACCESS(LOGIC_SHADOW_SILVER_SPIKES, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(logic->IsAdult ? RG_LONGSHOT : RG_HOOKSHOT) && + //We need to get onto the Door Platform to get North target Rupee at minimum, + //This needs either longshot, middair ground jump or hookshot & adult & defeating the redeads (as any age, as they are perm flags) + //hovers can cross from the corner platform with a backflip but that would be a trick. + logic->CanUse(RG_LONGSHOT) || ((AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);}) || logic->CanMiddairGroundJump()) && + //East midair rupee needs longshot to reach from the floor, or hover boots or jumpslash to reach from the upper door platform. + (logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS))) && + //1 rupee is in spikes, needs hovers or damage + (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC))), + }, { + //Locations + LOCATION(RC_SHADOW_TEMPLE_MQ_INVISIBLE_SPIKES_CHEST, logic->CanKillEnemy(RE_REDEAD) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SHADOW_MQ_N_TARGET_SPIKES_SILVER, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_CENTRAL_SPIKES_SILVER, true), + LOCATION(RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER, logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_S_TARGET_SPIKES_SILVER, logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_INSIDE_SPIKES_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + LOCATION(RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + }, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, true), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_UPPER_WIND_TUNNEL, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_S_DOOR, true), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_W_DOOR, true), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_CORNER_PLATFORM, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanMiddairGroundJump()))), + //if we have silvers, we can just hookshot (as adult) or longshot onto the platforms... + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS, (logic->HasItem(RG_SHADOW_SILVER_SPIKES) && logic->CanUse(logic->IsAdult ? RG_HOOKSHOT : RG_LONGSHOT))), + //otherwise we have to use the hidden target and if we don't have longshot, spawn the chest. even if the glass platforms have spawned, this logic includes the above logic + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM, (((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(logic->IsAdult && AnyAgeTime([]{return logic->CanKillEnemy(RE_REDEAD);}) ? RG_HOOKSHOT : RG_LONGSHOT)) && + //regardless, we can't assume the player does not have the silvers, so we need to cross from the glass to the platform with hovers or a jumpslash jump (as adult) + (logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanJumpslash()))) || + //alternativly, a middair groundjump from the invisible spikes takes adult directly there + ((ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->IsAdult && logic->CanMiddairGroundJump())) + }); + + areaTable[RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_W_DOOR] = Region("Shadow Temple MQ Floor Spikes West Door", SCENE_SHADOW_TEMPLE, {}, { + LOCATION(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_N_TARGET_SPIKES_SILVER, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_S_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), + }, { + //Exits + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM, logic->HasItem(RG_SHADOW_SILVER_SPIKES)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS, logic->HasItem(RG_SHADOW_SILVER_SPIKES) && logic->CanUse(RG_LONGSHOT)), + }); + + areaTable[RR_SHADOW_TEMPLE_MQ_SPIKES_CORNER_PLATFORM] = Region("Shadow Temple MQ Spikes Corner Platform", SCENE_SHADOW_TEMPLE, {}, { + //Locations + // can also get W target silver and get to door platform with hovers backwalk>backflip + LOCATION(RC_SHADOW_MQ_PLATFORM_SPIKES_SILVER, true), + LOCATION(RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER, true), + }, { + //Exits + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + }); + + //Assumes SHADOW_SPIKES_SILVER is checked on entry + areaTable[RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS] = Region("Shadow Temple MQ Spikes Glass Platforms", SCENE_SHADOW_TEMPLE, {}, { + //Locations + LOCATION(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_S_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_N_TARGET_SPIKES_SILVER, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(RG_HOOKSHOT)), + }, { + //Exits + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM, logic->CanUse(RG_HOVER_BOOTS) || (logic->IsAdult && logic->CanJumpslash())), + }); + + areaTable[RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM] = Region("Shadow Temple MQ Spikes Door Platform", SCENE_SHADOW_TEMPLE, { + //Events //(lens or trick) & (adult & hookshot) or longshot is always required for rupees below hookshot targets and the corner platform. + EVENT_ACCESS(LOGIC_SHADOW_SILVER_SPIKES, (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH)) && logic->CanUse(logic->IsAdult ? RG_LONGSHOT : RG_HOOKSHOT) && + //As we start on the upper door platform, we can get north target rupee with just hook, then jump off to get east middair, after which we do not need to get up here again + //East midair rupee needs longshot to reach from the floor, or hover boots or jumpslash to reach from the upper door platform. + (logic->CanUse(RG_LONGSHOT) || logic->CanJumpslash() || logic->CanUse(RG_HOVER_BOOTS)) && + //1 rupee is in spikes, needs hovers or damage + (logic->TakeDamage() || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC))), + }, { + //Locations + // can also get W_TARGET and E_TARGET with hovers backwalk backflip + LOCATION(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER, logic->CanUse(RG_LONGSHOT)), + LOCATION(RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER, true), + LOCATION(RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER, logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash()), + }, { + //Exits + ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH) || logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_GORON_TUNIC) || logic->TakeDamage()), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_CORNER_PLATFORM, logic->CanUse(RG_HOVER_BOOTS)/* && logic->CanUse(RG_ROLL)*/), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS, logic->HasItem(RG_SHADOW_SILVER_SPIKES) && (logic->CanUse(RG_HOOKSHOT) || logic->CanUse(RG_HOVER_BOOTS))), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_UPPER_WIND_TUNNEL, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), }); areaTable[RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM] = Region("Shadow Temple MQ Stalfos Room", SCENE_SHADOW_TEMPLE, {}, { @@ -615,8 +784,8 @@ void RegionTable_Init_ShadowTemple() { areaTable[RR_SHADOW_TEMPLE_MQ_UPPER_WIND_TUNNEL] = Region("Shadow Temple MQ Upper Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { //Exits - ENTRANCE(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), - ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL, (logic->CanUse(RG_HOVER_BOOTS) && logic->CanPassEnemy(RE_BIG_SKULLTULA)) || logic->CanUse(RG_HOOKSHOT)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM, logic->SmallKeys(SCENE_SHADOW_TEMPLE, 4)), + ENTRANCE(RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL, (logic->CanUse(RG_HOVER_BOOTS) && logic->CanPassEnemy(RE_BIG_SKULLTULA)) || logic->CanUse(RG_HOOKSHOT)), }); areaTable[RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL] = Region("Shadow Temple MQ Lower Wind Tunnel", SCENE_SHADOW_TEMPLE, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp index ce09d6d336..387b51f723 100644 --- a/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/dungeons/spirit_temple.cpp @@ -1,6 +1,7 @@ #include "soh/Enhancements/randomizer/location_access.h" #include "soh/Enhancements/randomizer/entrance.h" #include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" using namespace Rando; @@ -84,16 +85,21 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_NORTH] = Region("Spirit Temple Rupee Bridge North", SCENE_SPIRIT_TEMPLE, { //Events - EVENT_ACCESS(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), - EVENT_ACCESS(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES, (logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->HasFireSourceWithTorch()) || logic->CanUse(RG_DINS_FIRE)), + EVENT_ACCESS(LOGIC_SPIRIT_SILVER_CHILD, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + EVENT_ACCESS(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES, (logic->HasItem(RG_SPIRIT_SILVER_CHILD) && logic->HasFireSourceWithTorch()) || logic->CanUse(RG_DINS_FIRE)), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES) && logic->HasItem(RG_OPEN_CHEST)), - // possible to collect without lowering fence, should be a trick - LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) && logic->HasItem(RG_CLIMB)), + // possible to collect by climbing around token without lowering fence, should be a trick. boomerang can grab through fence + LOCATION(RC_SPIRIT_TEMPLE_GS_METAL_FENCE, logic->HasItem(RG_SPIRIT_SILVER_CHILD) && logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_BOMB_THROW) && logic->HasItem(RG_CLIMB)), + LOCATION(RC_SPIRIT_W_HIGH_CHILD_SILVER, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SPIRIT_W_LOW_CHILD_SILVER, true), + LOCATION(RC_SPIRIT_E_LOW_CHILD_SILVER, true), + LOCATION(RC_SPIRIT_E_HIGH_CHILD_SILVER, logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT)), + LOCATION(RC_SPIRIT_TORCH_CHILD_SILVER, true), }, { //Exits - ENTRANCE(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE)), + ENTRANCE(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_SOUTH, logic->HasItem(RG_SPIRIT_SILVER_CHILD)), ENTRANCE(RR_SPIRIT_TEMPLE_1F_ANUBIS, true), }); @@ -106,7 +112,7 @@ void RegionTable_Init_SpiritTemple() { }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_CHILD_SIDE_HUB, true), - ENTRANCE(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_NORTH, logic->Get(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE)), + ENTRANCE(RR_SPIRIT_TEMPLE_RUPEE_BRIDGE_NORTH, logic->HasItem(RG_SPIRIT_SILVER_CHILD)), }); areaTable[RR_SPIRIT_TEMPLE_CHILD_BOXES] = Region("Spirit Temple Child Boxes", SCENE_SPIRIT_TEMPLE, {}, { @@ -163,8 +169,11 @@ void RegionTable_Init_SpiritTemple() { //Jumpslash is possible as child, but pretty tight. Jumpslash as late as you can //A damage boost off the boulder is also possible, but you need to land on the middle of the boulder //to get enough distance to reach the rupee - EVENT_ACCESS(LOGIC_SPIRIT_BOUNDERS_SILVERS, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->CanUse(RG_LONGSHOT)/* || CanBunnyHop()*/), - }, {}, { + EVENT_ACCESS(LOGIC_SPIRIT_SILVER_BOULDERS, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->CanUse(RG_LONGSHOT)/* || CanBunnyHop()*/), + }, { + //Locations + LOCATION(RC_SPIRIT_AIRBORNE_BOULDER_SILVER, logic->CanUse(RG_HOVER_BOOTS) || logic->CanJumpslash() || logic->CanUse(RG_LONGSHOT)/* || CanBunnyHop()*/), + }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_ADULT_SIDE_HUB, true), ENTRANCE(RR_SPIRIT_TEMPLE_BOULDERS, true), @@ -173,10 +182,14 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_BOULDERS] = Region("Spirit Temple Boulders", SCENE_SPIRIT_TEMPLE, {}, { //Locations LOCATION(RC_SPIRIT_TEMPLE_GS_BOULDER_ROOM, logic->CanUse(RG_SONG_OF_TIME) && logic->CanKillEnemy(RE_GOLD_SKULLTULA)), + LOCATION(RC_SPIRIT_NW_BOULDER_SILVER, true), + LOCATION(RC_SPIRIT_SW_BOULDER_SILVER, true), + LOCATION(RC_SPIRIT_SE_BOULDER_SILVER, true), + LOCATION(RC_SPIRIT_NE_BOULDER_SILVER, true), }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_ABOVE_BOULDERS, logic->IsAdult || logic->HasItem(RG_CLIMB) || logic->CanUse(RG_HOOKSHOT) || logic->CanGroundJump()), - ENTRANCE(RR_SPIRIT_TEMPLE_PAST_BOULDERS, logic->Get(LOGIC_SPIRIT_BOUNDERS_SILVERS)), + ENTRANCE(RR_SPIRIT_TEMPLE_PAST_BOULDERS, logic->HasItem(RG_SPIRIT_SILVER_BOULDERS)), }); areaTable[RR_SPIRIT_TEMPLE_PAST_BOULDERS] = Region("Spirit Temple Past Boulders", SCENE_SPIRIT_TEMPLE, {}, { @@ -289,7 +302,13 @@ void RegionTable_Init_SpiritTemple() { ENTRANCE(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, true), }); - areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM] = Region("Spirit Temple Sun Block Room", SCENE_SPIRIT_TEMPLE, {}, {}, { + areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM] = Region("Spirit Temple Sun Block Room", SCENE_SPIRIT_TEMPLE, {}, { + //Locations + LOCATION(RC_SPIRIT_NEAR_LIGHT_SUN_SILVER, true), + LOCATION(RC_SPIRIT_AIRBORNE_SUN_SILVER, true), + LOCATION(RC_SPIRIT_MID_PLATFORM_SUN_SILVER, true), + LOCATION(RC_SPIRIT_NEAR_DOOR_SUN_SILVER, true), + }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_EMPTY_STAIRS, logic->HasItem(RG_POWER_BRACELET) || logic->SunlightArrows()), //The blocks can be used to get onto this ledge itemless @@ -300,14 +319,15 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE] = Region("Spirit Temple Sun Block Chest Ledge", SCENE_SPIRIT_TEMPLE, { //Events //Assumes RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM access - EVENT_ACCESS(LOGIC_SPIRIT_SUN_BLOCK_TORCH, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, []{return true;}, true)), + EVENT_ACCESS(LOGIC_SPIRIT_SILVER_SUN, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, []{return true;}, true)), }, { //Locations //Spawning the chest to get here is accounted for in movement logic, so we only need to confirm it can be spawned here LOCATION(RC_SPIRIT_TEMPLE_SUN_BLOCK_ROOM_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, []{return logic->HasFireSource() || - (logic->Get(LOGIC_SPIRIT_SUN_BLOCK_TORCH) && + (logic->HasItem(RG_SPIRIT_SILVER_SUN) && (logic->CanUse(RG_STICKS) || (ctx->GetTrickOption(RT_SPIRIT_SUN_CHEST) && logic->CanUse(RG_FAIRY_BOW))));}) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_NEAR_CHEST_SUN_SILVER, SpiritShared(RR_SPIRIT_TEMPLE_SUN_BLOCK_CHEST_LEDGE, []{return true;}, true)), }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_SUN_BLOCK_ROOM, true), @@ -564,7 +584,7 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_LEFT_CHEST, logic->HasItem(RG_OPEN_CHEST) && ((AnyAgeTime([]{return logic->BlastOrSmash();}) && logic->CanHitEyeTargets()) || (ctx->GetTrickOption(RT_BOULDER_COLLISION) && logic->IsChild ? logic->CanHitEyeTargets() : logic->CanUse(RG_FAIRY_SLINGSHOT)))), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_BACK_RIGHT_CHEST, logic->CanHitSwitch(ED_BOOMERANG) && logic->HasItem(RG_OPEN_CHEST)), - LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->Get(LOGIC_SPIRIT_1F_SILVER_RUPEES) && logic->HasItem(RG_OPEN_CHEST)), + LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_FRONT_RIGHT_CHEST, logic->HasItem(RG_SPIRIT_MQ_SILVER_LOBBY) && logic->HasItem(RG_OPEN_CHEST)), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_2, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_POT_3, logic->CanBreakPots()), @@ -575,6 +595,8 @@ void RegionTable_Init_SpiritTemple() { LOCATION(RC_SPIRIT_TEMPLE_MQ_ENTRANCE_CEILING_BOULDER, logic->CanUse(RG_BOMBCHU_5)), LOCATION(RC_SPIRIT_TEMPLE_LEFT_SNAKE_STATUE, logic->CanRead()), LOCATION(RC_SPIRIT_TEMPLE_RIGHT_SNAKE_STATUE, logic->CanRead()), + LOCATION(RC_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER, logic->BlastOrSmash()), + LOCATION(RC_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER, logic->BlastOrSmash()), }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_ENTRYWAY, true), @@ -927,12 +949,15 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BEHIND_GEYSER] = Region("Spirit Temple MQ Behind Geyser", SCENE_SPIRIT_TEMPLE, { //Events //Assumes RR_SPIRIT_TEMPLE_MQ_FOYER access - EVENT_ACCESS(LOGIC_SPIRIT_1F_SILVER_RUPEES, logic->CanUse(RG_MEGATON_HAMMER)), + EVENT_ACCESS(LOGIC_SPIRIT_MQ_SILVER_LOBBY, logic->CanUse(RG_MEGATON_HAMMER)), }, { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_POT_2, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_EARLY_ADULT_BOULDER, logic->BlastOrSmash()), + LOCATION(RC_SPIRIT_MQ_STAIRS_LOBBY_SILVER, true), + LOCATION(RC_SPIRIT_MQ_CORNER_LOBBY_SILVER, true), + LOCATION(RC_SPIRIT_MQ_JET_LOBBY_SILVER, logic->CanUse(RG_MEGATON_HAMMER)), }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_FOYER, logic->CanUse(RG_MEGATON_HAMMER) || (ctx->GetTrickOption(RT_HOVER_BOOST_SIMPLE) && logic->CanUse(RG_HOVER_BOOTS) && logic->CanStandingShield() && (logic->CanUseSword() || logic->CanUse(RG_STICKS)))), @@ -1052,6 +1077,11 @@ void RegionTable_Init_SpiritTemple() { //Locations LOCATION(RC_SPIRIT_TEMPLE_MQ_LONG_CLIMB_POT_1, logic->CanBreakPots()), LOCATION(RC_SPIRIT_TEMPLE_MQ_LONG_CLIMB_POT_2, logic->CanBreakPots()), + LOCATION(RC_SPIRIT_MQ_LOWEST_WALL_SILVER, logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)), + LOCATION(RC_SPIRIT_MQ_MID_LOW_WALL_SILVER, logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)), + LOCATION(RC_SPIRIT_MQ_MID_HIGH_WALL_SILVER, logic->CanUse(RG_HOOKSHOT) || logic->HasItem(RG_CLIMB)), + LOCATION(RC_SPIRIT_MQ_HIGHEST_WALL_SILVER, logic->CanUse(RG_LONGSHOT) || (logic->HasItem(RG_CLIMB) && (logic->CanKillEnemy(RE_KEESE) || logic->CanUse(RG_SKULL_MASK)))), + LOCATION(RC_SPIRIT_MQ_MIDDLE_WALL_SILVER, logic->CanUse(RG_LONGSHOT) || (logic->HasItem(RG_CLIMB) && (logic->CanKillEnemy(RE_KEESE) || logic->CanUse(RG_SKULL_MASK)))), }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BEAMOS_PITS, true), @@ -1061,12 +1091,18 @@ void RegionTable_Init_SpiritTemple() { areaTable[RR_SPIRIT_TEMPLE_MQ_BIG_WALL_UPPER] = Region("Spirit Temple MQ Big Wall Upper", SCENE_SPIRIT_TEMPLE, { //Events - //Getting some of these with just climbing downwards is theoretically possible but definitely a trick - EVENT_ACCESS(LOGIC_SPIRIT_MQ_BIG_WALL_SILVERS, (logic->CanKillEnemy(RE_KEESE) || logic->CanUse(RG_SKULL_MASK)) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))), - }, {}, { + //You can easilly get any 1 silver dropping down, but getting them all only going down is likely impossible + EVENT_ACCESS(LOGIC_SPIRIT_MQ_SILVER_BIG_WALL, (logic->CanKillEnemy(RE_KEESE) || logic->CanUse(RG_SKULL_MASK)) && (logic->HasItem(RG_CLIMB) || logic->CanUse(RG_LONGSHOT))), + }, { + LOCATION(RC_SPIRIT_MQ_LOWEST_WALL_SILVER, true), + LOCATION(RC_SPIRIT_MQ_MID_LOW_WALL_SILVER, true), + LOCATION(RC_SPIRIT_MQ_MID_HIGH_WALL_SILVER, true), + LOCATION(RC_SPIRIT_MQ_HIGHEST_WALL_SILVER, true), + LOCATION(RC_SPIRIT_MQ_MIDDLE_WALL_SILVER, true), + }, { //Exits ENTRANCE(RR_SPIRIT_TEMPLE_MQ_BIG_WALL_BASE, true), - ENTRANCE(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, logic->Get(LOGIC_SPIRIT_MQ_BIG_WALL_SILVERS)), + ENTRANCE(RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL, logic->HasItem(RG_SPIRIT_MQ_SILVER_BIG_WALL)), }); areaTable[RR_SPIRIT_TEMPLE_MQ_4F_CENTRAL] = Region("Spirit Temple MQ 4F Central", SCENE_SPIRIT_TEMPLE, {}, { diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp index d1bca0e740..179f12db9a 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/gerudo_valley.cpp @@ -59,7 +59,7 @@ void RegionTable_Init_GerudoValley() { }, { //Exits ENTRANCE(RR_GV_UPPER_STREAM_WATER, true), - ENTRANCE(RR_GV_WATERFALL_ALCOVE, (logic->CanUse(RG_LONGSHOT) && (logic->CanUse(RG_CLIMB) || ctx->GetTrickOption(RT_HOOKSHOT_LADDERS))) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)), + ENTRANCE(RR_GV_WATERFALL_ALCOVE, (logic->CanUse(RG_LONGSHOT) && (logic->HasItem(RG_CLIMB) || ctx->GetTrickOption(RT_HOOKSHOT_LADDERS))) || CanPlantBean(RR_GV_UPPER_STREAM, RG_GERUDO_VALLEY_BEAN_SOUL)), }); areaTable[RR_GV_UPPER_STREAM_WATER] = Region("GV Upper Stream Water", SCENE_GERUDO_VALLEY, {}, {}, { diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index 43173c5345..fce010dc54 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -4,6 +4,7 @@ #include #include "soh/OTRGlobals.h" +#include "randomizer.h" #include "dungeon.h" #include "SeedContext.h" #include "macros.h" @@ -272,6 +273,39 @@ bool Logic::HasItem(RandomizerGet itemName) { return CurrentUpgrade(UPG_SCALE) >= 1; case RG_GOLDEN_SCALE: return CurrentUpgrade(UPG_SCALE) >= 2; + // Silver Rupees + case RG_SHADOW_SILVER_BLADES: + case RG_SHADOW_SILVER_PIT: + case RG_SHADOW_SILVER_SPIKES: + case RG_SPIRIT_SILVER_CHILD: + case RG_SPIRIT_SILVER_SUN: + case RG_SPIRIT_SILVER_BOULDERS: + case RG_BOTW_SILVER: + case RG_ICE_CAVERN_SILVER_BLADES: + case RG_ICE_CAVERN_SILVER_BLOCK: + case RG_GTG_SILVER_SLOPE: + case RG_GTG_SILVER_LAVA: + case RG_GTG_SILVER_WATER: + case RG_GANONS_CASTLE_SILVER_LIGHT: + case RG_GANONS_CASTLE_SILVER_FOREST: + case RG_GANONS_CASTLE_SILVER_FIRE: + case RG_GANONS_CASTLE_SILVER_SPIRIT: + case RG_DODONGOS_CAVERN_MQ_SILVER: + case RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES: + case RG_SPIRIT_MQ_SILVER_LOBBY: + case RG_SPIRIT_MQ_SILVER_BIG_WALL: + case RG_GANONS_CASTLE_MQ_SILVER_WATER: + case RG_GANONS_CASTLE_MQ_SILVER_SHADOW: { + if (!ctx->GetOption(RSK_SHUFFLE_SILVER)) { + return Get((LogicVal)(LOGIC_SHADOW_SILVER_BLADES + (itemName - RG_SHADOW_SILVER_BLADES))); + } else if (ctx->GetOption(RSK_SHUFFLE_SILVER).Is(RO_SHUFFLE_SILVER_STARTWITH)) { + return true; + } else { + s8 field = *Randomizer::SilverFieldFromSaveContext(mSaveContext, itemName); + return field >= Randomizer::SilverTotal(itemName); + } + } + // Trade Items case RG_POCKET_EGG: return CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_EGG) || CheckRandoInf(RAND_INF_ADULT_TRADES_HAS_POCKET_CUCCO); @@ -2429,6 +2463,25 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case ITEMTYPE_BOSSKEY: SetDungeonItem(DUNGEON_KEY_BOSS, RandoGetToDungeonScene.find(item.GetRandomizerGet())->second, state); break; + case ITEMTYPE_SILVER: { + auto randoGet = item.GetRandomizerGet(); + s8* field = Randomizer::SilverFieldFromSaveContext(mSaveContext, randoGet); + bool isWallet = ctx->GetOption(RSK_SHUFFLE_SILVER).Is(RO_SHUFFLE_SILVER_WALLET); + if (!state) { + if (isWallet) { + *field = 0; + } else { + *field -= 1; + } + } else { + if (isWallet) { + *field = 10; + } else { + *field += 1; + } + } + break; + } case ITEMTYPE_FORTRESS_SMALLKEY: case ITEMTYPE_SMALLKEY: { auto randoGet = item.GetRandomizerGet(); @@ -2629,7 +2682,7 @@ void Logic::InitSaveContext() { mSaveContext->horseData.angle = -0x6AD9; mSaveContext->magicLevel = 0; mSaveContext->infTable[29] = 1; - mSaveContext->sceneFlags[5].swch = 0x40000000; + mSaveContext->sceneFlags[SCENE_WATER_TEMPLE].swch = 0x40000000; // SoH specific mSaveContext->ship.backupFW = mSaveContext->fw; @@ -2645,7 +2698,7 @@ void Logic::InitSaveContext() { void Logic::NewSaveContext() { if (mSaveContext != nullptr && mSaveContext != &gSaveContext) { - free(mSaveContext); + delete mSaveContext; } mSaveContext = new SaveContext(); InitSaveContext(); diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index e14e412d57..8e801ddc31 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -547,6 +547,17 @@ void Settings::CreateOptionDescriptions() { "Overworld - Only freestanding rupees & hearts that are outside of dungeons.\n" "\n" "All Items - Shuffle all freestanding rupees & hearts."; + mOptionDescriptions[RSK_SHUFFLE_SILVER] = + "Silver rupees will be shuffled.\n" + "Items will be added to pool which completes the silver rupee puzzles,\n" + "while silver rupee locations will be random items.\n" + "Off - silver rupees won't be shuffled." + "\n" + "On - silver rupees will be individually spread out." + "\n" + "Wallet - silver rupees are shuffled as wallets, a single check to set flag for collecting them." + "\n" + "Start With - Silver rupees are still replaced with items, but all silver rupee flags start set."; mOptionDescriptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES] = "Shuffle fairies in fountain locations. " "This includes the sets of fairies found in Ganon's Castle and the Desert Oasis."; diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index cb72c0affc..cd3314158c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -658,6 +658,33 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_LIGHT_MEDALLION: return !CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; + // silver rupees + case RG_SHADOW_SILVER_BLADES: + case RG_SHADOW_SILVER_PIT: + case RG_SHADOW_SILVER_SPIKES: + case RG_SPIRIT_SILVER_CHILD: + case RG_SPIRIT_SILVER_SUN: + case RG_SPIRIT_SILVER_BOULDERS: + case RG_BOTW_SILVER: + case RG_ICE_CAVERN_SILVER_BLADES: + case RG_ICE_CAVERN_SILVER_BLOCK: + case RG_GTG_SILVER_SLOPE: + case RG_GTG_SILVER_LAVA: + case RG_GTG_SILVER_WATER: + case RG_GANONS_CASTLE_SILVER_LIGHT: + case RG_GANONS_CASTLE_SILVER_FOREST: + case RG_GANONS_CASTLE_SILVER_FIRE: + case RG_GANONS_CASTLE_SILVER_SPIRIT: + case RG_DODONGOS_CAVERN_MQ_SILVER: + case RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES: + case RG_SPIRIT_MQ_SILVER_LOBBY: + case RG_SPIRIT_MQ_SILVER_BIG_WALL: + case RG_GANONS_CASTLE_MQ_SILVER_WATER: + case RG_GANONS_CASTLE_MQ_SILVER_SHADOW: + return *Randomizer::SilverFieldFromSaveContext(&gSaveContext, randoGet) < Randomizer::SilverTotal(randoGet) + ? CAN_OBTAIN + : CANT_OBTAIN_ALREADY_HAVE; + case RG_RECOVERY_HEART: case RG_GREEN_RUPEE: case RG_GREG_RUPEE: @@ -863,6 +890,27 @@ ShopItemIdentity Randomizer::IdentifyShopItem(s32 sceneNum, u8 slotIndex) { return shopItemIdentity; } +CheckIdentity Randomizer::IdentifySilver(s32 sceneNum, Vec3f pos) { + struct CheckIdentity silverIdentity; + + silverIdentity.randomizerInf = RAND_INF_MAX; + silverIdentity.randomizerCheck = RC_UNKNOWN_CHECK; + + s32 actorParams = TWO_ACTOR_PARAMS((s16)pos.x, (s16)pos.z); + if (sceneNum == SCENE_SHADOW_TEMPLE && actorParams == TWO_ACTOR_PARAMS(2110, 3372)) { + actorParams = TWO_ACTOR_PARAMS((s16)pos.x, (s16)pos.y); + } + + Rando::Location* location = GetCheckObjectFromActor(ACTOR_EN_G_SWITCH, sceneNum, actorParams); + + if (location->GetRandomizerCheck() != RC_UNKNOWN_CHECK) { + silverIdentity.randomizerInf = rcToRandomizerInf[location->GetRandomizerCheck()]; + silverIdentity.randomizerCheck = location->GetRandomizerCheck(); + } + + return silverIdentity; +} + u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) { return Rando::Context::GetInstance()->GetOption(randoSettingKey).Get(); } @@ -1416,6 +1464,41 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { INV_CONTENT(ITEM_NAYRUS_LOVE) = ITEM_ROCS_FEATHER; } break; + case RG_SHADOW_SILVER_BLADES: + case RG_SHADOW_SILVER_PIT: + case RG_SHADOW_SILVER_SPIKES: + case RG_SPIRIT_SILVER_CHILD: + case RG_SPIRIT_SILVER_SUN: + case RG_SPIRIT_SILVER_BOULDERS: + case RG_BOTW_SILVER: + case RG_ICE_CAVERN_SILVER_BLADES: + case RG_ICE_CAVERN_SILVER_BLOCK: + case RG_GTG_SILVER_SLOPE: + case RG_GTG_SILVER_LAVA: + case RG_GTG_SILVER_WATER: + case RG_GANONS_CASTLE_SILVER_LIGHT: + case RG_GANONS_CASTLE_SILVER_FOREST: + case RG_GANONS_CASTLE_SILVER_FIRE: + case RG_GANONS_CASTLE_SILVER_SPIRIT: + case RG_DODONGOS_CAVERN_MQ_SILVER: + case RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES: + case RG_SPIRIT_MQ_SILVER_LOBBY: + case RG_SPIRIT_MQ_SILVER_BIG_WALL: + case RG_GANONS_CASTLE_MQ_SILVER_WATER: + case RG_GANONS_CASTLE_MQ_SILVER_SHADOW: { + s8* field = Randomizer::SilverFieldFromSaveContext(&gSaveContext, item); + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) == + RO_SHUFFLE_SILVER_WALLET) { + *field = 10; + // this spoils MQ in theory, but will not update trackers because it's subtle and there's too many edge + // cases where this does not apply + Rupees_ChangeBy(Randomizer::SilverTotal(item) * 5); + } else { + *field += 1; + Rupees_ChangeBy(5); + } + break; + } default: LUSLOG_WARN("Randomizer_Item_Give didn't have behaviour specified for getItemId=%d", item); assert(false); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 38e298d1c8..e5ede9a509 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -40,12 +40,15 @@ class Randomizer { ~Randomizer(); bool SpoilerFileExists(const char* spoilerFileName); bool IsTrialRequired(s32 trialFlag); + static s8 SilverTotal(RandomizerGet rg); + static s8* SilverFieldFromSaveContext(SaveContext* saveContext, RandomizerGet rg); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); u8 GetTriforcePiecesRequired(); RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf); RandomizerInf GetRandomizerInfFromCheck(RandomizerCheck rc); Rando::Location* GetCheckObjectFromActor(s16 actorId, s16 sceneNum, s32 actorParams); ShopItemIdentity IdentifyShopItem(s32 sceneNum, u8 slotIndex); + CheckIdentity IdentifySilver(s32 sceneNum, Vec3f pos); GetItemEntry GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability = true); GetItemEntry GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums.h b/soh/soh/Enhancements/randomizer/randomizerEnums.h index cc625627bb..b5d4601e24 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums.h @@ -1,3 +1,4 @@ +#pragma once // Default expansion: real enums #if !defined(RANDO_ENUM_BEGIN) && !defined(RANDO_ENUM_ITEM) && !defined(RANDO_ENUM_END) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h index 9034bd4ee1..fae4cea67d 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h @@ -177,6 +177,28 @@ RANDO_ENUM_ITEM(LOGIC_OCARINA_C_UP_BUTTON) RANDO_ENUM_ITEM(LOGIC_OCARINA_C_DOWN_BUTTON) RANDO_ENUM_ITEM(LOGIC_OCARINA_C_LEFT_BUTTON) RANDO_ENUM_ITEM(LOGIC_OCARINA_C_RIGHT_BUTTON) +RANDO_ENUM_ITEM(LOGIC_SHADOW_SILVER_BLADES) +RANDO_ENUM_ITEM(LOGIC_SHADOW_SILVER_PIT) +RANDO_ENUM_ITEM(LOGIC_SHADOW_SILVER_SPIKES) +RANDO_ENUM_ITEM(LOGIC_SPIRIT_SILVER_CHILD) +RANDO_ENUM_ITEM(LOGIC_SPIRIT_SILVER_SUN) +RANDO_ENUM_ITEM(LOGIC_SPIRIT_SILVER_BOULDERS) +RANDO_ENUM_ITEM(LOGIC_BOTW_SILVER) +RANDO_ENUM_ITEM(LOGIC_ICE_CAVERN_SILVER_BLADES) +RANDO_ENUM_ITEM(LOGIC_ICE_CAVERN_SILVER_BLOCK) +RANDO_ENUM_ITEM(LOGIC_GTG_SILVER_SLOPE) +RANDO_ENUM_ITEM(LOGIC_GTG_SILVER_LAVA) +RANDO_ENUM_ITEM(LOGIC_GTG_SILVER_WATER) +RANDO_ENUM_ITEM(LOGIC_GANONS_CASTLE_SILVER_LIGHT) +RANDO_ENUM_ITEM(LOGIC_GANONS_CASTLE_SILVER_FOREST) +RANDO_ENUM_ITEM(LOGIC_GANONS_CASTLE_SILVER_FIRE) +RANDO_ENUM_ITEM(LOGIC_GANONS_CASTLE_SILVER_SPIRIT) +RANDO_ENUM_ITEM(LOGIC_DODONGOS_CAVERN_MQ_SILVER) +RANDO_ENUM_ITEM(LOGIC_SHADOW_MQ_SILVER_INVISIBLE_BLADES) +RANDO_ENUM_ITEM(LOGIC_SPIRIT_MQ_SILVER_LOBBY) +RANDO_ENUM_ITEM(LOGIC_SPIRIT_MQ_SILVER_BIG_WALL) +RANDO_ENUM_ITEM(LOGIC_GANONS_CASTLE_MQ_SILVER_WATER) +RANDO_ENUM_ITEM(LOGIC_GANONS_CASTLE_MQ_SILVER_SHADOW) RANDO_ENUM_ITEM(LOGIC_ROCS_FEATHER) RANDO_ENUM_ITEM(LOGIC_CAN_BORROW_MASKS) RANDO_ENUM_ITEM(LOGIC_BORROW_SKULL_MASK) @@ -233,7 +255,6 @@ RANDO_ENUM_ITEM(LOGIC_DC_LIFT_PLATFORM) RANDO_ENUM_ITEM(LOGIC_DC_KILLED_LOWER_LIZALFOS) RANDO_ENUM_ITEM(LOGIC_DC_MQ_CLEAR_UPPER_LOBBY_ROCKS) RANDO_ENUM_ITEM(LOGIC_DC_MQ_CLEAR_BIG_BLOCK_WEB) -RANDO_ENUM_ITEM(LOGIC_DC_MQ_STAIRS_SILVER_RUPEES) RANDO_ENUM_ITEM(LOGIC_DC_MQ_BEHIND_FIRE_SWITCH) RANDO_ENUM_ITEM(LOGIC_JABU_RUTO_IN_1F) RANDO_ENUM_ITEM(LOGIC_JABU_WEST_TENTACLE) @@ -281,12 +302,9 @@ RANDO_ENUM_ITEM(LOGIC_WATER_MQ_B1_SWITCH) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_B1_OPENED_PILLAR) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_PILLAR_SOT_BLOCK) RANDO_ENUM_ITEM(LOGIC_WATER_MQ_SIDE_TOWER_TARGETS) -RANDO_ENUM_ITEM(LOGIC_SPIRIT_1F_SILVER_RUPEES) RANDO_ENUM_ITEM(LOGIC_SPIRIT_CHILD_SWITCH_BRIDGE) -RANDO_ENUM_ITEM(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE) RANDO_ENUM_ITEM(LOGIC_SPIRIT_SILVER_RUPEE_BRIDGE_TORCHES) RANDO_ENUM_ITEM(LOGIC_SPIRIT_SUN_BLOCK_TORCH) -RANDO_ENUM_ITEM(LOGIC_SPIRIT_BOUNDERS_SILVERS) RANDO_ENUM_ITEM(LOGIC_SPIRIT_STATUE_SOUTH_DOOR) RANDO_ENUM_ITEM(LOGIC_SPIRIT_NABOORU_KIDNAPPED) RANDO_ENUM_ITEM(LOGIC_SPIRIT_PLATFORM_LOWERED) @@ -300,7 +318,6 @@ RANDO_ENUM_ITEM(LOGIC_SPIRIT_MQ_TIME_TRAVEL_CHEST) RANDO_ENUM_ITEM(LOGIC_SPIRIT_MQ_STATUE_ROOM_TORCHES) RANDO_ENUM_ITEM(LOGIC_SPIRIT_MQ_3SUNS_ENEMIES) RANDO_ENUM_ITEM(LOGIC_SPIRIT_MQ_SYMPHONY_ROOM_DOOR) -RANDO_ENUM_ITEM(LOGIC_SPIRIT_MQ_BIG_WALL_SILVERS) RANDO_ENUM_ITEM(LOGIC_REVERSE_SPIRIT_CHILD) RANDO_ENUM_ITEM(LOGIC_REVERSE_SPIRIT_ADULT) RANDO_ENUM_ITEM(LOGIC_FORWARDS_SPIRIT_CHILD) @@ -325,15 +342,11 @@ RANDO_ENUM_ITEM(LOGIC_BOTW_MQ_OPENED_WEST_ROOM) RANDO_ENUM_ITEM(LOGIC_BOTW_MQ_OPENED_MIDDLE_HOLE) RANDO_ENUM_ITEM(LOGIC_GTG_MQ_MAZE_SWITCH) RANDO_ENUM_ITEM(LOGIC_GTG_MQ_RIGHT_SIDE_SWITCH) -RANDO_ENUM_ITEM(LOGIC_GTG_PLATFORM_SILVER_RUPEES) RANDO_ENUM_ITEM(LOGIC_GTG_UNLOCKED_DOOR_BEHIND_HEAVY_BLOCK) RANDO_ENUM_ITEM(LOGIC_GTG_PUSHED_HEAVY_BLOCK) RANDO_ENUM_ITEM(LOGIC_GTG_CLEARED_EYE_STATUE) -RANDO_ENUM_ITEM(LOGIC_FOREST_TRIAL_SILVER_RUPEES) RANDO_ENUM_ITEM(LOGIC_FOREST_TRIAL_MQ_SPAWN_BEAMOS_CHEST) -RANDO_ENUM_ITEM(LOGIC_FIRE_TRIAL_SILVER_RUPEES) RANDO_ENUM_ITEM(LOGIC_WATER_TRIAL_RUSTED_SWITCH) -RANDO_ENUM_ITEM(LOGIC_WATER_TRIAL_MQ_SILVER_RUPEES) RANDO_ENUM_ITEM(LOGIC_WATER_TRIAL_MQ_MELTED_FINAL_DOOR_RED_ICE) RANDO_ENUM_ITEM(LOGIC_SHADOW_TRIAL_FIRST_CHEST) RANDO_ENUM_ITEM(LOGIC_SHADOW_TRIAL_LOWER_SWITCH) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h index a90957bc6d..f9ac7a73bc 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerCheck.h @@ -2504,6 +2504,163 @@ RANDO_ENUM_ITEM(RC_GERUDO_TRAINING_GROUND_MQ_WONDER_EYE_STATUE) RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_WONDER_SHADOW_TRIAL) // End Wonder Items +// Start Silver Rupees +RANDO_ENUM_ITEM(RC_SHADOW_N_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_TALL_BLOCK_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_N_NOOK_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_W_NOOK_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_S_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_N_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_S_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_BEAMOS_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_E_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_W_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_PLATFORM_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_E_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_FLOOR_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_W_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_AIRBORNE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_W_HIGH_CHILD_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_W_LOW_CHILD_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_E_LOW_CHILD_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_E_HIGH_CHILD_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_TORCH_CHILD_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_NEAR_LIGHT_SUN_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_AIRBORNE_SUN_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MID_PLATFORM_SUN_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_NEAR_CHEST_SUN_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_NEAR_DOOR_SUN_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_NW_BOULDER_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_SW_BOULDER_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_SE_BOULDER_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_NE_BOULDER_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_AIRBORNE_BOULDER_SILVER) +RANDO_ENUM_ITEM(RC_BOTW_B1_LADDER_SILVER) +RANDO_ENUM_ITEM(RC_BOTW_B2_LADDER_SILVER) +RANDO_ENUM_ITEM(RC_BOTW_B3_LADDER_SILVER) +RANDO_ENUM_ITEM(RC_BOTW_NW_OOZE_SILVER) +RANDO_ENUM_ITEM(RC_BOTW_SE_OOZE_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_ICICLES_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_W_INNER_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_OUTER_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_E_INNER_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_AIRBORNE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_LOWER_BLOCK_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_NEAR_BLOCK_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_FROZEN_BLOCK_SILVER) +RANDO_ENUM_ITEM(RC_ICE_CAVERN_NEAR_GS_BLOCK_SILVER) +RANDO_ENUM_ITEM(RC_GTG_FIRE_WALL_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_LOWER_BOULDER_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_TARGET_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_JUMPDOWN_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_UPPER_BOULDER_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_NEAR_SWITCH_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_NEAR_BARRED_DOOR_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_FIRE_RING_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_UPPER_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_UNDER_LEDGE_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MIDDLE_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GTG_ABOVE_TARGET_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GTG_LEFT_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GTG_UNDER_TARGET_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GTG_RIGHT_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_UPPER_LIGHT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_ON_TARGET_FOREST_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_CORNER_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RC_DODONGOS_CAVERN_MQ_BEAMOS_SILVER) +RANDO_ENUM_ITEM(RC_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER) +RANDO_ENUM_ITEM(RC_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER) +RANDO_ENUM_ITEM(RC_DODONGOS_CAVERN_MQ_VINES_SILVER) +RANDO_ENUM_ITEM(RC_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_W_NOOK_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_NE_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_S_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_N_NOOK_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_W_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_HIGH_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_HIGHEST_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_N_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_E_PIT_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_PLATFORM_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_W_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_N_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_CENTRAL_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_S_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_INSIDE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SHADOW_MQ_E_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_STAIRS_LOBBY_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_CORNER_LOBBY_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_JET_LOBBY_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_LOWEST_WALL_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_MID_LOW_WALL_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_MID_HIGH_WALL_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_HIGHEST_WALL_SILVER) +RANDO_ENUM_ITEM(RC_SPIRIT_MQ_MIDDLE_WALL_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_ICICLES_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_JUMPDOWN_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_HIGH_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_FREEZARD_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_PIT_SLOPE_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_NEAR_SWITCH_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_FAR_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_MIDDLE_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_NEAR_BARRED_DOOR_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_BACK_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_MIDDLE_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GTG_MQ_FRONT_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_NOOK_WATER_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER) +RANDO_ENUM_ITEM(RC_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER) +// End Silver Rupees + RANDO_ENUM_ITEM(RC_SFM_FAIRY_GROTTO_FAIRY_1) RANDO_ENUM_ITEM(RC_SFM_FAIRY_GROTTO_FAIRY_2) RANDO_ENUM_ITEM(RC_SFM_FAIRY_GROTTO_FAIRY_3) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h index 3b7806385f..4b31a2824f 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerGet.h @@ -136,6 +136,28 @@ RANDO_ENUM_ITEM(RG_GERUDO_TRAINING_GROUND_KEY_RING) RANDO_ENUM_ITEM(RG_GERUDO_FORTRESS_KEY_RING) RANDO_ENUM_ITEM(RG_GANONS_CASTLE_KEY_RING) RANDO_ENUM_ITEM(RG_TREASURE_GAME_KEY_RING) +RANDO_ENUM_ITEM(RG_SHADOW_SILVER_BLADES) +RANDO_ENUM_ITEM(RG_SHADOW_SILVER_PIT) +RANDO_ENUM_ITEM(RG_SHADOW_SILVER_SPIKES) +RANDO_ENUM_ITEM(RG_SPIRIT_SILVER_CHILD) +RANDO_ENUM_ITEM(RG_SPIRIT_SILVER_SUN) +RANDO_ENUM_ITEM(RG_SPIRIT_SILVER_BOULDERS) +RANDO_ENUM_ITEM(RG_BOTW_SILVER) +RANDO_ENUM_ITEM(RG_ICE_CAVERN_SILVER_BLADES) +RANDO_ENUM_ITEM(RG_ICE_CAVERN_SILVER_BLOCK) +RANDO_ENUM_ITEM(RG_GTG_SILVER_SLOPE) +RANDO_ENUM_ITEM(RG_GTG_SILVER_LAVA) +RANDO_ENUM_ITEM(RG_GTG_SILVER_WATER) +RANDO_ENUM_ITEM(RG_GANONS_CASTLE_SILVER_LIGHT) +RANDO_ENUM_ITEM(RG_GANONS_CASTLE_SILVER_FOREST) +RANDO_ENUM_ITEM(RG_GANONS_CASTLE_SILVER_FIRE) +RANDO_ENUM_ITEM(RG_GANONS_CASTLE_SILVER_SPIRIT) +RANDO_ENUM_ITEM(RG_DODONGOS_CAVERN_MQ_SILVER) +RANDO_ENUM_ITEM(RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES) +RANDO_ENUM_ITEM(RG_SPIRIT_MQ_SILVER_LOBBY) +RANDO_ENUM_ITEM(RG_SPIRIT_MQ_SILVER_BIG_WALL) +RANDO_ENUM_ITEM(RG_GANONS_CASTLE_MQ_SILVER_WATER) +RANDO_ENUM_ITEM(RG_GANONS_CASTLE_MQ_SILVER_SHADOW) RANDO_ENUM_ITEM(RG_KOKIRI_EMERALD) RANDO_ENUM_ITEM(RG_GORON_RUBY) RANDO_ENUM_ITEM(RG_ZORA_SAPPHIRE) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h index 02fc97d94e..88f8154d69 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerHintTextKey.h @@ -1079,6 +1079,13 @@ RANDO_ENUM_ITEM(RHT_SPEAK) RANDO_ENUM_ITEM(RHT_OPEN_CHEST) RANDO_ENUM_ITEM(RHT_FISHING_POLE) RANDO_ENUM_ITEM(RHT_SKELETON_KEY) +RANDO_ENUM_ITEM(RHT_SILVER_RUPEE_DODONGOS_CAVERN) +RANDO_ENUM_ITEM(RHT_SILVER_RUPEE_SHADOW_TEMPLE) +RANDO_ENUM_ITEM(RHT_SILVER_RUPEE_SPIRIT_TEMPLE) +RANDO_ENUM_ITEM(RHT_SILVER_RUPEE_BOTW) +RANDO_ENUM_ITEM(RHT_SILVER_RUPEE_ICE_CAVERN) +RANDO_ENUM_ITEM(RHT_SILVER_RUPEE_GTG) +RANDO_ENUM_ITEM(RHT_SILVER_RUPEE_GANONS_CASTLE) RANDO_ENUM_ITEM(RHT_EPONA) RANDO_ENUM_ITEM(RHT_OVERWORLD_KEY) RANDO_ENUM_ITEM(RHT_HINT_MYSTERIOUS) @@ -1458,6 +1465,14 @@ RANDO_ENUM_ITEM(RHT_ICE_CAVERN_HEART) RANDO_ENUM_ITEM(RHT_ICE_CAVERN_RUPEE) RANDO_ENUM_ITEM(RHT_GERUDO_TRAINING_GROUNDS_HEART) RANDO_ENUM_ITEM(RHT_GANONS_CASTLE_HEART) +// Silver Shuffle +RANDO_ENUM_ITEM(RHT_DODONGOS_CAVERN_SILVER) +RANDO_ENUM_ITEM(RHT_SHADOW_TEMPLE_SILVER) +RANDO_ENUM_ITEM(RHT_SPIRIT_TEMPLE_SILVER) +RANDO_ENUM_ITEM(RHT_BOTW_SILVER) +RANDO_ENUM_ITEM(RHT_ICE_CAVERN_SILVER) +RANDO_ENUM_ITEM(RHT_GTG_SILVER) +RANDO_ENUM_ITEM(RHT_GANONS_CASTLE_SILVER) // Fairy Shuffle RANDO_ENUM_ITEM(RHT_SFM_FAIRY_GROTTO_FAIRY) RANDO_ENUM_ITEM(RHT_ZR_FAIRY_GROTTO_FAIRY) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h index ce6e94a2c0..50ee49da5e 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerInf.h @@ -1978,6 +1978,163 @@ RANDO_ENUM_ITEM(RAND_INF_GERUDO_TRAINING_GROUND_MQ_WONDER_EYE_STATUE) RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_WONDER_SHADOW_TRIAL) // End Wonder Items +// Start Silver Rupees +RANDO_ENUM_ITEM(RAND_INF_RC_SHADOW_N_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_RC_SHADOW_TALL_BLOCK_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_RC_SHADOW_N_NOOK_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_W_NOOK_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_S_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_N_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_S_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_BEAMOS_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_E_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_W_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_PLATFORM_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_E_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_FLOOR_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_W_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_AIRBORNE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_W_HIGH_CHILD_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_W_LOW_CHILD_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_E_LOW_CHILD_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_E_HIGH_CHILD_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_TORCH_CHILD_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_NEAR_LIGHT_SUN_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_AIRBORNE_SUN_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MID_PLATFORM_SUN_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_NEAR_CHEST_SUN_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_NEAR_DOOR_SUN_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_NW_BOULDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_SW_BOULDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_SE_BOULDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_NE_BOULDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_AIRBORNE_BOULDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_BOTW_B1_LADDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_BOTW_B2_LADDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_BOTW_B3_LADDER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_BOTW_NW_OOZE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_BOTW_SE_OOZE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_ICICLES_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_W_INNER_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_OUTER_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_E_INNER_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_AIRBORNE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_NEAR_FIRE_BLOCK_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_LOWER_BLOCK_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_NEAR_BLOCK_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_FROZEN_BLOCK_SILVER) +RANDO_ENUM_ITEM(RAND_INF_ICE_CAVERN_NEAR_GS_BLOCK_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_FIRE_WALL_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_LOWER_BOULDER_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_TARGET_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_JUMPDOWN_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_UPPER_BOULDER_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_NEAR_SWITCH_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_NEAR_BARRED_DOOR_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_FIRE_RING_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_UPPER_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_UNDER_LEDGE_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MIDDLE_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_ABOVE_TARGET_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_LEFT_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_UNDER_TARGET_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_RIGHT_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_OUTER_RIGHT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_OUTER_LEFT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_UPPER_LIGHT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_INNER_RIGHT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_INNER_LEFT_LIGHT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_LARGE_PLATFORM_FOREST_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_SOT_BLOCK_FOREST_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_SMALL_PLATFORM_FOREST_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_UNDER_LEDGE_FOREST_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_ON_TARGET_FOREST_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_TORCH_SLUG_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_FLAME_JETS_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_DISTANT_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_CLOSE_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_GANONS_CASTLE_UNDER_PILLAR_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_AIRBORNE_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_NEAR_DOORMAT_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_LOWER_MIDDLE_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_CORNER_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_NEAR_BARRED_DOOR_SPIRIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_DODONGOS_CAVERN_MQ_BEAMOS_SILVER) +RANDO_ENUM_ITEM(RAND_INF_DODONGOS_CAVERN_MQ_1F_CRATE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_DODONGOS_CAVERN_MQ_LOWER_2F_CRATE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_DODONGOS_CAVERN_MQ_VINES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_DODONGOS_CAVERN_MQ_UPPER_2F_CRATE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_W_NOOK_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_TALL_BLOCK_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_NE_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_S_UNDER_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_N_NOOK_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_W_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_HIGH_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_HIGHEST_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_N_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_E_PIT_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_W_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_SW_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_NW_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_S_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_INNER_NE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_SE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_OUTSIDE_CIRCLE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_OUTER_NE_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_E_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_SOT_BLOCK_INVISIBLE_BLADE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_PLATFORM_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_W_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_W_AIRBORNE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_N_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_CENTRAL_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_CENTRAL_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_S_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_INSIDE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_E_AIRBORNE_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SHADOW_MQ_E_TARGET_SPIKES_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_STAIRS_LOBBY_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_E_BOULDER_LOBBY_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_W_BOULDER_LOBBY_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_CORNER_LOBBY_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_JET_LOBBY_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_LOWEST_WALL_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_MID_LOW_WALL_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_MID_HIGH_WALL_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_HIGHEST_WALL_SILVER) +RANDO_ENUM_ITEM(RAND_INF_SPIRIT_MQ_MIDDLE_WALL_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_ICICLES_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_JUMPDOWN_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_HIGH_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_FREEZARD_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_PIT_SLOPE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_NEAR_SWITCH_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_FAR_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_MIDDLE_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_SILVER_LAVA_4) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_NEAR_MAZE_LEDGE_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_NEAR_LIT_TORCH_LAVA_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_BACK_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_MIDDLE_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GTG_MQ_FRONT_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_UNDER_PILLAR_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_NEAR_TARGET_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_ON_PILLAR_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_LAUNCH_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_JET_PLATFORM_FIRE_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_IN_HOLE_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_AIRBORNE_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_FROZEN_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_OVER_PIT_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_NOOK_WATER_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_BOMB_FLOWER_SHADOW_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_NEAR_TORCH_SHADOW_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_BEAMOS_PLATFORM_SHADOW_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_GUILLOTINE_SHADOW_SILVER) +RANDO_ENUM_ITEM(RAND_INF_GANONS_CASTLE_MQ_MOVING_PLATFORM_SHADOW_SILVER) +// End Silver Rupees + RANDO_ENUM_ITEM(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_1) RANDO_ENUM_ITEM(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_2) RANDO_ENUM_ITEM(RAND_INF_SFM_FAIRY_GROTTO_FAIRY_3) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h index 83316836af..1456652c74 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerMiscEnums.h @@ -127,6 +127,7 @@ RANDO_ENUM_ITEM(RCTYPE_OCARINA) // Ocarina locations RANDO_ENUM_ITEM(RCTYPE_BEEHIVE) // Beehives RANDO_ENUM_ITEM(RCTYPE_FISH) // Fishes RANDO_ENUM_ITEM(RCTYPE_FREESTANDING) // Freestanding rupees and hearts +RANDO_ENUM_ITEM(RCTYPE_SILVER) // Silver rupees RANDO_ENUM_ITEM(RCTYPE_FOUNTAIN_FAIRY) // Fairies in Fountains RANDO_ENUM_ITEM(RCTYPE_STONE_FAIRY) // Fairies from Gossip Stones RANDO_ENUM_ITEM(RCTYPE_BEAN_FAIRY) // Fairies from Beans diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h index bb3c95e00c..d81a554b34 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h @@ -423,6 +423,14 @@ RANDO_ENUM_ITEM(RO_SHUFFLE_WONDER_ITEMS_OVERWORLD) RANDO_ENUM_ITEM(RO_SHUFFLE_WONDER_ITEMS_ALL) RANDO_ENUM_END(RandoOptionWonderItems) +// Shuffle Silver settings (off, on, wallet, start with) +RANDO_ENUM_BEGIN(RandoOptionSilver) +RANDO_ENUM_ITEM(RO_SHUFFLE_SILVER_OFF) +RANDO_ENUM_ITEM(RO_SHUFFLE_SILVER_ON) +RANDO_ENUM_ITEM(RO_SHUFFLE_SILVER_WALLET) +RANDO_ENUM_ITEM(RO_SHUFFLE_SILVER_STARTWITH) +RANDO_ENUM_END(RandoOptionSilver) + // Shuffle Pots settings (off, dungeons, overworld, all) RANDO_ENUM_BEGIN(RandoOptionShufflePots) RANDO_ENUM_ITEM(RO_SHUFFLE_POTS_OFF) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h index a3924e2d56..65331ad241 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerRegion.h @@ -842,8 +842,11 @@ RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_LOWER_HUGE_PIT_DOOR_LEDGE) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_STONE_UMBRELLA) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_STONE_UMBRELLA_UPPER) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_INVISIBLE_SPINNING_BLADES) -RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_INVISIBLE_SPIKES) -RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_INVISIBLE_SPIKES_PLATFORM) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_FLOOR_SPIKES_S_DOOR) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_FLOOR_SPIKES_W_DOOR) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_FLOOR_SPIKES_ROOM) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_SPIKES_CORNER_PLATFORM) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_SPIKES_DOOR_PLATFORM) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_SKULL_JAR) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_UPPER_WIND_TUNNEL) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_LOWER_WIND_TUNNEL) @@ -883,8 +886,12 @@ RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_LOWER_HUGE_PIT_DOOR_LEDGE) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_STONE_UMBRELLA_ROOM) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_UPPER_STONE_UMBRELLA) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_S_DOOR) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_W_DOOR) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_ROOM) -RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_FLOOR_SPIKES_PLATFORM) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_SPIKES_CORNER_PLATFORM) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_SPIKES_GLASS_PLATFORMS) +RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_SPIKES_DOOR_PLATFORM) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_STALFOS_ROOM) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_UPPER_WIND_TUNNEL) RANDO_ENUM_ITEM(RR_SHADOW_TEMPLE_MQ_LOWER_WIND_TUNNEL) @@ -923,6 +930,7 @@ RANDO_ENUM_ITEM(RR_BOTW_B3_OOZE) RANDO_ENUM_ITEM(RR_BOTW_B3_BOMB_FLOWERS) RANDO_ENUM_ITEM(RR_BOTW_B3_BLOCKED_GRASS) RANDO_ENUM_ITEM(RR_BOTW_B3_CHEST_AREA) +RANDO_ENUM_ITEM(RR_BOTW_LADDER_DOOR) RANDO_ENUM_ITEM(RR_BOTW_B3_PLATFORM) RANDO_ENUM_ITEM(RR_BOTW_MQ_PERIMETER) @@ -946,7 +954,7 @@ RANDO_ENUM_ITEM(RR_ICE_CAVERN_HUB) RANDO_ENUM_ITEM(RR_ICE_CAVERN_MAP_ROOM) RANDO_ENUM_ITEM(RR_ICE_CAVERN_COMPASS_ROOM) RANDO_ENUM_ITEM(RR_ICE_CAVERN_BLOCK_ROOM) -RANDO_ENUM_ITEM(RR_ICE_CAVERN_BLOCK_ROOM_BLUE_FIRE) +RANDO_ENUM_ITEM(RR_ICE_CAVERN_BLOCK_ROOM_NOOKS) RANDO_ENUM_ITEM(RR_ICE_CAVERN_AFTER_BLOCK_ROOM) RANDO_ENUM_ITEM(RR_ICE_CAVERN_BEFORE_FINAL_ROOM) RANDO_ENUM_ITEM(RR_ICE_CAVERN_FINAL_ROOM) @@ -1009,7 +1017,7 @@ RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MAIN) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_DEKU_SCRUBS) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_FOREST_TRIAL_WOLFOS_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM) -RANDO_ENUM_ITEM(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_END) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_MIDDLE) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_FOREST_TRIAL_BEAMOS_ROOM_FINAL_DOOR) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_FOREST_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_FIRE_TRIAL_OPEN_DOOR) @@ -1054,13 +1062,15 @@ RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_TARGET_DOOR) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_FIRE_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_WATER_TRIAL_GEYSER_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_HIGH) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_WATER_TRIAL_BLOCK_ROOM_END) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_WATER_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_CHEST_PLATFORM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_MOVING_PLATFORM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_TORCH) -RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FAR_SIDE) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BEAMOS_CHEST) +RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_BARRED_DOOR) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_FINAL_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM) RANDO_ENUM_ITEM(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_BEFORE_SWITCH) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h index 700a5afd74..a987d082b3 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h @@ -294,6 +294,7 @@ RANDO_ENUM_ITEM(RSK_SHUFFLE_DEKU_STICK_BAG) RANDO_ENUM_ITEM(RSK_SHUFFLE_DEKU_NUT_BAG) RANDO_ENUM_ITEM(RSK_SHUFFLE_FREESTANDING) RANDO_ENUM_ITEM(RSK_SHUFFLE_WONDER_ITEMS) +RANDO_ENUM_ITEM(RSK_SHUFFLE_SILVER) RANDO_ENUM_ITEM(RSK_SHUFFLE_FOUNTAIN_FAIRIES) RANDO_ENUM_ITEM(RSK_SHUFFLE_STONE_FAIRIES) RANDO_ENUM_ITEM(RSK_SHUFFLE_BEAN_FAIRIES) diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp index 44b9e75d3a..0f587596e0 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.cpp @@ -179,6 +179,8 @@ void RandomizerCheckObjects::UpdateImGuiVisibility() { ((CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), RO_SHUFFLE_FREESTANDING_OFF) == RO_SHUFFLE_FREESTANDING_DUNGEONS) && RandomizerCheckObjects::AreaIsDungeon(location.GetArea()))) && + (location.GetRCType() != RCTYPE_SILVER || + CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleSilver"), RO_GENERIC_NO)) && (location.GetRCType() != RCTYPE_BEEHIVE || CVarGetInteger(CVAR_RANDOMIZER_SETTING("ShuffleBeehives"), RO_GENERIC_NO)) && (location.GetRCType() != RCTYPE_COW || diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h index 9355ca322a..21c7558d4d 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_objects.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_objects.h @@ -1,6 +1,6 @@ #pragma once -#include "randomizerTypes.h" +#include "randomizerEnums.h" #include "z64scene.h" #include #include diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp index 8cb108c721..fd0c48d749 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.cpp @@ -2,6 +2,8 @@ #include "randomizer_entrance_tracker.h" #include "randomizer_item_tracker.h" #include "randomizerTypes.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" +#include "soh/Enhancements/randomizer/static_data.h" #include "soh/OTRGlobals.h" #include "soh/SaveManager.h" #include "soh/ResourceManagerHelpers.h" @@ -67,6 +69,7 @@ bool showBeehives; bool showCows; bool showOverworldFreestanding; bool showDungeonFreestanding; +bool showSilver; bool showAdultTrade; bool showKokiriSword; bool showMasterSword; @@ -358,6 +361,9 @@ std::map MapRGtoRandomizerCheckArea = { { RG_ICE_CAVERN_MAP, RCAREA_ICE_CAVERN } }; +// In the case that we get an excess key or silver rupee, it spoils the MQ status +// because it is not turned into a blue rupee as excess. +// For keyrings, we can count the keys on the viewmodel void SpoilAreaFromCheck(RandomizerCheck rc) { Rando::Location* loc = Rando::StaticData::GetLocation(rc); Rando::ItemLocation* itemLoc = Rando::Context::GetInstance()->GetItemLocation(rc); @@ -367,11 +373,177 @@ void SpoilAreaFromCheck(RandomizerCheck rc) { SetAreaSpoiled(area); } } + if (itemLoc->GetPlacedItem().GetItemType() == ItemType::ITEMTYPE_SILVER) { + if (!Rando::StaticData::constantSilvers.contains(itemLoc->GetPlacedRandomizerGet()) && + !IsAreaSpoiled(Rando::StaticData::silverToArea[itemLoc->GetPlacedRandomizerGet()])) { + SetAreaSpoiled(Rando::StaticData::silverToArea[itemLoc->GetPlacedRandomizerGet()]); + } else if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) == + RO_SHUFFLE_SILVER_ON) { + switch (itemLoc->GetPlacedRandomizerGet()) { + case RG_SHADOW_SILVER_SPIKES: + if (*Randomizer::SilverFieldFromSaveContext(&gSaveContext, itemLoc->GetPlacedRandomizerGet()) >= + 6) { + SetAreaSpoiled(RCAREA_SHADOW_TEMPLE); + } + break; + case RG_GTG_SILVER_LAVA: + if (*Randomizer::SilverFieldFromSaveContext(&gSaveContext, itemLoc->GetPlacedRandomizerGet()) >= + 6) { + SetAreaSpoiled(RCAREA_GERUDO_TRAINING_GROUND); + } + break; + case RG_GTG_SILVER_WATER: + if (*Randomizer::SilverFieldFromSaveContext(&gSaveContext, itemLoc->GetPlacedRandomizerGet()) >= + 4) { + SetAreaSpoiled(RCAREA_GERUDO_TRAINING_GROUND); + } + break; + default: + break; + } + } + } else if (itemLoc->GetPlacedItem().GetItemType() == ItemType::ITEMTYPE_SMALLKEY) { + switch (itemLoc->GetPlacedRandomizerGet()) { + case RG_FOREST_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::FOREST_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) >= 6) { + SetAreaSpoiled(RCAREA_FOREST_TEMPLE); + } + break; + case RG_FIRE_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::FIRE_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) >= 6) { + SetAreaSpoiled(RCAREA_FIRE_TEMPLE); + } + break; + case RG_WATER_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::WATER_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) >= 3) { + SetAreaSpoiled(RCAREA_WATER_TEMPLE); + } + break; + case RG_SPIRIT_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::SPIRIT_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) >= 6) { + SetAreaSpoiled(RCAREA_SPIRIT_TEMPLE); + } + break; + case RG_SHADOW_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::SHADOW_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) >= 6) { + SetAreaSpoiled(RCAREA_SHADOW_TEMPLE); + } + break; + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::BOTTOM_OF_THE_WELL) + ->GetTotalSmallKeys(&gSaveContext) >= 3) { + SetAreaSpoiled(RCAREA_BOTTOM_OF_THE_WELL); + } + break; + case RG_GERUDO_TRAINING_GROUND_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::GERUDO_TRAINING_GROUND) + ->GetTotalSmallKeys(&gSaveContext) >= 4) { + SetAreaSpoiled(RCAREA_GERUDO_TRAINING_GROUND); + } + break; + case RG_FOREST_TEMPLE_KEY_RING: + SetAreaSpoiled(RCAREA_FOREST_TEMPLE); + break; + case RG_FIRE_TEMPLE_KEY_RING: + SetAreaSpoiled(RCAREA_FIRE_TEMPLE); + break; + case RG_WATER_TEMPLE_KEY_RING: + SetAreaSpoiled(RCAREA_WATER_TEMPLE); + break; + case RG_SPIRIT_TEMPLE_KEY_RING: + SetAreaSpoiled(RCAREA_SPIRIT_TEMPLE); + break; + case RG_SHADOW_TEMPLE_KEY_RING: + SetAreaSpoiled(RCAREA_SHADOW_TEMPLE); + break; + case RG_BOTTOM_OF_THE_WELL_KEY_RING: + SetAreaSpoiled(RCAREA_BOTTOM_OF_THE_WELL); + break; + case RG_GERUDO_TRAINING_GROUND_KEY_RING: + SetAreaSpoiled(RCAREA_GERUDO_TRAINING_GROUND); + break; + default: + break; + } + } if (!IsAreaSpoiled(loc->GetArea())) { SetAreaSpoiled(loc->GetArea()); } } +void SpoilAreaFromCantObtain(RandomizerGet rg) { + // only spoil if it wouldn't transform anyway, in case someone manages to glitch this value + switch (rg) { + case RG_FOREST_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::FOREST_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) < 6) { + SetAreaSpoiled(RCAREA_FOREST_TEMPLE); + } + break; + case RG_FIRE_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::FIRE_TEMPLE)->GetTotalSmallKeys(&gSaveContext) < + 8) { + SetAreaSpoiled(RCAREA_FIRE_TEMPLE); + } + break; + case RG_WATER_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::WATER_TEMPLE)->GetTotalSmallKeys(&gSaveContext) < + 6) { + SetAreaSpoiled(RCAREA_WATER_TEMPLE); + } + break; + case RG_SPIRIT_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::SPIRIT_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) < 7) { + SetAreaSpoiled(RCAREA_SPIRIT_TEMPLE); + } + break; + case RG_SHADOW_TEMPLE_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::SHADOW_TEMPLE) + ->GetTotalSmallKeys(&gSaveContext) < 6) { + SetAreaSpoiled(RCAREA_SHADOW_TEMPLE); + } + break; + case RG_BOTTOM_OF_THE_WELL_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::BOTTOM_OF_THE_WELL) + ->GetTotalSmallKeys(&gSaveContext) < 3) { + SetAreaSpoiled(RCAREA_BOTTOM_OF_THE_WELL); + } + break; + case RG_GERUDO_TRAINING_GROUND_SMALL_KEY: + if (OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::GERUDO_TRAINING_GROUND) + ->GetTotalSmallKeys(&gSaveContext) < 9) { + SetAreaSpoiled(RCAREA_GERUDO_TRAINING_GROUND); + } + break; + case RG_SHADOW_SILVER_SPIKES: + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) == RO_SHUFFLE_SILVER_ON && + *Randomizer::SilverFieldFromSaveContext(&gSaveContext, rg) < 10) { + SetAreaSpoiled(RCAREA_SHADOW_TEMPLE); + } + break; + case RG_GTG_SILVER_LAVA: + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) == RO_SHUFFLE_SILVER_ON && + *Randomizer::SilverFieldFromSaveContext(&gSaveContext, rg) < 6) { + SetAreaSpoiled(RCAREA_GERUDO_TRAINING_GROUND); + } + break; + case RG_GTG_SILVER_WATER: + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) == RO_SHUFFLE_SILVER_ON && + *Randomizer::SilverFieldFromSaveContext(&gSaveContext, rg) < 5) { + SetAreaSpoiled(RCAREA_GERUDO_TRAINING_GROUND); + } + break; + default: + return; + } +} + void RecalculateAllAreaTotals() { for (auto& [rcArea, checks] : checksByArea) { if (rcArea == RCAREA_INVALID) { @@ -629,6 +801,7 @@ void CheckTrackerLoadGame(int32_t fileNum) { } for (int i = RCAREA_KOKIRI_FOREST; i < RCAREA_INVALID; i++) { if (!IsAreaSpoiled(static_cast(i)) && + (RandomizerCheckObjects::AreaIsOverworld(static_cast(i)) || !IS_RANDO || OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_NONE || (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == @@ -905,11 +1078,10 @@ void CheckTrackerFlagSet(int16_t flagType, int32_t flag) { for (auto& loc : Rando::StaticData::GetLocationTable()) { if ((!IS_RANDO && ((loc.GetQuest() == RCQUEST_MQ && !IS_MASTER_QUEST) || (loc.GetQuest() == RCQUEST_VANILLA && IS_MASTER_QUEST))) || - (IS_RANDO && - !(OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc.GetScene()) == nullptr) && - ((OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc.GetScene())->IsMQ() && + (IS_RANDO && !(OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(loc.GetScene()) == nullptr) && + ((OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(loc.GetScene())->IsMQ() && loc.GetQuest() == RCQUEST_VANILLA) || - OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(loc.GetScene())->IsVanilla() && + OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(loc.GetScene())->IsVanilla() && loc.GetQuest() == RCQUEST_MQ))) { continue; } @@ -1044,9 +1216,17 @@ bool IsAreaSpoiled(RandomizerCheckArea rcArea) { return areasSpoiled & (1 << rcArea); } +// we don't care how many silvers for this check, only that all possible silver items are known +bool AreAllSilversSpoiled() { + return IsAreaSpoiled(RCAREA_DODONGOS_CAVERN) && IsAreaSpoiled(RCAREA_BOTTOM_OF_THE_WELL) && + IsAreaSpoiled(RCAREA_GANONS_CASTLE) && IsAreaSpoiled(RCAREA_SHADOW_TEMPLE) && + IsAreaSpoiled(RCAREA_SPIRIT_TEMPLE) && IsAreaSpoiled(RCAREA_ICE_CAVERN); +} + void SetAreaSpoiled(RandomizerCheckArea rcArea) { areasSpoiled |= (1 << rcArea); SaveManager::Instance->SaveSection(gSaveContext.fileNum, sectionId, true); + RefreshItemTrackerMainWindow(); } void InternalRecalculateAvailableChecks(RandomizerRegion startingRegion, RandoAgeTime startingAgeTime); @@ -1325,8 +1505,7 @@ void CheckTrackerWindow::DrawElement() { areaTotalsTooltipSS << "Checked / Total"; if (showVOrMQ && RandomizerCheckObjects::AreaIsDungeon(rcArea)) { - if (OTRGlobals::Instance->gRandoContext->GetDungeons() - ->GetDungeonFromScene(DungeonSceneLookupByArea(rcArea)) + if (OTRGlobals::Instance->gRandoContext->GetDungeonFromScene(DungeonSceneLookupByArea(rcArea)) ->IsMQ()) { areaTotalsSS << " - MQ"; } else { @@ -1701,6 +1880,8 @@ void LoadSettings() { showDungeonFreestanding = false; break; } + + showSilver = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER); } else { // Vanilla showOverworldFreestanding = false; showDungeonFreestanding = true; @@ -1796,6 +1977,7 @@ bool IsCheckShuffled(RandomizerCheck rc) { (loc->GetRCType() != RCTYPE_FREESTANDING || (showOverworldFreestanding && RandomizerCheckObjects::AreaIsOverworld(loc->GetArea())) || (showDungeonFreestanding && RandomizerCheckObjects::AreaIsDungeon(loc->GetArea()))) && + (loc->GetRCType() != RCTYPE_SILVER || showSilver) && (loc->GetRCType() != RCTYPE_ADULT_TRADE || showAdultTrade || rc == RC_KAK_ANJU_AS_ADULT || // adult trade checks that are always shuffled rc == RC_DMT_TRADE_CLAIM_CHECK // even when shuffle adult trade is off diff --git a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h index 1edd0b0cea..f2fe1d0b1b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_check_tracker.h @@ -59,6 +59,8 @@ void UpdateAllOrdering(); void UpdateAllAreas(); void RecalculateAllAreaTotals(); void SpoilAreaFromCheck(RandomizerCheck rc); +void SpoilAreaFromCantObtain(RandomizerGet rg); void RecalculateAvailableChecks(RandomizerRegion startingRegion = RR_ROOT, RandoAgeTime startingAgeTime = RAT_NONE); void LoadFromPreset(const nlohmann::json& info); +bool AreAllSilversSpoiled(); } // namespace CheckTracker diff --git a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h index dfc3f010ef..b0d3eece86 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_entrance_tracker.h @@ -9,7 +9,7 @@ #include #include #include -#include "randomizerTypes.h" +#include "randomizerEnums.h" typedef enum { // ENTRANCE_GROUP_NO_GROUP, diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp index 5224974afb..49aad6c646 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.cpp @@ -9,11 +9,16 @@ #include "randomizer_check_tracker.h" #include "randomizer_item_tracker.h" #include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/randomizer/dungeon.h" +#include "soh/Enhancements/randomizer/item.h" +#include "soh/Enhancements/randomizer/randomizerEnums.h" #include "soh/OTRGlobals.h" #include "soh/ResourceManagerHelpers.h" #include "soh/SaveManager.h" #include "soh/SohGui/SohGui.hpp" #include "soh/SohGui/SohMenu.h" +#include "ShuffleSilver.h" +#include "static_data.h" #include "soh/SohGui/UIWidgets.hpp" #include "soh/util.h" #include "soh/Enhancements/randomizer/randomizer.h" @@ -59,6 +64,7 @@ static WidgetInfo bossSoulsTracking; static WidgetInfo jabberNutsTracking; static WidgetInfo ocarinaButtonTracking; static WidgetInfo overworldKeysTracking; +static WidgetInfo silverRupeeTracking; static WidgetInfo fishingPoleTracking; static WidgetInfo personalNotesWiget; static WidgetInfo hookshotIdentWidget; @@ -69,166 +75,204 @@ extern std::shared_ptr mSohMenu; } std::vector inventoryItems = { - ITEM_TRACKER_ITEM(ITEM_STICK, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_NUT, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_BOMB, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_BOW, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_ARROW_FIRE, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_DINS_FIRE, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_SLINGSHOT, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_OCARINA_FAIRY, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_BOMBCHU, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_HOOKSHOT, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_ARROW_ICE, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_FARORES_WIND, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_BOOMERANG, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_LENS, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_BEAN, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_HAMMER, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_ARROW_LIGHT, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_NAYRUS_LOVE, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_BOTTLE, 0, DrawBottle), ITEM_TRACKER_ITEM(ITEM_BOTTLE, 1, DrawBottle), - ITEM_TRACKER_ITEM(ITEM_BOTTLE, 2, DrawBottle), ITEM_TRACKER_ITEM(ITEM_BOTTLE, 3, DrawBottle), - ITEM_TRACKER_ITEM(ITEM_POCKET_EGG, 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_MASK_KEATON, 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_STICK, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_NUT, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_BOMB, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_BOW, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_ARROW_FIRE, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_DINS_FIRE, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_SLINGSHOT, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_OCARINA_FAIRY, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_BOMBCHU, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_HOOKSHOT, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_ARROW_ICE, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_FARORES_WIND, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_BOOMERANG, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_LENS, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_BEAN, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_HAMMER, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_ARROW_LIGHT, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_NAYRUS_LOVE, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_BOTTLE, "", 0, DrawBottle), ITEM_TRACKER_ITEM(ITEM_BOTTLE, "", 1, DrawBottle), + ITEM_TRACKER_ITEM(ITEM_BOTTLE, "", 2, DrawBottle), ITEM_TRACKER_ITEM(ITEM_BOTTLE, "", 3, DrawBottle), + ITEM_TRACKER_ITEM(ITEM_POCKET_EGG, "", 0, DrawItem), ITEM_TRACKER_ITEM(ITEM_MASK_KEATON, "", 0, DrawItem), }; std::vector equipmentItems = { - ITEM_TRACKER_ITEM(ITEM_SWORD_KOKIRI, 1 << 0, DrawEquip), ITEM_TRACKER_ITEM(ITEM_SWORD_MASTER, 1 << 1, DrawEquip), - ITEM_TRACKER_ITEM(ITEM_SWORD_BGS, 1 << 2, DrawEquip), ITEM_TRACKER_ITEM(ITEM_TUNIC_KOKIRI, 1 << 8, DrawEquip), - ITEM_TRACKER_ITEM(ITEM_TUNIC_GORON, 1 << 9, DrawEquip), ITEM_TRACKER_ITEM(ITEM_TUNIC_ZORA, 1 << 10, DrawEquip), - ITEM_TRACKER_ITEM(ITEM_SHIELD_DEKU, 1 << 4, DrawEquip), ITEM_TRACKER_ITEM(ITEM_SHIELD_HYLIAN, 1 << 5, DrawEquip), - ITEM_TRACKER_ITEM(ITEM_SHIELD_MIRROR, 1 << 6, DrawEquip), ITEM_TRACKER_ITEM(ITEM_BOOTS_KOKIRI, 1 << 12, DrawEquip), - ITEM_TRACKER_ITEM(ITEM_BOOTS_IRON, 1 << 13, DrawEquip), ITEM_TRACKER_ITEM(ITEM_BOOTS_HOVER, 1 << 14, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_SWORD_KOKIRI, "", 1 << 0, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_SWORD_MASTER, "", 1 << 1, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_SWORD_BGS, "", 1 << 2, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_TUNIC_KOKIRI, "", 1 << 8, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_TUNIC_GORON, "", 1 << 9, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_TUNIC_ZORA, "", 1 << 10, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_SHIELD_DEKU, "", 1 << 4, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_SHIELD_HYLIAN, "", 1 << 5, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_SHIELD_MIRROR, "", 1 << 6, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_BOOTS_KOKIRI, "", 1 << 12, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_BOOTS_IRON, "", 1 << 13, DrawEquip), + ITEM_TRACKER_ITEM(ITEM_BOOTS_HOVER, "", 1 << 14, DrawEquip), }; std::vector miscItems = { - ITEM_TRACKER_ITEM(ITEM_BRACELET, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_SCALE_SILVER, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_WALLET_ADULT, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_HEART_CONTAINER, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_HEART_PIECE, 0, DrawItem), - ITEM_TRACKER_ITEM(ITEM_MAGIC_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM(QUEST_GERUDO_CARD, 1 << 22, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_SKULL_TOKEN, 1 << 23, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_STONE_OF_AGONY, 1 << 21, DrawQuest), + ITEM_TRACKER_ITEM(ITEM_BRACELET, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_SCALE_SILVER, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_WALLET_ADULT, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_HEART_CONTAINER, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_HEART_PIECE, "", 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_MAGIC_SMALL, "", 0, DrawItem), + ITEM_TRACKER_QUEST(QUEST_GERUDO_CARD, "", 1 << 22, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_SKULL_TOKEN, "", 1 << 23, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_STONE_OF_AGONY, "", 1 << 21, DrawQuest), }; std::vector dungeonRewardStones = { - ITEM_TRACKER_ITEM(QUEST_KOKIRI_EMERALD, 1 << 18, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_GORON_RUBY, 1 << 19, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_ZORA_SAPPHIRE, 1 << 20, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_KOKIRI_EMERALD, "", 1 << 18, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_GORON_RUBY, "", 1 << 19, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_ZORA_SAPPHIRE, "", 1 << 20, DrawQuest), }; std::vector dungeonRewardMedallions = { - ITEM_TRACKER_ITEM(QUEST_MEDALLION_FOREST, 1 << 0, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_MEDALLION_FIRE, 1 << 1, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_MEDALLION_WATER, 1 << 2, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_MEDALLION_SPIRIT, 1 << 3, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_MEDALLION_SHADOW, 1 << 4, DrawQuest), - ITEM_TRACKER_ITEM(QUEST_MEDALLION_LIGHT, 1 << 5, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_MEDALLION_FOREST, "", 1 << 0, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_MEDALLION_FIRE, "", 1 << 1, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_MEDALLION_WATER, "", 1 << 2, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_MEDALLION_SPIRIT, "", 1 << 3, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_MEDALLION_SHADOW, "", 1 << 4, DrawQuest), + ITEM_TRACKER_QUEST(QUEST_MEDALLION_LIGHT, "", 1 << 5, DrawQuest), }; std::vector dungeonRewards = {}; std::vector songItems = { - ITEM_TRACKER_ITEM(QUEST_SONG_LULLABY, 0, DrawSong), ITEM_TRACKER_ITEM(QUEST_SONG_EPONA, 0, DrawSong), - ITEM_TRACKER_ITEM(QUEST_SONG_SARIA, 0, DrawSong), ITEM_TRACKER_ITEM(QUEST_SONG_SUN, 0, DrawSong), - ITEM_TRACKER_ITEM(QUEST_SONG_TIME, 0, DrawSong), ITEM_TRACKER_ITEM(QUEST_SONG_STORMS, 0, DrawSong), - ITEM_TRACKER_ITEM(QUEST_SONG_MINUET, 0, DrawSong), ITEM_TRACKER_ITEM(QUEST_SONG_BOLERO, 0, DrawSong), - ITEM_TRACKER_ITEM(QUEST_SONG_SERENADE, 0, DrawSong), ITEM_TRACKER_ITEM(QUEST_SONG_REQUIEM, 0, DrawSong), - ITEM_TRACKER_ITEM(QUEST_SONG_NOCTURNE, 0, DrawSong), ITEM_TRACKER_ITEM(QUEST_SONG_PRELUDE, 0, DrawSong), + ITEM_TRACKER_QUEST(QUEST_SONG_LULLABY, "", 0, DrawSong), ITEM_TRACKER_QUEST(QUEST_SONG_EPONA, "", 0, DrawSong), + ITEM_TRACKER_QUEST(QUEST_SONG_SARIA, "", 0, DrawSong), ITEM_TRACKER_QUEST(QUEST_SONG_SUN, "", 0, DrawSong), + ITEM_TRACKER_QUEST(QUEST_SONG_TIME, "", 0, DrawSong), ITEM_TRACKER_QUEST(QUEST_SONG_STORMS, "", 0, DrawSong), + ITEM_TRACKER_QUEST(QUEST_SONG_MINUET, "", 0, DrawSong), ITEM_TRACKER_QUEST(QUEST_SONG_BOLERO, "", 0, DrawSong), + ITEM_TRACKER_QUEST(QUEST_SONG_SERENADE, "", 0, DrawSong), ITEM_TRACKER_QUEST(QUEST_SONG_REQUIEM, "", 0, DrawSong), + ITEM_TRACKER_QUEST(QUEST_SONG_NOCTURNE, "", 0, DrawSong), ITEM_TRACKER_QUEST(QUEST_SONG_PRELUDE, "", 0, DrawSong), }; std::vector gregItems = { - ITEM_TRACKER_ITEM(ITEM_RUPEE_GREEN, 0, DrawItem), + ITEM_TRACKER_ITEM(ITEM_RUPEE_GREEN, "", 0, DrawItem), }; std::vector triforcePieces = { - ITEM_TRACKER_ITEM(RG_TRIFORCE_PIECE, 0, DrawItem), + ITEM_TRACKER_RG(RG_TRIFORCE_PIECE, "", 0, DrawItem), }; std::vector rocsFeather = { - ITEM_TRACKER_ITEM(RG_ROCS_FEATHER, 0, DrawItem), + ITEM_TRACKER_RG(RG_ROCS_FEATHER, "", 0, DrawItem), }; std::vector swimItems = { - ITEM_TRACKER_ITEM_CUSTOM(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, ITEM_SCALE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_BRONZE_SCALE, "Swim", ITEM_SCALE_SILVER, 0, DrawItem), }; std::vector crawlItems = { - ITEM_TRACKER_ITEM(RG_CRAWL, 0, DrawItem), + ITEM_TRACKER_RG(RG_CRAWL, "", 0, DrawItem), }; std::vector climbItems = { - ITEM_TRACKER_ITEM(RG_CLIMB, 0, DrawItem), + ITEM_TRACKER_RG(RG_CLIMB, "", 0, DrawItem), }; std::vector grabItems = { - ITEM_TRACKER_ITEM(RG_POWER_BRACELET, 0, DrawItem), + ITEM_TRACKER_RG(RG_POWER_BRACELET, "", 0, DrawItem), }; std::vector openChestItems = { - ITEM_TRACKER_ITEM(RG_OPEN_CHEST, 0, DrawItem), + ITEM_TRACKER_RG(RG_OPEN_CHEST, "", 0, DrawItem), }; std::vector beanSoulItems = { - ITEM_TRACKER_ITEM_CUSTOM(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_DESERT_COLOSSUS_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_GERUDO_VALLEY_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_GRAVEYARD_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_KOKIRI_FOREST_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_LAKE_HYLIA_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_LOST_WOODS_BRIDGE_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_LOST_WOODS_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_ZORAS_RIVER_BEAN_SOUL, ITEM_BEAN, ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, "DMC", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, "DMT", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_DESERT_COLOSSUS_BEAN_SOUL, "DC", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GERUDO_VALLEY_BEAN_SOUL, "GV", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GRAVEYARD_BEAN_SOUL, "GY", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_KOKIRI_FOREST_BEAN_SOUL, "KF", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_LAKE_HYLIA_BEAN_SOUL, "LH", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_LOST_WOODS_BRIDGE_BEAN_SOUL, "LWB", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_LOST_WOODS_BEAN_SOUL, "LWT", ITEM_BEAN, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_ZORAS_RIVER_BEAN_SOUL, "ZR", ITEM_BEAN, 0, DrawItem), }; std::vector bossSoulItems = { - ITEM_TRACKER_ITEM(RG_GOHMA_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_KING_DODONGO_SOUL, 0, DrawItem), - ITEM_TRACKER_ITEM(RG_BARINADE_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_PHANTOM_GANON_SOUL, 0, DrawItem), - ITEM_TRACKER_ITEM(RG_VOLVAGIA_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_MORPHA_SOUL, 0, DrawItem), - ITEM_TRACKER_ITEM(RG_BONGO_BONGO_SOUL, 0, DrawItem), ITEM_TRACKER_ITEM(RG_TWINROVA_SOUL, 0, DrawItem), - ITEM_TRACKER_ITEM(RG_GANON_SOUL, 0, DrawItem), + ITEM_TRACKER_RG(RG_GOHMA_SOUL, "GOHMA", 0, DrawItem), + ITEM_TRACKER_RG(RG_KING_DODONGO_SOUL, "KD", 0, DrawItem), + ITEM_TRACKER_RG(RG_BARINADE_SOUL, "BARI", 0, DrawItem), + ITEM_TRACKER_RG(RG_PHANTOM_GANON_SOUL, "PG", 0, DrawItem), + ITEM_TRACKER_RG(RG_VOLVAGIA_SOUL, "VOLV", 0, DrawItem), + ITEM_TRACKER_RG(RG_MORPHA_SOUL, "MORPH", 0, DrawItem), + ITEM_TRACKER_RG(RG_BONGO_BONGO_SOUL, "BONGO", 0, DrawItem), + ITEM_TRACKER_RG(RG_TWINROVA_SOUL, "TWIN", 0, DrawItem), + ITEM_TRACKER_RG(RG_GANON_SOUL, "GANON", 0, DrawItem), }; std::vector jabbernutItems = { - ITEM_TRACKER_ITEM(RG_SPEAK_DEKU, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_GERUDO, 0, DrawItem), - ITEM_TRACKER_ITEM(RG_SPEAK_GORON, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_HYLIAN, 0, DrawItem), - ITEM_TRACKER_ITEM(RG_SPEAK_KOKIRI, 0, DrawItem), ITEM_TRACKER_ITEM(RG_SPEAK_ZORA, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPEAK_DEKU, "DEKU", ITEM_NUT, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPEAK_GERUDO, "GERUDO", ITEM_NUT, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPEAK_GORON, "GORON", ITEM_NUT, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPEAK_HYLIAN, "HYLIAN", ITEM_NUT, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPEAK_KOKIRI, "KOKIRI", ITEM_NUT, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPEAK_ZORA, "ZORA", ITEM_NUT, 0, DrawItem), }; std::vector ocarinaButtonItems = { // Hack for right now, just gonna draw ocarina buttons as ocarinas. // Will replace with other macro once we have a custom texture - ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_A_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_UP_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_DOWN_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_LEFT_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME, ITEM_OCARINA_TIME, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_OCARINA_A_BUTTON, "A", ITEM_OCARINA_TIME, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_OCARINA_C_UP_BUTTON, "C-U", ITEM_OCARINA_TIME, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_OCARINA_C_DOWN_BUTTON, "C-D", ITEM_OCARINA_TIME, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_OCARINA_C_LEFT_BUTTON, "C-L", ITEM_OCARINA_TIME, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_OCARINA_C_RIGHT_BUTTON, "C-R", ITEM_OCARINA_TIME, 0, DrawItem), }; std::vector overworldKeyItems = { // Hack for right now, just gonna overworld keys as dungeon keys. // Will replace with other macro once we have a custom texture - ITEM_TRACKER_ITEM_CUSTOM(RG_GUARD_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_MARKET_BAZAAR_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_MARKET_POTION_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_MASK_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_MARKET_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_BOMBCHU_BOWLING_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_TREASURE_CHEST_GAME_BUILDING_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_BOMBCHU_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_ALLEY_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_KAK_BAZAAR_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_KAK_POTION_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_BOSS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_GRANNYS_POTION_SHOP_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_SKULLTULA_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_IMPAS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_WINDMILL_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_KAK_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_DAMPES_HUT_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_TALONS_HOUSE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_STABLES_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_BACK_TOWER_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_HYLIA_LAB_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), - ITEM_TRACKER_ITEM_CUSTOM(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL, ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GUARD_HOUSE_KEY, "GUARD", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_MARKET_BAZAAR_KEY, "MKBAZ", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_MARKET_POTION_SHOP_KEY, "MKPOT", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_MASK_SHOP_KEY, "MASK", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_MARKET_SHOOTING_GALLERY_KEY, "MKSHO", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_BOMBCHU_BOWLING_KEY, "BOWL", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_TREASURE_CHEST_GAME_BUILDING_KEY, "TREASU", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_BOMBCHU_SHOP_KEY, "CHUSHO", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_RICHARDS_HOUSE_KEY, "RICH", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_ALLEY_HOUSE_KEY, "ALLEY", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_KAK_BAZAAR_KEY, "KAKBAZ", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_KAK_POTION_SHOP_KEY, "KAKPO", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_BOSS_HOUSE_KEY, "BOSS", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GRANNYS_POTION_SHOP_KEY, "GRANNY", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SKULLTULA_HOUSE_KEY, "SKULL", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_IMPAS_HOUSE_KEY, "IMPAS", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_WINDMILL_KEY, "WIND", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_KAK_SHOOTING_GALLERY_KEY, "KAKSHO", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_DAMPES_HUT_KEY, "DAMPES", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_TALONS_HOUSE_KEY, "TALONS", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_STABLES_KEY, "STABLE", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_BACK_TOWER_KEY, "TOWER", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_HYLIA_LAB_KEY, "LAB", ITEM_KEY_SMALL, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_FISHING_HOLE_KEY, "FISH", ITEM_KEY_SMALL, 0, DrawItem), }; -std::vector fishingPoleItems = { ITEM_TRACKER_ITEM(ITEM_FISHING_POLE, 0, DrawItem) }; +std::vector fishingPoleItems = { ITEM_TRACKER_ITEM(ITEM_FISHING_POLE, "", 0, DrawItem) }; + +std::vector silverRupeeItems = { + ITEM_TRACKER_RG_CUSTOM(RG_ICE_CAVERN_SILVER_BLADES, "ICBlad", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_ICE_CAVERN_SILVER_BLOCK, "ICBlok", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_BOTW_SILVER, "BotW", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GTG_SILVER_SLOPE, "GTGSlo", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GTG_SILVER_LAVA, "GTGLva", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GTG_SILVER_WATER, "GTGWtr", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPIRIT_SILVER_CHILD, "SpiChd", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPIRIT_SILVER_SUN, "SpiSun", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPIRIT_SILVER_BOULDERS, "SpiBol", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SHADOW_SILVER_BLADES, "ShaBla", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SHADOW_SILVER_PIT, "ShaPit", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SHADOW_SILVER_SPIKES, "ShaSpk", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GANONS_CASTLE_SILVER_LIGHT, "LhtTri", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GANONS_CASTLE_SILVER_FOREST, "ForTri", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GANONS_CASTLE_SILVER_FIRE, "FirTri", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GANONS_CASTLE_SILVER_SPIRIT, "SpiTri", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_DODONGOS_CAVERN_MQ_SILVER, "DC", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES, "ShaInv", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPIRIT_MQ_SILVER_LOBBY, "SpiLob", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_SPIRIT_MQ_SILVER_BIG_WALL, "SpiWal", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GANONS_CASTLE_MQ_SILVER_WATER, "WatTri", ITEM_RUPEE_SILVER, 0, DrawItem), + ITEM_TRACKER_RG_CUSTOM(RG_GANONS_CASTLE_MQ_SILVER_SHADOW, "ShaTri", ITEM_RUPEE_SILVER, 0, DrawItem), +}; std::vector itemTrackerDungeonsWithMapsHorizontal = { { SCENE_DEKU_TREE, { ITEM_DUNGEON_MAP, ITEM_COMPASS } }, @@ -291,122 +335,66 @@ std::map itemTrackerDungeonShortNames = { { SCENE_THIEVES_HIDEOUT, "HIDE" }, }; -std::map itemTrackerBeanShortNames = { - { RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL, "DMC" }, - { RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL, "DMT" }, - { RG_DESERT_COLOSSUS_BEAN_SOUL, "DC" }, - { RG_GERUDO_VALLEY_BEAN_SOUL, "GV" }, - { RG_GRAVEYARD_BEAN_SOUL, "GY" }, - { RG_KOKIRI_FOREST_BEAN_SOUL, "KF" }, - { RG_LAKE_HYLIA_BEAN_SOUL, "LH" }, - { RG_LOST_WOODS_BRIDGE_BEAN_SOUL, "LWB" }, - { RG_LOST_WOODS_BEAN_SOUL, "LWT" }, - { RG_ZORAS_RIVER_BEAN_SOUL, "ZR" }, -}; - -std::map itemTrackerBossShortNames = { - { RG_GOHMA_SOUL, "GOHMA" }, { RG_KING_DODONGO_SOUL, "KD" }, { RG_BARINADE_SOUL, "BARI" }, - { RG_PHANTOM_GANON_SOUL, "PG" }, { RG_VOLVAGIA_SOUL, "VOLV" }, { RG_MORPHA_SOUL, "MORPH" }, - { RG_BONGO_BONGO_SOUL, "BONGO" }, { RG_TWINROVA_SOUL, "TWIN" }, { RG_GANON_SOUL, "GANON" }, -}; - -std::map itemTrackerJabberNutShortNames = { - { RG_SPEAK_DEKU, "DEKU" }, { RG_SPEAK_GERUDO, "GERUDO" }, { RG_SPEAK_GORON, "GORON" }, - { RG_SPEAK_HYLIAN, "HYLIAN" }, { RG_SPEAK_KOKIRI, "KOKIRI" }, { RG_SPEAK_ZORA, "ZORA" }, -}; - -std::map itemTrackerOcarinaButtonShortNames = { - { RG_OCARINA_A_BUTTON, "A" }, { RG_OCARINA_C_UP_BUTTON, "C-U" }, { RG_OCARINA_C_DOWN_BUTTON, "C-D" }, - { RG_OCARINA_C_LEFT_BUTTON, "C-L" }, { RG_OCARINA_C_RIGHT_BUTTON, "C-R" }, -}; - -std::map itemTrackerOverworldKeyShortNames = { - { RG_GUARD_HOUSE_KEY, "GUARD" }, - { RG_MARKET_BAZAAR_KEY, "MKBAZ" }, - { RG_MARKET_POTION_SHOP_KEY, "MKPOT" }, - { RG_MASK_SHOP_KEY, "MASK" }, - { RG_MARKET_SHOOTING_GALLERY_KEY, "MKSHO" }, - { RG_BOMBCHU_BOWLING_KEY, "BOWL" }, - { RG_TREASURE_CHEST_GAME_BUILDING_KEY, "TREASU" }, - { RG_BOMBCHU_SHOP_KEY, "CHUSHO" }, - { RG_RICHARDS_HOUSE_KEY, "RICH" }, - { RG_ALLEY_HOUSE_KEY, "ALLEY" }, - { RG_KAK_BAZAAR_KEY, "KAKBAZ" }, - { RG_KAK_POTION_SHOP_KEY, "KAKPO" }, - { RG_BOSS_HOUSE_KEY, "BOSS" }, - { RG_GRANNYS_POTION_SHOP_KEY, "GRANNY" }, - { RG_SKULLTULA_HOUSE_KEY, "SKULL" }, - { RG_IMPAS_HOUSE_KEY, "IMPAS" }, - { RG_WINDMILL_KEY, "WIND" }, - { RG_KAK_SHOOTING_GALLERY_KEY, "KAKSHO" }, - { RG_DAMPES_HUT_KEY, "DAMPES" }, - { RG_TALONS_HOUSE_KEY, "TALONS" }, - { RG_STABLES_KEY, "STABLE" }, - { RG_BACK_TOWER_KEY, "TOWER" }, - { RG_HYLIA_LAB_KEY, "LAB" }, - { RG_FISHING_HOLE_KEY, "FISH" }, -}; - std::vector dungeonItems = {}; std::unordered_map actualItemTrackerItemMap = { - { ITEM_BOTTLE, ITEM_TRACKER_ITEM(ITEM_BOTTLE, 0, DrawItem) }, - { ITEM_BIG_POE, ITEM_TRACKER_ITEM(ITEM_BIG_POE, 0, DrawItem) }, - { ITEM_BLUE_FIRE, ITEM_TRACKER_ITEM(ITEM_BLUE_FIRE, 0, DrawItem) }, - { ITEM_BUG, ITEM_TRACKER_ITEM(ITEM_BUG, 0, DrawItem) }, - { ITEM_FAIRY, ITEM_TRACKER_ITEM(ITEM_FAIRY, 0, DrawItem) }, - { ITEM_FISH, ITEM_TRACKER_ITEM(ITEM_FISH, 0, DrawItem) }, - { ITEM_POTION_GREEN, ITEM_TRACKER_ITEM(ITEM_POTION_GREEN, 0, DrawItem) }, - { ITEM_POE, ITEM_TRACKER_ITEM(ITEM_POE, 0, DrawItem) }, - { ITEM_POTION_RED, ITEM_TRACKER_ITEM(ITEM_POTION_RED, 0, DrawItem) }, - { ITEM_POTION_BLUE, ITEM_TRACKER_ITEM(ITEM_POTION_BLUE, 0, DrawItem) }, - { ITEM_MILK_BOTTLE, ITEM_TRACKER_ITEM(ITEM_MILK_BOTTLE, 0, DrawItem) }, - { ITEM_MILK_HALF, ITEM_TRACKER_ITEM(ITEM_MILK_HALF, 0, DrawItem) }, - { ITEM_LETTER_RUTO, ITEM_TRACKER_ITEM(ITEM_LETTER_RUTO, 0, DrawItem) }, + { ITEM_BOTTLE, ITEM_TRACKER_ITEM(ITEM_BOTTLE, "", 0, DrawItem) }, + { ITEM_BIG_POE, ITEM_TRACKER_ITEM(ITEM_BIG_POE, "", 0, DrawItem) }, + { ITEM_BLUE_FIRE, ITEM_TRACKER_ITEM(ITEM_BLUE_FIRE, "", 0, DrawItem) }, + { ITEM_BUG, ITEM_TRACKER_ITEM(ITEM_BUG, "", 0, DrawItem) }, + { ITEM_FAIRY, ITEM_TRACKER_ITEM(ITEM_FAIRY, "", 0, DrawItem) }, + { ITEM_FISH, ITEM_TRACKER_ITEM(ITEM_FISH, "", 0, DrawItem) }, + { ITEM_POTION_GREEN, ITEM_TRACKER_ITEM(ITEM_POTION_GREEN, "", 0, DrawItem) }, + { ITEM_POE, ITEM_TRACKER_ITEM(ITEM_POE, "", 0, DrawItem) }, + { ITEM_POTION_RED, ITEM_TRACKER_ITEM(ITEM_POTION_RED, "", 0, DrawItem) }, + { ITEM_POTION_BLUE, ITEM_TRACKER_ITEM(ITEM_POTION_BLUE, "", 0, DrawItem) }, + { ITEM_MILK_BOTTLE, ITEM_TRACKER_ITEM(ITEM_MILK_BOTTLE, "", 0, DrawItem) }, + { ITEM_MILK_HALF, ITEM_TRACKER_ITEM(ITEM_MILK_HALF, "", 0, DrawItem) }, + { ITEM_LETTER_RUTO, ITEM_TRACKER_ITEM(ITEM_LETTER_RUTO, "", 0, DrawItem) }, - { ITEM_HOOKSHOT, ITEM_TRACKER_ITEM(ITEM_HOOKSHOT, 0, DrawItem) }, - { ITEM_LONGSHOT, ITEM_TRACKER_ITEM(ITEM_LONGSHOT, 0, DrawItem) }, + { ITEM_HOOKSHOT, ITEM_TRACKER_ITEM(ITEM_HOOKSHOT, "", 0, DrawItem) }, + { ITEM_LONGSHOT, ITEM_TRACKER_ITEM(ITEM_LONGSHOT, "", 0, DrawItem) }, - { ITEM_OCARINA_FAIRY, ITEM_TRACKER_ITEM(ITEM_OCARINA_FAIRY, 0, DrawItem) }, - { ITEM_OCARINA_TIME, ITEM_TRACKER_ITEM(ITEM_OCARINA_TIME, 0, DrawItem) }, + { ITEM_OCARINA_FAIRY, ITEM_TRACKER_ITEM(ITEM_OCARINA_FAIRY, "", 0, DrawItem) }, + { ITEM_OCARINA_TIME, ITEM_TRACKER_ITEM(ITEM_OCARINA_TIME, "", 0, DrawItem) }, - { ITEM_MAGIC_SMALL, ITEM_TRACKER_ITEM(ITEM_MAGIC_SMALL, 0, DrawItem) }, - { ITEM_MAGIC_LARGE, ITEM_TRACKER_ITEM(ITEM_MAGIC_LARGE, 0, DrawItem) }, + { ITEM_MAGIC_SMALL, ITEM_TRACKER_ITEM(ITEM_MAGIC_SMALL, "", 0, DrawItem) }, + { ITEM_MAGIC_LARGE, ITEM_TRACKER_ITEM(ITEM_MAGIC_LARGE, "", 0, DrawItem) }, - { ITEM_WALLET_ADULT, ITEM_TRACKER_ITEM(ITEM_WALLET_ADULT, 0, DrawItem) }, - { ITEM_WALLET_GIANT, ITEM_TRACKER_ITEM(ITEM_WALLET_GIANT, 0, DrawItem) }, + { ITEM_WALLET_ADULT, ITEM_TRACKER_ITEM(ITEM_WALLET_ADULT, "", 0, DrawItem) }, + { ITEM_WALLET_GIANT, ITEM_TRACKER_ITEM(ITEM_WALLET_GIANT, "", 0, DrawItem) }, - { ITEM_BRACELET, ITEM_TRACKER_ITEM(ITEM_BRACELET, 0, DrawItem) }, - { ITEM_GAUNTLETS_SILVER, ITEM_TRACKER_ITEM(ITEM_GAUNTLETS_SILVER, 0, DrawItem) }, - { ITEM_GAUNTLETS_GOLD, ITEM_TRACKER_ITEM(ITEM_GAUNTLETS_GOLD, 0, DrawItem) }, + { ITEM_BRACELET, ITEM_TRACKER_ITEM(ITEM_BRACELET, "", 0, DrawItem) }, + { ITEM_GAUNTLETS_SILVER, ITEM_TRACKER_ITEM(ITEM_GAUNTLETS_SILVER, "", 0, DrawItem) }, + { ITEM_GAUNTLETS_GOLD, ITEM_TRACKER_ITEM(ITEM_GAUNTLETS_GOLD, "", 0, DrawItem) }, - { ITEM_SCALE_SILVER, ITEM_TRACKER_ITEM(ITEM_SCALE_SILVER, 0, DrawItem) }, - { ITEM_SCALE_GOLDEN, ITEM_TRACKER_ITEM(ITEM_SCALE_GOLDEN, 0, DrawItem) }, + { ITEM_SCALE_SILVER, ITEM_TRACKER_ITEM(ITEM_SCALE_SILVER, "", 0, DrawItem) }, + { ITEM_SCALE_GOLDEN, ITEM_TRACKER_ITEM(ITEM_SCALE_GOLDEN, "", 0, DrawItem) }, - { ITEM_WEIRD_EGG, ITEM_TRACKER_ITEM(ITEM_WEIRD_EGG, 0, DrawItem) }, - { ITEM_CHICKEN, ITEM_TRACKER_ITEM(ITEM_CHICKEN, 0, DrawItem) }, - { ITEM_LETTER_ZELDA, ITEM_TRACKER_ITEM(ITEM_LETTER_ZELDA, 0, DrawItem) }, - { ITEM_MASK_KEATON, ITEM_TRACKER_ITEM(ITEM_MASK_KEATON, 0, DrawItem) }, - { ITEM_MASK_SKULL, ITEM_TRACKER_ITEM(ITEM_MASK_SKULL, 0, DrawItem) }, - { ITEM_MASK_SPOOKY, ITEM_TRACKER_ITEM(ITEM_MASK_SPOOKY, 0, DrawItem) }, - { ITEM_MASK_BUNNY, ITEM_TRACKER_ITEM(ITEM_MASK_BUNNY, 0, DrawItem) }, - { ITEM_MASK_GORON, ITEM_TRACKER_ITEM(ITEM_MASK_GORON, 0, DrawItem) }, - { ITEM_MASK_ZORA, ITEM_TRACKER_ITEM(ITEM_MASK_ZORA, 0, DrawItem) }, - { ITEM_MASK_GERUDO, ITEM_TRACKER_ITEM(ITEM_MASK_GERUDO, 0, DrawItem) }, - { ITEM_MASK_TRUTH, ITEM_TRACKER_ITEM(ITEM_MASK_TRUTH, 0, DrawItem) }, - { ITEM_SOLD_OUT, ITEM_TRACKER_ITEM(ITEM_SOLD_OUT, 0, DrawItem) }, + { ITEM_WEIRD_EGG, ITEM_TRACKER_ITEM(ITEM_WEIRD_EGG, "", 0, DrawItem) }, + { ITEM_CHICKEN, ITEM_TRACKER_ITEM(ITEM_CHICKEN, "", 0, DrawItem) }, + { ITEM_LETTER_ZELDA, ITEM_TRACKER_ITEM(ITEM_LETTER_ZELDA, "", 0, DrawItem) }, + { ITEM_MASK_KEATON, ITEM_TRACKER_ITEM(ITEM_MASK_KEATON, "", 0, DrawItem) }, + { ITEM_MASK_SKULL, ITEM_TRACKER_ITEM(ITEM_MASK_SKULL, "", 0, DrawItem) }, + { ITEM_MASK_SPOOKY, ITEM_TRACKER_ITEM(ITEM_MASK_SPOOKY, "", 0, DrawItem) }, + { ITEM_MASK_BUNNY, ITEM_TRACKER_ITEM(ITEM_MASK_BUNNY, "", 0, DrawItem) }, + { ITEM_MASK_GORON, ITEM_TRACKER_ITEM(ITEM_MASK_GORON, "", 0, DrawItem) }, + { ITEM_MASK_ZORA, ITEM_TRACKER_ITEM(ITEM_MASK_ZORA, "", 0, DrawItem) }, + { ITEM_MASK_GERUDO, ITEM_TRACKER_ITEM(ITEM_MASK_GERUDO, "", 0, DrawItem) }, + { ITEM_MASK_TRUTH, ITEM_TRACKER_ITEM(ITEM_MASK_TRUTH, "", 0, DrawItem) }, + { ITEM_SOLD_OUT, ITEM_TRACKER_ITEM(ITEM_SOLD_OUT, "", 0, DrawItem) }, - { ITEM_POCKET_EGG, ITEM_TRACKER_ITEM(ITEM_POCKET_EGG, 0, DrawItem) }, - { ITEM_POCKET_CUCCO, ITEM_TRACKER_ITEM(ITEM_POCKET_CUCCO, 0, DrawItem) }, - { ITEM_COJIRO, ITEM_TRACKER_ITEM(ITEM_COJIRO, 0, DrawItem) }, - { ITEM_ODD_MUSHROOM, ITEM_TRACKER_ITEM(ITEM_ODD_MUSHROOM, 0, DrawItem) }, - { ITEM_ODD_POTION, ITEM_TRACKER_ITEM(ITEM_ODD_POTION, 0, DrawItem) }, - { ITEM_SAW, ITEM_TRACKER_ITEM(ITEM_SAW, 0, DrawItem) }, - { ITEM_SWORD_BROKEN, ITEM_TRACKER_ITEM(ITEM_SWORD_BROKEN, 0, DrawItem) }, - { ITEM_PRESCRIPTION, ITEM_TRACKER_ITEM(ITEM_PRESCRIPTION, 0, DrawItem) }, - { ITEM_FROG, ITEM_TRACKER_ITEM(ITEM_FROG, 0, DrawItem) }, - { ITEM_EYEDROPS, ITEM_TRACKER_ITEM(ITEM_EYEDROPS, 0, DrawItem) }, - { ITEM_CLAIM_CHECK, ITEM_TRACKER_ITEM(ITEM_CLAIM_CHECK, 0, DrawItem) }, + { ITEM_POCKET_EGG, ITEM_TRACKER_ITEM(ITEM_POCKET_EGG, "", 0, DrawItem) }, + { ITEM_POCKET_CUCCO, ITEM_TRACKER_ITEM(ITEM_POCKET_CUCCO, "", 0, DrawItem) }, + { ITEM_COJIRO, ITEM_TRACKER_ITEM(ITEM_COJIRO, "", 0, DrawItem) }, + { ITEM_ODD_MUSHROOM, ITEM_TRACKER_ITEM(ITEM_ODD_MUSHROOM, "", 0, DrawItem) }, + { ITEM_ODD_POTION, ITEM_TRACKER_ITEM(ITEM_ODD_POTION, "", 0, DrawItem) }, + { ITEM_SAW, ITEM_TRACKER_ITEM(ITEM_SAW, "", 0, DrawItem) }, + { ITEM_SWORD_BROKEN, ITEM_TRACKER_ITEM(ITEM_SWORD_BROKEN, "", 0, DrawItem) }, + { ITEM_PRESCRIPTION, ITEM_TRACKER_ITEM(ITEM_PRESCRIPTION, "", 0, DrawItem) }, + { ITEM_FROG, ITEM_TRACKER_ITEM(ITEM_FROG, "", 0, DrawItem) }, + { ITEM_EYEDROPS, ITEM_TRACKER_ITEM(ITEM_EYEDROPS, "", 0, DrawItem) }, + { ITEM_CLAIM_CHECK, ITEM_TRACKER_ITEM(ITEM_CLAIM_CHECK, "", 0, DrawItem) }, }; std::vector buttonMap = { @@ -466,6 +454,31 @@ static bool presetLoaded = false; static std::unordered_map presetPos; static std::unordered_map presetSize; +void TrackSilverRupees(std::vector* trackList) { + for (auto silverRupee : silverRupeeItems) { + RandomizerGet rg = static_cast(silverRupee.id); + if ((gSaveContext.gameMode != GAMEMODE_NORMAL && silverRupee.id <= RG_GANONS_CASTLE_SILVER_SPIRIT) || + (IsSilverInPool(rg) && (Rando::StaticData::constantSilvers.contains(rg) || + CheckTracker::IsAreaSpoiled(Rando::StaticData::silverToArea[rg])))) { + trackList->push_back(silverRupee); + } + } + if (gSaveContext.gameMode == GAMEMODE_NORMAL && !CheckTracker::AreAllSilversSpoiled()) { + trackList->push_back({ (uint32_t)ITEMTYPE_SILVER, ITEM_KIND_DUMMY, "????", "ITEM_RUPEE_SILVER", + "ITEM_RUPEE_SILVER_Faded", 0, DrawItem }); + } +} + +void DrawName(std::string str, ImU32 color) { + int iconSize = CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36); + ImVec2 p = ImGui::GetCursorScreenPos(); + ImGui::SetCursorScreenPos( + ImVec2(p.x + (iconSize >> 1) - (ImGui::CalcTextSize(str.c_str()).x / 2), p.y - (iconSize + 13))); + ImGui::PushStyleColor(ImGuiCol_Text, color); + ImGui::Text("%s", str.c_str()); + ImGui::PopStyleColor(); +} + void ItemTrackerOnFrame() { if (notesNeedSave && notesIdleFrames <= notesMaxIdleFrames) { notesIdleFrames++; @@ -478,14 +491,17 @@ bool IsValidSaveFile() { } bool HasSong(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_QUEST); return GameInteractor::IsSaveLoaded() ? ((1 << item.id) & gSaveContext.inventory.questItems) : false; } bool HasQuestItem(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_QUEST); return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.questItems) : false; } bool HasEquipment(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_ITEM); return GameInteractor::IsSaveLoaded() ? (item.data & gSaveContext.inventory.equipment) : false; } @@ -506,138 +522,169 @@ ItemTrackerNumbers GetItemCurrentAndMax(ItemTrackerItem item) { result.maxCapacity = 0; result.currentAmmo = 0; - switch (item.id) { - case ITEM_STICK: - result.currentCapacity = CUR_CAPACITY(UPG_STICKS); - result.maxCapacity = 30; - result.currentAmmo = AMMO(ITEM_STICK); - break; - case ITEM_NUT: - result.currentCapacity = CUR_CAPACITY(UPG_NUTS); - result.maxCapacity = 40; - result.currentAmmo = AMMO(ITEM_NUT); - break; - case ITEM_BOMB: - result.currentCapacity = CUR_CAPACITY(UPG_BOMB_BAG); - result.maxCapacity = 40; - result.currentAmmo = AMMO(ITEM_BOMB); - break; - case ITEM_BOW: - result.currentCapacity = CUR_CAPACITY(UPG_QUIVER); - result.maxCapacity = 50; - result.currentAmmo = AMMO(ITEM_BOW); - break; - case ITEM_SLINGSHOT: - result.currentCapacity = CUR_CAPACITY(UPG_BULLET_BAG); - result.maxCapacity = 50; - result.currentAmmo = AMMO(ITEM_SLINGSHOT); - break; - case ITEM_WALLET_ADULT: - case ITEM_WALLET_GIANT: - result.currentCapacity = - IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET) ? 0 : CUR_CAPACITY(UPG_WALLET); - result.maxCapacity = - IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INCLUDE_TYCOON_WALLET) ? 999 - : 500; - result.currentAmmo = gSaveContext.rupees; - break; - case ITEM_BOMBCHU: { - auto bombchuBag = RAND_GET_OPTION(RSK_BOMBCHU_BAG); + if (item.kind == ITEM_KIND_ITEM) { + switch (item.id) { + case ITEM_STICK: + result.currentCapacity = CUR_CAPACITY(UPG_STICKS); + result.maxCapacity = 30; + result.currentAmmo = AMMO(ITEM_STICK); + break; + case ITEM_NUT: + result.currentCapacity = CUR_CAPACITY(UPG_NUTS); + result.maxCapacity = 40; + result.currentAmmo = AMMO(ITEM_NUT); + break; + case ITEM_BOMB: + result.currentCapacity = CUR_CAPACITY(UPG_BOMB_BAG); + result.maxCapacity = 40; + result.currentAmmo = AMMO(ITEM_BOMB); + break; + case ITEM_BOW: + result.currentCapacity = CUR_CAPACITY(UPG_QUIVER); + result.maxCapacity = 50; + result.currentAmmo = AMMO(ITEM_BOW); + break; + case ITEM_SLINGSHOT: + result.currentCapacity = CUR_CAPACITY(UPG_BULLET_BAG); + result.maxCapacity = 50; + result.currentAmmo = AMMO(ITEM_SLINGSHOT); + break; + case ITEM_WALLET_ADULT: + case ITEM_WALLET_GIANT: + result.currentCapacity = + IS_RANDO && !Flags_GetRandomizerInf(RAND_INF_HAS_WALLET) ? 0 : CUR_CAPACITY(UPG_WALLET); + result.maxCapacity = + IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_INCLUDE_TYCOON_WALLET) + ? 999 + : 500; + result.currentAmmo = gSaveContext.rupees; + break; + case ITEM_BOMBCHU: { + auto bombchuBag = RAND_GET_OPTION(RSK_BOMBCHU_BAG); - uint8_t capacity = 0; + uint8_t capacity = 0; - if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU) { - if (bombchuBag.Is(RO_BOMBCHU_BAG_PROGRESSIVE)) { - capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity(); + if (INV_CONTENT(ITEM_BOMBCHU) == ITEM_BOMBCHU) { + if (bombchuBag.Is(RO_BOMBCHU_BAG_PROGRESSIVE)) { + capacity = OTRGlobals::Instance->gRandoContext->GetBombchuCapacity(); + } else { + capacity = 50; + } + } + + result.currentCapacity = capacity; + result.maxCapacity = 50; + result.currentAmmo = AMMO(ITEM_BOMBCHU); + break; + } + case ITEM_BEAN: + result.currentCapacity = INV_CONTENT(ITEM_BEAN) == ITEM_BEAN ? 10 : 0; + result.maxCapacity = 10; + result.currentAmmo = AMMO(ITEM_BEAN); + break; + case ITEM_HEART_CONTAINER: + result.maxCapacity = result.currentCapacity = 8; + result.currentAmmo = gSaveContext.ship.stats.heartContainers; + break; + case ITEM_HEART_PIECE: + result.maxCapacity = result.currentCapacity = 36; + result.currentAmmo = gSaveContext.ship.stats.heartPieces; + break; + case ITEM_KEY_SMALL: + // Though the ammo/capacity naming doesn't really make sense for keys, we are + // hijacking the same system to display key counts as there are enough similarities + result.currentAmmo = MAX(gSaveContext.inventory.dungeonKeys[item.data], 0); + if (item.data == SCENE_THIEVES_HIDEOUT) { + std::vector DoorFlags = THIEVES_HIDEOUT_DOOR_FLAGS; + result.currentCapacity = + Rando::FindTotalSmallKeys(&gSaveContext, SCENE_THIEVES_HIDEOUT, &DoorFlags); + result.maxCapacity = GERUDO_FORTRESS_SMALL_KEY_MAX; } else { - capacity = 50; + result.currentCapacity = OTRGlobals::Instance->gRandoContext->GetDungeons() + ->GetDungeonFromScene(item.data) + ->GetTotalSmallKeys(&gSaveContext); + switch (item.data) { + case SCENE_FOREST_TEMPLE: + result.maxCapacity = FOREST_TEMPLE_SMALL_KEY_MAX; + break; + case SCENE_FIRE_TEMPLE: + result.maxCapacity = FIRE_TEMPLE_SMALL_KEY_MAX; + if (IS_RANDO && + !(OTRGlobals::Instance->gRandoContext->GetOption(RSK_KEYSANITY) + .Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || + OTRGlobals::Instance->gRandoContext->GetOption(RSK_KEYSANITY) + .Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) || + OTRGlobals::Instance->gRandoContext->GetOption(RSK_KEYSANITY) + .Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) && + OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { + result.currentCapacity = result.currentCapacity - 1; + } + break; + case SCENE_WATER_TEMPLE: + result.maxCapacity = WATER_TEMPLE_SMALL_KEY_MAX; + break; + case SCENE_SPIRIT_TEMPLE: + result.maxCapacity = SPIRIT_TEMPLE_SMALL_KEY_MAX; + break; + case SCENE_SHADOW_TEMPLE: + result.maxCapacity = SHADOW_TEMPLE_SMALL_KEY_MAX; + break; + case SCENE_BOTTOM_OF_THE_WELL: + result.maxCapacity = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; + break; + case SCENE_GERUDO_TRAINING_GROUND: + result.maxCapacity = GERUDO_TRAINING_GROUND_SMALL_KEY_MAX; + break; + case SCENE_INSIDE_GANONS_CASTLE: + result.maxCapacity = GANONS_CASTLE_SMALL_KEY_MAX; + break; + } + break; } - } - - result.currentCapacity = capacity; - result.maxCapacity = 50; - result.currentAmmo = AMMO(ITEM_BOMBCHU); - break; } - case ITEM_BEAN: - result.currentCapacity = INV_CONTENT(ITEM_BEAN) == ITEM_BEAN ? 10 : 0; - result.maxCapacity = 10; - result.currentAmmo = AMMO(ITEM_BEAN); - break; - case QUEST_SKULL_TOKEN: - result.maxCapacity = result.currentCapacity = 100; - result.currentAmmo = gSaveContext.inventory.gsTokens; - break; - case ITEM_HEART_CONTAINER: - result.maxCapacity = result.currentCapacity = 8; - result.currentAmmo = gSaveContext.ship.stats.heartContainers; - break; - case ITEM_HEART_PIECE: - result.maxCapacity = result.currentCapacity = 36; - result.currentAmmo = gSaveContext.ship.stats.heartPieces; - break; - case ITEM_KEY_SMALL: - // Though the ammo/capacity naming doesn't really make sense for keys, we are - // hijacking the same system to display key counts as there are enough similarities - result.currentAmmo = MAX(gSaveContext.inventory.dungeonKeys[item.data], 0); - if (item.data == SCENE_THIEVES_HIDEOUT) { - std::vector DoorFlags = THIEVES_HIDEOUT_DOOR_FLAGS; - result.currentCapacity = Rando::FindTotalSmallKeys(&gSaveContext, SCENE_THIEVES_HIDEOUT, &DoorFlags); - result.maxCapacity = GERUDO_FORTRESS_SMALL_KEY_MAX; - } else { - result.currentCapacity = OTRGlobals::Instance->gRandoContext->GetDungeons() - ->GetDungeonFromScene(item.data) - ->GetTotalSmallKeys(&gSaveContext); - switch (item.data) { - case SCENE_FOREST_TEMPLE: - result.maxCapacity = FOREST_TEMPLE_SMALL_KEY_MAX; - break; - case SCENE_FIRE_TEMPLE: - result.maxCapacity = FIRE_TEMPLE_SMALL_KEY_MAX; - if (IS_RANDO && - !(OTRGlobals::Instance->gRandoContext->GetOption(RSK_KEYSANITY) - .Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) || - OTRGlobals::Instance->gRandoContext->GetOption(RSK_KEYSANITY) - .Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) || - OTRGlobals::Instance->gRandoContext->GetOption(RSK_KEYSANITY) - .Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON)) && - OTRGlobals::Instance->gRandoContext->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) { - result.currentCapacity = result.currentCapacity - 1; - } - break; - case SCENE_WATER_TEMPLE: - result.maxCapacity = WATER_TEMPLE_SMALL_KEY_MAX; - break; - case SCENE_SPIRIT_TEMPLE: - result.maxCapacity = SPIRIT_TEMPLE_SMALL_KEY_MAX; - break; - case SCENE_SHADOW_TEMPLE: - result.maxCapacity = SHADOW_TEMPLE_SMALL_KEY_MAX; - break; - case SCENE_BOTTOM_OF_THE_WELL: - result.maxCapacity = BOTTOM_OF_THE_WELL_SMALL_KEY_MAX; - break; - case SCENE_GERUDO_TRAINING_GROUND: - result.maxCapacity = GERUDO_TRAINING_GROUND_SMALL_KEY_MAX; - break; - case SCENE_INSIDE_GANONS_CASTLE: - result.maxCapacity = GANONS_CASTLE_SMALL_KEY_MAX; - break; + } else if (item.kind == ITEM_KIND_QUEST && item.id == QUEST_SKULL_TOKEN) { + result.maxCapacity = result.currentCapacity = 100; + result.currentAmmo = gSaveContext.inventory.gsTokens; + } else if (item.kind == ITEM_KIND_RG) { + switch (item.id) { + case RG_SHADOW_SILVER_BLADES: + case RG_SHADOW_SILVER_PIT: + case RG_SHADOW_SILVER_SPIKES: + case RG_SPIRIT_SILVER_CHILD: + case RG_SPIRIT_SILVER_SUN: + case RG_SPIRIT_SILVER_BOULDERS: + case RG_BOTW_SILVER: + case RG_ICE_CAVERN_SILVER_BLADES: + case RG_ICE_CAVERN_SILVER_BLOCK: + case RG_GTG_SILVER_SLOPE: + case RG_GTG_SILVER_LAVA: + case RG_GTG_SILVER_WATER: + case RG_GANONS_CASTLE_SILVER_LIGHT: + case RG_GANONS_CASTLE_SILVER_FOREST: + case RG_GANONS_CASTLE_SILVER_FIRE: + case RG_GANONS_CASTLE_SILVER_SPIRIT: + case RG_DODONGOS_CAVERN_MQ_SILVER: + case RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES: + case RG_SPIRIT_MQ_SILVER_LOBBY: + case RG_SPIRIT_MQ_SILVER_BIG_WALL: + case RG_GANONS_CASTLE_MQ_SILVER_WATER: + case RG_GANONS_CASTLE_MQ_SILVER_SHADOW: + // don't show max and current when we have wallets + if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) == + RO_SHUFFLE_SILVER_ON) { + result.maxCapacity = Randomizer::SilverTotal(static_cast(item.id)); + result.currentAmmo = + *Randomizer::SilverFieldFromSaveContext(&gSaveContext, static_cast(item.id)); } - } - break; + break; + default: + break; + } } return result; } -#define IM_COL_WHITE IM_COL32(255, 255, 255, 255) -#define IM_COL_RED IM_COL32(255, 0, 0, 255) -#define IM_COL_GREEN IM_COL32(0, 255, 0, 255) -#define IM_COL_GRAY IM_COL32(155, 155, 155, 255) -#define IM_COL_PURPLE IM_COL32(180, 90, 200, 255) -#define IM_COL_LIGHT_YELLOW IM_COL32(255, 255, 130, 255) - void DrawItemCount(ItemTrackerItem item, bool hideMax) { if (!GameInteractor::IsSaveLoaded()) { return; @@ -650,25 +697,22 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountType"), ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY); int32_t trackerKeyNumberDisplayMode = CVarGetInteger(CVAR_TRACKER_ITEM("KeyCounts"), KEYS_COLLECTED_MAX); float textScalingFactor = static_cast(iconSize) / 36.0f; - uint32_t actualItemId = INV_CONTENT(item.id); - bool hasItem = actualItemId != ITEM_NONE; + uint32_t actualItemId = item.kind == ITEM_KIND_ITEM ? static_cast(INV_CONTENT(item.id)) : ITEM_NONE; - if (CVarGetInteger(CVAR_TRACKER_ITEM("HookshotIdentifier"), 0)) { - if ((actualItemId == ITEM_HOOKSHOT || actualItemId == ITEM_LONGSHOT) && hasItem) { + if (CVarGetInteger(CVAR_TRACKER_ITEM("HookshotIdentifier"), 0) && + (actualItemId == ITEM_HOOKSHOT || actualItemId == ITEM_LONGSHOT)) { + // Calculate the scaled position for the text + ImVec2 textPos = + ImVec2(p.x + (iconSize >> 1) - + (ImGui::CalcTextSize(item.id == ITEM_HOOKSHOT ? "H" : "L").x * textScalingFactor / 2) + + 8 * textScalingFactor, + p.y - 22 * textScalingFactor); - // Calculate the scaled position for the text - ImVec2 textPos = - ImVec2(p.x + (iconSize / 2) - - (ImGui::CalcTextSize(item.id == ITEM_HOOKSHOT ? "H" : "L").x * textScalingFactor / 2) + - 8 * textScalingFactor, - p.y - 22 * textScalingFactor); + ImGui::SetCursorScreenPos(textPos); + ImGui::SetWindowFontScale(textScalingFactor); - ImGui::SetCursorScreenPos(textPos); - ImGui::SetWindowFontScale(textScalingFactor); - - ImGui::Text(item.id == ITEM_HOOKSHOT ? "H" : "L"); - ImGui::SetWindowFontScale(1.0f); // Reset font scale to the original state - } + ImGui::Text(item.id == ITEM_HOOKSHOT ? "H" : "L"); + ImGui::SetWindowFontScale(1.0f); // Reset font scale to the original state } // progressive open chest: 'S' for small chests only, 'B' once big chests can be opened too @@ -690,7 +734,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { ImGui::SetWindowFontScale(textSize / 13.0f); - if (item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { + if (item.kind == ITEM_KIND_ITEM && item.id == ITEM_KEY_SMALL && IsValidSaveFile()) { std::string currentString = ""; std::string maxString = hideMax ? "???" : std::to_string(currentAndMax.maxCapacity); ImU32 currentColor = IM_COL_WHITE; @@ -708,7 +752,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { } ImGui::SetCursorScreenPos( - ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize((currentString + maxString).c_str()).x / 2), p.y - 14)); + ImVec2(p.x + (iconSize >> 1) - (ImGui::CalcTextSize((currentString + maxString).c_str()).x / 2), p.y - 14)); ImGui::PushStyleColor(ImGuiCol_Text, currentColor); ImGui::Text("%s", currentString.c_str()); ImGui::PopStyleColor(); @@ -716,22 +760,39 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { ImGui::PushStyleColor(ImGuiCol_Text, maxColor); ImGui::Text("%s", maxString.c_str()); ImGui::PopStyleColor(); + } else if (item.kind == ITEM_KIND_RG && IsSilver(static_cast(item.id)) && IsValidSaveFile() && + IS_RANDO && + OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) == RO_SHUFFLE_SILVER_ON) { + std::string maxString = hideMax ? "???" : std::to_string(currentAndMax.maxCapacity); + std::string str = std::to_string(currentAndMax.currentAmmo) + "/" + maxString; + + ImU32 color = IM_COL_WHITE; + if (!hideMax && currentAndMax.maxCapacity == currentAndMax.currentAmmo) { + color = IM_COL_GREEN; + } + + ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize >> 1) - (ImGui::CalcTextSize((str).c_str()).x / 2), p.y - 14)); + ImGui::PushStyleColor(ImGuiCol_Text, color); + ImGui::Text("%s", str.c_str()); + ImGui::PopStyleColor(); } else if (currentAndMax.currentCapacity > 0 && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_NONE && IsValidSaveFile()) { std::string currentString = ""; std::string maxString = ""; ImU32 currentColor = IM_COL_WHITE; - ImU32 maxColor = item.id == QUEST_SKULL_TOKEN ? IM_COL_RED : IM_COL_GREEN; + ImU32 maxColor = item.kind == ITEM_KIND_QUEST && item.id == QUEST_SKULL_TOKEN ? IM_COL_RED : IM_COL_GREEN; bool shouldAlignToLeft = CVarGetInteger(CVAR_TRACKER_ITEM("ItemCountAlignLeft"), 0) && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_CAPACITY && trackerNumberDisplayMode != ITEM_TRACKER_NUMBER_AMMO; - bool shouldDisplayAmmo = trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_AMMO || - trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY || - // These items have a static capacity, so display ammo instead - item.id == ITEM_BEAN || item.id == QUEST_SKULL_TOKEN || - item.id == ITEM_HEART_CONTAINER || item.id == ITEM_HEART_PIECE; + bool shouldDisplayAmmo = + trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_AMMO || + trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY || + // These items have a static capacity, so display ammo instead + (item.kind == ITEM_KIND_QUEST && item.id == QUEST_SKULL_TOKEN) || + (item.kind == ITEM_KIND_ITEM && + (item.id == ITEM_BEAN || item.id == ITEM_HEART_CONTAINER || item.id == ITEM_HEART_PIECE)); bool shouldDisplayMax = !(trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_CURRENT_CAPACITY_ONLY || trackerNumberDisplayMode == ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY); @@ -739,7 +800,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { if (shouldDisplayAmmo) { currentString = std::to_string(currentAndMax.currentAmmo); if (currentAndMax.currentAmmo >= currentAndMax.currentCapacity) { - if (item.id == QUEST_SKULL_TOKEN) { + if (item.kind == ITEM_KIND_QUEST && item.id == QUEST_SKULL_TOKEN) { currentColor = IM_COL_RED; } else { currentColor = IM_COL_GREEN; @@ -764,7 +825,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { float x = shouldAlignToLeft ? p.x - : p.x + (iconSize / 2) - (ImGui::CalcTextSize((currentString + maxString).c_str()).x / 2); + : p.x + (iconSize >> 1) - (ImGui::CalcTextSize((currentString + maxString).c_str()).x / 2); ImGui::SetCursorScreenPos(ImVec2(x, p.y - 14)); ImGui::PushStyleColor(ImGuiCol_Text, currentColor); @@ -774,7 +835,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { ImGui::PushStyleColor(ImGuiCol_Text, maxColor); ImGui::Text("%s", maxString.c_str()); ImGui::PopStyleColor(); - } else if (item.id == RG_TRIFORCE_PIECE && IS_RANDO && + } else if (item.kind == ITEM_KIND_RG && item.id == RG_TRIFORCE_PIECE && IS_RANDO && (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_TOTAL) > 0) && IsValidSaveFile()) { std::string currentString = ""; @@ -805,7 +866,7 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { } ImGui::SetCursorScreenPos( - ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize((currentString + maxString).c_str()).x / 2), p.y - 14)); + ImVec2(p.x + (iconSize >> 1) - (ImGui::CalcTextSize((currentString + maxString).c_str()).x / 2), p.y - 14)); ImGui::PushStyleColor(ImGuiCol_Text, currentColor); ImGui::Text("%s", currentString.c_str()); ImGui::PopStyleColor(); @@ -820,22 +881,24 @@ void DrawItemCount(ItemTrackerItem item, bool hideMax) { } void DrawEquip(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_ITEM); bool hasEquip = HasEquipment(item); float iconSize = static_cast(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); ImGui::Image(std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(hasEquip && IsValidSaveFile() ? item.name : item.nameFaded), + ->GetTextureByName(hasEquip && IsValidSaveFile() ? item.iconName : item.fadedIconName), ImVec2(iconSize, iconSize), ImVec2(0.0f, 0.0f), ImVec2(1, 1)); Tooltip(SohUtils::GetItemName(item.id).c_str()); } void DrawQuest(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_QUEST); bool hasQuestItem = HasQuestItem(item); float iconSize = static_cast(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); ImGui::BeginGroup(); ImGui::ImageWithBg( std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(hasQuestItem && IsValidSaveFile() ? item.name : item.nameFaded), + ->GetTextureByName(hasQuestItem && IsValidSaveFile() ? item.iconName : item.fadedIconName), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); if (item.id == QUEST_SKULL_TOKEN) { @@ -860,377 +923,309 @@ bool HasBossSoul(RandomizerInf bossSoul) { } void DrawItem(ItemTrackerItem item) { - - uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? INV_CONTENT(item.id) : ITEM_NONE; + uint32_t actualItemId = + GameInteractor::IsSaveLoaded() && item.kind == ITEM_KIND_ITEM ? INV_CONTENT(item.id) : ITEM_NONE; float iconSize = static_cast(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); bool hasItem = actualItemId != ITEM_NONE; + bool hideMax = false; std::string itemName = ""; + bool drawItem = true; - // Hack fix as RG_MARKET_SHOOTING_GALLERY_KEY is RandomizerGet #255 which collides - // with ITEM_NONE (ItemId #255) due to the lack of a modid to separate them - if (item.name != "ITEM_KEY_SMALL" && item.id == ITEM_NONE) { - return; - } + if (item.kind == ITEM_KIND_ITEM) { + switch (item.id) { + case ITEM_HEART_CONTAINER: + actualItemId = item.id; + hasItem = gSaveContext.ship.stats.heartContainers > 0; + break; + case ITEM_HEART_PIECE: + actualItemId = item.id; + hasItem = gSaveContext.ship.stats.heartPieces > 0; + break; + case ITEM_MAGIC_SMALL: + case ITEM_MAGIC_LARGE: + actualItemId = gSaveContext.magicLevel == 2 ? ITEM_MAGIC_LARGE : ITEM_MAGIC_SMALL; + hasItem = gSaveContext.magicLevel > 0; + break; + case ITEM_WALLET_ADULT: + case ITEM_WALLET_GIANT: + actualItemId = CUR_UPG_VALUE(UPG_WALLET) == 2 ? ITEM_WALLET_GIANT : ITEM_WALLET_ADULT; + hasItem = !IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET); + break; + case ITEM_BRACELET: + case ITEM_GAUNTLETS_SILVER: + case ITEM_GAUNTLETS_GOLD: + actualItemId = CUR_UPG_VALUE(UPG_STRENGTH) >= 3 ? ITEM_GAUNTLETS_GOLD + : CUR_UPG_VALUE(UPG_STRENGTH) == 2 ? ITEM_GAUNTLETS_SILVER + : ITEM_BRACELET; + hasItem = CUR_UPG_VALUE(UPG_STRENGTH) > 0; + break; + case ITEM_SCALE_SILVER: + case ITEM_SCALE_GOLDEN: + actualItemId = CUR_UPG_VALUE(UPG_SCALE) == 2 ? ITEM_SCALE_GOLDEN : ITEM_SCALE_SILVER; + hasItem = CUR_UPG_VALUE(UPG_SCALE) > 0; + break; + case ITEM_RUPEE_GREEN: + actualItemId = item.id; + hasItem = Flags_GetRandomizerInf(RAND_INF_GREG_FOUND); + break; + case ITEM_NONE: // spacer, don't render + return; + } + } else if (item.kind == ITEM_KIND_RG) { + actualItemId = item.id; + if (Rando::StaticData::RandoGetToRandInf.contains(static_cast(item.id))) { + hasItem = Flags_GetRandomizerInf(static_cast( + Rando::StaticData::RandoGetToRandInf.at(static_cast(item.id)))); + } + auto test = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER); + switch (item.id) { + case RG_TRIFORCE_PIECE: + hasItem = IS_RANDO && + (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_TOTAL) > 0); + itemName = "Triforce Piece"; + break; + case ITEM_NAYRUS_LOVE: + if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_ROCS_FEATHER)) { + hasItem = Flags_GetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE); + } + break; + case RG_ROCS_FEATHER: + itemName = "Roc's Feather"; + break; + case RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL: + itemName = "Death Mountain Crater Bean Soul"; + break; + case RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL: + itemName = "Death Mountain Trail Bean Soul"; + break; + case RG_DESERT_COLOSSUS_BEAN_SOUL: + itemName = "Desert Colossus Bean Soul"; + break; + case RG_GERUDO_VALLEY_BEAN_SOUL: + itemName = "Gerudo Valley Bean Soul"; + break; + case RG_GRAVEYARD_BEAN_SOUL: + itemName = "Graveyard Bean Soul"; + break; + case RG_KOKIRI_FOREST_BEAN_SOUL: + itemName = "Kokiri Forest Bean Soul"; + break; + case RG_LAKE_HYLIA_BEAN_SOUL: + itemName = "Lake Hylia Bean Soul"; + break; + case RG_LOST_WOODS_BRIDGE_BEAN_SOUL: + itemName = "Lost Woods Bridge Bean Soul"; + break; + case RG_LOST_WOODS_BEAN_SOUL: + itemName = "Lost Woods Theatre Bean Soul"; + break; + case RG_ZORAS_RIVER_BEAN_SOUL: + itemName = "Zora's River Bean Soul"; + break; + case RG_GOHMA_SOUL: + hasItem = HasBossSoul(RAND_INF_GOHMA_SOUL); + itemName = "Gohma's Soul"; + break; + case RG_KING_DODONGO_SOUL: + hasItem = HasBossSoul(RAND_INF_KING_DODONGO_SOUL); + itemName = "King Dodongo's Soul"; + break; + case RG_BARINADE_SOUL: + hasItem = HasBossSoul(RAND_INF_BARINADE_SOUL); + itemName = "Barinade's Soul"; + break; + case RG_PHANTOM_GANON_SOUL: + hasItem = HasBossSoul(RAND_INF_PHANTOM_GANON_SOUL); + itemName = "Phantom Ganon's Soul"; + break; + case RG_VOLVAGIA_SOUL: + hasItem = HasBossSoul(RAND_INF_VOLVAGIA_SOUL); + itemName = "Volvagia's Soul"; + break; + case RG_MORPHA_SOUL: + hasItem = HasBossSoul(RAND_INF_MORPHA_SOUL); + itemName = "Morpha's Soul"; + break; + case RG_BONGO_BONGO_SOUL: + hasItem = HasBossSoul(RAND_INF_BONGO_BONGO_SOUL); + itemName = "Bongo Bongo's Soul"; + break; + case RG_TWINROVA_SOUL: + hasItem = HasBossSoul(RAND_INF_TWINROVA_SOUL); + itemName = "Twinrova's Soul"; + break; + case RG_GANON_SOUL: + hasItem = HasBossSoul(RAND_INF_GANON_SOUL); + itemName = "Ganon's Soul"; + break; - switch (item.id) { - case ITEM_HEART_CONTAINER: - actualItemId = item.id; - hasItem = gSaveContext.ship.stats.heartContainers > 0; - break; - case ITEM_HEART_PIECE: - actualItemId = item.id; - hasItem = gSaveContext.ship.stats.heartPieces > 0; - break; - case ITEM_MAGIC_SMALL: - case ITEM_MAGIC_LARGE: - actualItemId = gSaveContext.magicLevel == 2 ? ITEM_MAGIC_LARGE : ITEM_MAGIC_SMALL; - hasItem = gSaveContext.magicLevel > 0; - break; - case ITEM_WALLET_ADULT: - case ITEM_WALLET_GIANT: - actualItemId = CUR_UPG_VALUE(UPG_WALLET) == 2 ? ITEM_WALLET_GIANT : ITEM_WALLET_ADULT; - hasItem = !IS_RANDO || Flags_GetRandomizerInf(RAND_INF_HAS_WALLET); - break; - case ITEM_BRACELET: - case ITEM_GAUNTLETS_SILVER: - case ITEM_GAUNTLETS_GOLD: - actualItemId = CUR_UPG_VALUE(UPG_STRENGTH) >= 3 ? ITEM_GAUNTLETS_GOLD - : CUR_UPG_VALUE(UPG_STRENGTH) == 2 ? ITEM_GAUNTLETS_SILVER - : ITEM_BRACELET; - hasItem = CUR_UPG_VALUE(UPG_STRENGTH) > 0; - break; - case ITEM_SCALE_SILVER: - case ITEM_SCALE_GOLDEN: - actualItemId = CUR_UPG_VALUE(UPG_SCALE) == 2 ? ITEM_SCALE_GOLDEN : ITEM_SCALE_SILVER; - hasItem = CUR_UPG_VALUE(UPG_SCALE) > 0; - break; - case ITEM_RUPEE_GREEN: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_GREG_FOUND); - break; - case RG_TRIFORCE_PIECE: - actualItemId = item.id; - hasItem = IS_RANDO && - (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_TOTAL) > 0); - itemName = "Triforce Piece"; - break; - case ITEM_NAYRUS_LOVE: - if (IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_ROCS_FEATHER)) { - hasItem = Flags_GetRandomizerInf(RAND_INF_OBTAINED_NAYRUS_LOVE); - } - break; - case RG_ROCS_FEATHER: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_OBTAINED_ROCS_FEATHER); - itemName = "Roc's Feather"; - break; - case RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_DEATH_MOUNTAIN_CRATER_BEAN_SOUL); - itemName = "Death Mountain Crater Bean Soul"; - break; - case RG_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_DEATH_MOUNTAIN_TRAIL_BEAN_SOUL); - itemName = "Death Mountain Trail Bean Soul"; - break; - case RG_DESERT_COLOSSUS_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_DESERT_COLOSSUS_BEAN_SOUL); - itemName = "Desert Colossus Bean Soul"; - break; - case RG_GERUDO_VALLEY_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_GERUDO_VALLEY_BEAN_SOUL); - itemName = "Gerudo Valley Bean Soul"; - break; - case RG_GRAVEYARD_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_GRAVEYARD_BEAN_SOUL); - itemName = "Graveyard Bean Soul"; - break; - case RG_KOKIRI_FOREST_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_KOKIRI_FOREST_BEAN_SOUL); - itemName = "Kokiri Forest Bean Soul"; - break; - case RG_LAKE_HYLIA_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_LAKE_HYLIA_BEAN_SOUL); - itemName = "Lake Hylia Bean Soul"; - break; - case RG_LOST_WOODS_BRIDGE_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_LOST_WOODS_BRIDGE_BEAN_SOUL); - itemName = "Lost Woods Bridge Bean Soul"; - break; - case RG_LOST_WOODS_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_LOST_WOODS_BEAN_SOUL); - itemName = "Lost Woods Theatre Bean Soul"; - break; - case RG_ZORAS_RIVER_BEAN_SOUL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_ZORAS_RIVER_BEAN_SOUL); - itemName = "Zora's River Bean Soul"; - break; - case RG_GOHMA_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_GOHMA_SOUL); - itemName = "Gohma's Soul"; - break; - case RG_KING_DODONGO_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_KING_DODONGO_SOUL); - itemName = "King Dodongo's Soul"; - break; - case RG_BARINADE_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_BARINADE_SOUL); - itemName = "Barinade's Soul"; - break; - case RG_PHANTOM_GANON_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_PHANTOM_GANON_SOUL); - itemName = "Phantom Ganon's Soul"; - break; - case RG_VOLVAGIA_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_VOLVAGIA_SOUL); - itemName = "Volvagia's Soul"; - break; - case RG_MORPHA_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_MORPHA_SOUL); - itemName = "Morpha's Soul"; - break; - case RG_BONGO_BONGO_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_BONGO_BONGO_SOUL); - itemName = "Bongo Bongo's Soul"; - break; - case RG_TWINROVA_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_TWINROVA_SOUL); - itemName = "Twinrova's Soul"; - break; - case RG_GANON_SOUL: - actualItemId = item.id; - hasItem = HasBossSoul(RAND_INF_GANON_SOUL); - itemName = "Ganon's Soul"; - break; + case RG_SPEAK_DEKU: + itemName = "Deku Jabber Nut"; + break; + case RG_SPEAK_GERUDO: + itemName = "Gerudo Jabber Nut"; + break; + case RG_SPEAK_GORON: + itemName = "Goron Jabber Nut"; + break; + case RG_SPEAK_HYLIAN: + itemName = "Hylian Jabber Nut"; + break; + case RG_SPEAK_KOKIRI: + itemName = "Kokiri Jabber Nut"; + break; + case RG_SPEAK_ZORA: + itemName = "Zora Jabber Nut"; + break; - case RG_SPEAK_DEKU: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_DEKU); - itemName = "Deku Jabber Nut"; - break; - case RG_SPEAK_GERUDO: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GERUDO); - itemName = "Gerudo Jabber Nut"; - break; - case RG_SPEAK_GORON: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_GORON); - itemName = "Goron Jabber Nut"; - break; - case RG_SPEAK_HYLIAN: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_HYLIAN); - itemName = "Hylian Jabber Nut"; - break; - case RG_SPEAK_KOKIRI: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_KOKIRI); - itemName = "Kokiri Jabber Nut"; - break; - case RG_SPEAK_ZORA: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SPEAK_ZORA); - itemName = "Zora Jabber Nut"; - break; + case RG_OCARINA_A_BUTTON: + itemName = "Ocarina A Button"; + break; + case RG_OCARINA_C_UP_BUTTON: + itemName = "Ocarina C Up Button"; + break; + case RG_OCARINA_C_DOWN_BUTTON: + itemName = "Ocarina C Down Button"; + break; + case RG_OCARINA_C_LEFT_BUTTON: + itemName = "Ocarina C Left Button"; + break; + case RG_OCARINA_C_RIGHT_BUTTON: + itemName = "Ocarina C Right Button"; + break; + case ITEM_FISHING_POLE: + hasItem = IS_RANDO && Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND); + itemName = "Fishing Pole"; + break; - case RG_OCARINA_A_BUTTON: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A); - itemName = "Ocarina A Button"; - break; - case RG_OCARINA_C_UP_BUTTON: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP); - itemName = "Ocarina C Up Button"; - break; - case RG_OCARINA_C_DOWN_BUTTON: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN); - itemName = "Ocarina C Down Button"; - break; - case RG_OCARINA_C_LEFT_BUTTON: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT); - itemName = "Ocarina C Left Button"; - break; - case RG_OCARINA_C_RIGHT_BUTTON: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT); - itemName = "Ocarina C Right Button"; - break; - case ITEM_FISHING_POLE: - actualItemId = item.id; - hasItem = IS_RANDO && Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND); - itemName = "Fishing Pole"; - break; - - case RG_GUARD_HOUSE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_GUARD_HOUSE_KEY_OBTAINED); - itemName = "Guard House Key"; - break; - case RG_MARKET_BAZAAR_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_MARKET_BAZAAR_KEY_OBTAINED); - itemName = "Market Bazaar Key"; - break; - case RG_MARKET_POTION_SHOP_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED); - itemName = "Market Potion Shop Key"; - break; - case RG_MASK_SHOP_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_MASK_SHOP_KEY_OBTAINED); - itemName = "Mask Shop Key"; - break; - case RG_MARKET_SHOOTING_GALLERY_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED); - itemName = "Market Shooting Gallery Key"; - break; - case RG_BOMBCHU_BOWLING_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED); - itemName = "Bombchu Bowling Key"; - break; - case RG_TREASURE_CHEST_GAME_BUILDING_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED); - itemName = "Treasure Chest Game Building Key"; - break; - case RG_BOMBCHU_SHOP_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED); - itemName = "Bombchu Shop Key"; - break; - case RG_RICHARDS_HOUSE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED); - itemName = "Richards House Key"; - break; - case RG_ALLEY_HOUSE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_ALLEY_HOUSE_KEY_OBTAINED); - itemName = "Alley House Key"; - break; - case RG_KAK_BAZAAR_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_KAK_BAZAAR_KEY_OBTAINED); - itemName = "Kak Bazaar Key"; - break; - case RG_KAK_POTION_SHOP_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED); - itemName = "Kak Potion Shop Key"; - break; - case RG_BOSS_HOUSE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_BOSS_HOUSE_KEY_OBTAINED); - itemName = "Boss House Key"; - break; - case RG_GRANNYS_POTION_SHOP_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED); - itemName = "Granny's Potion Shop Key"; - break; - case RG_SKULLTULA_HOUSE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED); - itemName = "Skulltula House Key"; - break; - case RG_IMPAS_HOUSE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_IMPAS_HOUSE_KEY_OBTAINED); - itemName = "Impa's House Key"; - break; - case RG_WINDMILL_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_WINDMILL_KEY_OBTAINED); - itemName = "Windmill Key"; - break; - case RG_KAK_SHOOTING_GALLERY_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED); - itemName = "Kak Shooting Gallery Key"; - break; - case RG_DAMPES_HUT_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_DAMPES_HUT_KEY_OBTAINED); - itemName = "Dampé's Hut Key"; - break; - case RG_TALONS_HOUSE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_TALONS_HOUSE_KEY_OBTAINED); - itemName = "Talon's House Key"; - break; - case RG_STABLES_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_STABLES_KEY_OBTAINED); - itemName = "Stables Key"; - break; - case RG_BACK_TOWER_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_BACK_TOWER_KEY_OBTAINED); - itemName = "Back Tower Key"; - break; - case RG_HYLIA_LAB_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_HYLIA_LAB_KEY_OBTAINED); - itemName = "Hylia Lab Key"; - break; - case RG_FISHING_HOLE_KEY: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_FISHING_HOLE_KEY_OBTAINED); - itemName = "Fishing Hole Key"; - break; - case RG_BRONZE_SCALE: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_SWIM); - itemName = "Swim"; - break; - case RG_CRAWL: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_CRAWL); - itemName = "Crawl"; - break; - case RG_CLIMB: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_CLIMB); - itemName = "Climb"; - break; - case RG_POWER_BRACELET: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_GRAB); - itemName = "Grab"; - break; - case RG_OPEN_CHEST: - actualItemId = item.id; - hasItem = Flags_GetRandomizerInf(RAND_INF_CAN_OPEN_CHEST); - itemName = "Open"; - break; + case RG_GUARD_HOUSE_KEY: + itemName = "Guard House Key"; + break; + case RG_MARKET_BAZAAR_KEY: + itemName = "Market Bazaar Key"; + break; + case RG_MARKET_POTION_SHOP_KEY: + itemName = "Market Potion Shop Key"; + break; + case RG_MASK_SHOP_KEY: + itemName = "Mask Shop Key"; + break; + case RG_MARKET_SHOOTING_GALLERY_KEY: + itemName = "Market Shooting Gallery Key"; + break; + case RG_BOMBCHU_BOWLING_KEY: + itemName = "Bombchu Bowling Key"; + break; + case RG_TREASURE_CHEST_GAME_BUILDING_KEY: + itemName = "Treasure Chest Game Building Key"; + break; + case RG_BOMBCHU_SHOP_KEY: + itemName = "Bombchu Shop Key"; + break; + case RG_RICHARDS_HOUSE_KEY: + itemName = "Richards House Key"; + break; + case RG_ALLEY_HOUSE_KEY: + itemName = "Alley House Key"; + break; + case RG_KAK_BAZAAR_KEY: + itemName = "Kak Bazaar Key"; + break; + case RG_KAK_POTION_SHOP_KEY: + itemName = "Kak Potion Shop Key"; + break; + case RG_BOSS_HOUSE_KEY: + itemName = "Boss House Key"; + break; + case RG_GRANNYS_POTION_SHOP_KEY: + itemName = "Granny's Potion Shop Key"; + break; + case RG_SKULLTULA_HOUSE_KEY: + itemName = "Skulltula House Key"; + break; + case RG_IMPAS_HOUSE_KEY: + itemName = "Impa's House Key"; + break; + case RG_WINDMILL_KEY: + itemName = "Windmill Key"; + break; + case RG_KAK_SHOOTING_GALLERY_KEY: + itemName = "Kak Shooting Gallery Key"; + break; + case RG_DAMPES_HUT_KEY: + itemName = "Dampé's Hut Key"; + break; + case RG_TALONS_HOUSE_KEY: + itemName = "Talon's House Key"; + break; + case RG_STABLES_KEY: + itemName = "Stables Key"; + break; + case RG_BACK_TOWER_KEY: + itemName = "Back Tower Key"; + break; + case RG_HYLIA_LAB_KEY: + itemName = "Hylia Lab Key"; + break; + case RG_FISHING_HOLE_KEY: + itemName = "Fishing Hole Key"; + break; + case RG_SHADOW_SILVER_BLADES: + case RG_SHADOW_SILVER_PIT: + case RG_SHADOW_SILVER_SPIKES: + case RG_SPIRIT_SILVER_CHILD: + case RG_SPIRIT_SILVER_SUN: + case RG_SPIRIT_SILVER_BOULDERS: + case RG_BOTW_SILVER: + case RG_ICE_CAVERN_SILVER_BLADES: + case RG_ICE_CAVERN_SILVER_BLOCK: + case RG_GTG_SILVER_SLOPE: + case RG_GTG_SILVER_LAVA: + case RG_GTG_SILVER_WATER: + case RG_GANONS_CASTLE_SILVER_LIGHT: + case RG_GANONS_CASTLE_SILVER_FOREST: + case RG_GANONS_CASTLE_SILVER_FIRE: + case RG_GANONS_CASTLE_SILVER_SPIRIT: + case RG_DODONGOS_CAVERN_MQ_SILVER: + case RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES: + case RG_SPIRIT_MQ_SILVER_LOBBY: + case RG_SPIRIT_MQ_SILVER_BIG_WALL: + case RG_GANONS_CASTLE_MQ_SILVER_WATER: + case RG_GANONS_CASTLE_MQ_SILVER_SHADOW: + hideMax = + !CheckTracker::IsAreaSpoiled(Rando::StaticData::silverToArea[static_cast(item.id)]); + hasItem = IsSilverCleared(static_cast(item.id)) && + (!hideMax || OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_SHUFFLE_SILVER) != + RO_SHUFFLE_SILVER_ON); + itemName = Rando::StaticData::RetrieveItem(static_cast(actualItemId)) + .GetName() + .GetForLanguage(CVarGetInteger(CVAR_SETTING("Languages"), LANGUAGE_ENG)); + break; + case RG_BRONZE_SCALE: + itemName = "Swim"; + break; + case RG_CRAWL: + itemName = "Crawl"; + break; + case RG_CLIMB: + itemName = "Climb"; + break; + case RG_POWER_BRACELET: + itemName = "Grab"; + break; + case RG_OPEN_CHEST: + itemName = "Open"; + break; + } + } else if (item.kind == ITEM_KIND_DUMMY) { + if (item.id == ITEMTYPE_SILVER) { + hasItem = false; + itemName = "More Silver Rupees may or may not exist based on unknown dungeons."; + } } if (GameInteractor::IsSaveLoaded() && - (hasItem && item.id != actualItemId && + (hasItem && item.kind == ITEM_KIND_ITEM && item.id != actualItemId && actualItemTrackerItemMap.find(actualItemId) != actualItemTrackerItemMap.end())) { item = actualItemTrackerItemMap[actualItemId]; } @@ -1238,73 +1233,18 @@ void DrawItem(ItemTrackerItem item) { ImGui::BeginGroup(); ImGui::Image(std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), + ->GetTextureByName(hasItem && IsValidSaveFile() ? item.iconName : item.fadedIconName), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); - DrawItemCount(item, false); + DrawItemCount(item, hideMax); - if (item.id >= RG_DEATH_MOUNTAIN_CRATER_BEAN_SOUL && item.id <= RG_ZORAS_RIVER_BEAN_SOUL) { - ImVec2 p = ImGui::GetCursorScreenPos(); - std::string beanName = itemTrackerBeanShortNames[item.id]; - ImGui::SetCursorScreenPos( - ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(beanName.c_str()).x / 2), p.y - (iconSize + 13))); - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); - ImGui::Text("%s", beanName.c_str()); - ImGui::PopStyleColor(); - } - - if (item.id >= RG_GOHMA_SOUL && item.id <= RG_GANON_SOUL) { - ImVec2 p = ImGui::GetCursorScreenPos(); - std::string bossName = itemTrackerBossShortNames[item.id]; - ImGui::SetCursorScreenPos( - ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(bossName.c_str()).x / 2), p.y - (iconSize + 13))); - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); - ImGui::Text("%s", bossName.c_str()); - ImGui::PopStyleColor(); - } - - if (item.id >= RG_SPEAK_DEKU && item.id <= RG_SPEAK_ZORA) { - ImVec2 p = ImGui::GetCursorScreenPos(); - std::string name = itemTrackerJabberNutShortNames[item.id]; - ImGui::SetCursorScreenPos( - ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(name.c_str()).x / 2), p.y - (iconSize + 13))); - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); - ImGui::Text("%s", name.c_str()); - ImGui::PopStyleColor(); - } - - if (item.id >= RG_OCARINA_A_BUTTON && item.id <= RG_OCARINA_C_RIGHT_BUTTON) { - ImVec2 p = ImGui::GetCursorScreenPos(); - std::string ocarinaButtonName = itemTrackerOcarinaButtonShortNames[item.id]; - ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(ocarinaButtonName.c_str()).x / 2), - p.y - (iconSize + 13))); - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); - ImGui::Text("%s", ocarinaButtonName.c_str()); - ImGui::PopStyleColor(); - } - - if (item.id >= RG_GUARD_HOUSE_KEY && item.id <= RG_FISHING_HOLE_KEY) { - ImVec2 p = ImGui::GetCursorScreenPos(); - std::string overworldKeyName = itemTrackerOverworldKeyShortNames[item.id]; - ImGui::SetCursorScreenPos(ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(overworldKeyName.c_str()).x / 2), - p.y - (iconSize + 13))); - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); - ImGui::Text("%s", overworldKeyName.c_str()); - ImGui::PopStyleColor(); - } - - if (item.id == RG_BRONZE_SCALE) { - ImVec2 p = ImGui::GetCursorScreenPos(); - ImGui::SetCursorScreenPos( - ImVec2(p.x + (iconSize / 2) - (ImGui::CalcTextSize(itemName.c_str()).x / 2), p.y - (iconSize + 2))); - ImGui::PushStyleColor(ImGuiCol_Text, IM_COL_WHITE); - ImGui::Text("%s", itemName.c_str()); - ImGui::PopStyleColor(); + if (item.displayName != "") { + DrawName(item.displayName, item.kind == ITEM_KIND_DUMMY ? IM_COL_GREEN : IM_COL_WHITE); } ImGui::EndGroup(); - if (itemName == "") { + if (itemName == "" && item.kind == ITEM_KIND_ITEM) { itemName = SohUtils::GetItemName(item.id); } @@ -1312,6 +1252,7 @@ void DrawItem(ItemTrackerItem item) { } void DrawBottle(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_ITEM); uint32_t actualItemId = GameInteractor::IsSaveLoaded() ? (gSaveContext.inventory.items[SLOT(item.id) + item.data]) : false; bool hasItem = actualItemId != ITEM_NONE; @@ -1324,13 +1265,14 @@ void DrawBottle(ItemTrackerItem item) { float iconSize = static_cast(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); ImGui::Image(std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), + ->GetTextureByName(hasItem && IsValidSaveFile() ? item.iconName : item.fadedIconName), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); Tooltip(SohUtils::GetItemName(item.id).c_str()); }; void DrawDungeonItem(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_ITEM); uint32_t itemId = item.id; ImU32 dungeonColor = IM_COL_WHITE; uint32_t bitMask = 1 << (item.id - ITEM_KEY_BOSS); // Bitset starts at ITEM_KEY_BOSS == 0. the rest are sequential @@ -1340,11 +1282,11 @@ void DrawDungeonItem(ItemTrackerItem item) { ImGui::BeginGroup(); if (itemId == ITEM_KEY_SMALL) { ImGui::Image(std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.name : item.nameFaded), + ->GetTextureByName(hasSmallKey && IsValidSaveFile() ? item.iconName : item.fadedIconName), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); } else { ImGui::Image(std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(hasItem && IsValidSaveFile() ? item.name : item.nameFaded), + ->GetTextureByName(hasItem && IsValidSaveFile() ? item.iconName : item.fadedIconName), ImVec2(iconSize, iconSize), ImVec2(0, 0), ImVec2(1, 1)); } @@ -1385,12 +1327,13 @@ void DrawDungeonItem(ItemTrackerItem item) { } void DrawSong(ItemTrackerItem item) { + assert(item.kind == ITEM_KIND_QUEST); float iconSize = static_cast(CVarGetInteger(CVAR_TRACKER_ITEM("IconSize"), 36)); ImVec2 p = ImGui::GetCursorScreenPos(); bool hasSong = HasSong(item); ImGui::SetCursorScreenPos(ImVec2(p.x + 6, p.y)); ImGui::Image(std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) - ->GetTextureByName(hasSong && IsValidSaveFile() ? item.name : item.nameFaded), + ->GetTextureByName(hasSong && IsValidSaveFile() ? item.iconName : item.fadedIconName), ImVec2(iconSize / 1.5f, iconSize), ImVec2(0, 0), ImVec2(1, 1)); Tooltip(SohUtils::GetQuestItemName(item.id).c_str()); } @@ -1503,9 +1446,9 @@ void DrawItemsInRows(std::vector items, int columns = 6) { int topPadding = (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_WINDOW) ? 20 : 0; - for (int i = 0; i < items.size(); i++) { - int row = i / columns; - int column = i % columns; + for (size_t i = 0; i < items.size(); i++) { + size_t row = i / columns; + size_t column = i % columns; ImGui::SetCursorPos( ImVec2((column * (iconSize + iconSpacing) + 8.0f), (row * (iconSize + iconSpacing)) + 8.0f + topPadding)); items[i].drawFunc(items[i]); @@ -1523,7 +1466,7 @@ void DrawItemsInACircle(std::vector items) { ImVec2 max = ImGui::GetWindowContentRegionMax(); float radius = (iconSize + iconSpacing) * 2.0f; - for (int i = 0; i < items.size(); i++) { + for (size_t i = 0; i < items.size(); i++) { float angle = static_cast(i) / items.size() * 2.0f * M_PIf; float x = (radius / 2.0f) * cos(angle) + max.x / 2.0f; float y = (radius / 2.0f) * sin(angle) + max.y / 2.0f; @@ -1551,26 +1494,28 @@ std::vector GetDungeonItemsVector(std::vector i) { switch (dungeons[j].items[i]) { case ITEM_KEY_SMALL: - dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, dungeons[j].id, DrawDungeonItem)); + dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_KEY_SMALL, "", dungeons[j].id, DrawDungeonItem)); break; case ITEM_KEY_BOSS: // Swap Ganon's Castle boss key to the right scene ID manually if (dungeons[j].id == SCENE_INSIDE_GANONS_CASTLE) { dungeonItems.push_back( - ITEM_TRACKER_ITEM(ITEM_KEY_BOSS, SCENE_GANONS_TOWER, DrawDungeonItem)); + ITEM_TRACKER_ITEM(ITEM_KEY_BOSS, "", SCENE_GANONS_TOWER, DrawDungeonItem)); } else { - dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_KEY_BOSS, dungeons[j].id, DrawDungeonItem)); + dungeonItems.push_back( + ITEM_TRACKER_ITEM(ITEM_KEY_BOSS, "", dungeons[j].id, DrawDungeonItem)); } break; case ITEM_DUNGEON_MAP: - dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_DUNGEON_MAP, dungeons[j].id, DrawDungeonItem)); + dungeonItems.push_back( + ITEM_TRACKER_ITEM(ITEM_DUNGEON_MAP, "", dungeons[j].id, DrawDungeonItem)); break; case ITEM_COMPASS: - dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_COMPASS, dungeons[j].id, DrawDungeonItem)); + dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_COMPASS, "", dungeons[j].id, DrawDungeonItem)); break; } } else { - dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, 0, DrawItem)); + dungeonItems.push_back(ITEM_TRACKER_ITEM(ITEM_NONE, "", 0, DrawItem)); } } } @@ -1585,6 +1530,10 @@ std::vector GetDungeonItemsVector(std::vector questMatchingSilverRupeeItems; + TrackSilverRupees(&questMatchingSilverRupeeItems); + BeginFloatingWindows("Silver Rupee Tracker"); + DrawItemsInRows(questMatchingSilverRupeeItems); + EndFloatingWindows(); + } + if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.FishingPole"), SECTION_DISPLAY_EXTENDED_HIDDEN) == SECTION_DISPLAY_EXTENDED_SEPARATE) { BeginFloatingWindows("Fishing Pole Tracker"); @@ -2027,7 +1996,7 @@ void ItemTrackerWindow::DrawElement() { } } if (presetLoaded) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); presetLoaded = false; } } @@ -2077,11 +2046,11 @@ void ItemTrackerSettingsWindow::DrawElement() { if (CVarGetInteger(CVAR_TRACKER_ITEM("WindowType"), TRACKER_WINDOW_FLOATING) == TRACKER_WINDOW_FLOATING) { if (CVarCheckbox("Enable Dragging", CVAR_TRACKER_ITEM("Draggable"), CheckboxOptions().Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarCheckbox("Only Enable While Paused", CVAR_TRACKER_ITEM("ShowOnlyPaused"), CheckboxOptions().Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarCombobox("Display Mode", CVAR_TRACKER_ITEM("DisplayType.Main"), showMode, ComboboxOptions() @@ -2089,7 +2058,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.Main"), TRACKER_DISPLAY_ALWAYS) == TRACKER_DISPLAY_COMBO_BUTTON) { @@ -2099,7 +2068,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarCombobox("Combo Button 2", CVAR_TRACKER_ITEM("ComboButton2"), buttonStrings, ComboboxOptions() @@ -2107,7 +2076,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } } } @@ -2127,7 +2096,7 @@ void ItemTrackerSettingsWindow::DrawElement() { ITEM_TRACKER_NUMBER_CURRENT_AMMO_ONLY) { if (CVarCheckbox("Align count to left side", CVAR_TRACKER_ITEM("ItemCountAlignLeft"), CheckboxOptions().Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } } @@ -2142,7 +2111,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarCombobox("Equipment", CVAR_TRACKER_ITEM("DisplayType.Equipment"), displayTypes, ComboboxOptions() @@ -2150,7 +2119,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarCombobox("Misc", CVAR_TRACKER_ITEM("DisplayType.Misc"), displayTypes, ComboboxOptions() @@ -2158,7 +2127,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarCombobox("Dungeon Rewards", CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), displayTypes, ComboboxOptions() @@ -2166,13 +2135,13 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonRewards"), SECTION_DISPLAY_MAIN_WINDOW) == SECTION_DISPLAY_SEPARATE) { if (CVarCheckbox("Circle display", CVAR_TRACKER_ITEM("DungeonRewardsLayout"), CheckboxOptions().DefaultValue(false).Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } } if (CVarCombobox("Songs", CVAR_TRACKER_ITEM("DisplayType.Songs"), displayTypes, @@ -2181,7 +2150,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } SohGui::mSohMenu->MenuDrawItem(dungeonItemTracking, 250, THEME_COLOR); if (CVarGetInteger(CVAR_TRACKER_ITEM("DisplayType.DungeonItems"), SECTION_DISPLAY_HIDDEN) != @@ -2190,12 +2159,12 @@ void ItemTrackerSettingsWindow::DrawElement() { SECTION_DISPLAY_SEPARATE) { if (CVarCheckbox("Horizontal display", CVAR_TRACKER_ITEM("DungeonItems.Layout"), CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } } if (CVarCheckbox("Maps and compasses", CVAR_TRACKER_ITEM("DungeonItems.DisplayMaps"), CheckboxOptions().DefaultValue(true).Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } } SohGui::mSohMenu->MenuDrawItem(gregTracking, 250, THEME_COLOR); @@ -2205,6 +2174,7 @@ void ItemTrackerSettingsWindow::DrawElement() { SohGui::mSohMenu->MenuDrawItem(jabberNutsTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(ocarinaButtonTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(overworldKeysTracking, 250, THEME_COLOR); + SohGui::mSohMenu->MenuDrawItem(silverRupeeTracking, 250, THEME_COLOR); SohGui::mSohMenu->MenuDrawItem(fishingPoleTracking, 250, THEME_COLOR); if (CVarCombobox("Total Checks", CVAR_TRACKER_ITEM("TotalChecks.DisplayType"), minimalDisplayTypes, @@ -2213,7 +2183,7 @@ void ItemTrackerSettingsWindow::DrawElement() { .ComponentAlignment(ComponentAlignments::Right) .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR))) { - shouldUpdateVectors = true; + RefreshItemTrackerMainWindow(); } SohGui::mSohMenu->MenuDrawItem(personalNotesWiget, 250, THEME_COLOR); @@ -2253,7 +2223,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(windowType)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); SohGui::mSohMenu->AddSearchWidget({ windowTypeWidget, "Randomizer", "Item Tracker", "General Settings" }); enableDraggingWidget; onlyPausedWidget; @@ -2289,7 +2259,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); SohGui::mSohMenu->AddSearchWidget({ triforcePieceTracking, "Randomizer", "Item Tracker", "General Settings" }); dungeonItemTracking = { .name = "Dungeon Items", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; @@ -2300,7 +2270,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget( { dungeonItemTracking, "Randomizer", "Item Tracker", "General Settings", "keys maps compasses icon" }); @@ -2313,7 +2283,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(extendedDisplayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget({ gregTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); @@ -2325,7 +2295,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget({ beanSoulsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); @@ -2337,7 +2307,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget({ bossSoulsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); @@ -2349,7 +2319,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget({ jabberNutsTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); @@ -2372,7 +2342,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget( { ocarinaButtonTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); @@ -2385,7 +2355,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget( { overworldKeysTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); @@ -2398,11 +2368,24 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(extendedDisplayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget( { fishingPoleTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + silverRupeeTracking = { .name = "Silver Rupees", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; + silverRupeeTracking.CVar(CVAR_TRACKER_ITEM("DisplayType.SilverRupees")) + .Options(ComboboxOptions() + .DefaultIndex(SECTION_DISPLAY_HIDDEN) + .ComponentAlignment(ComponentAlignments::Right) + .LabelPosition(LabelPositions::Far) + .Color(THEME_COLOR) + .ComboMap(displayTypes)) + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); + ; + SohGui::mSohMenu->AddSearchWidget( + { silverRupeeTracking, "Randomizer", "Item Tracker", "General Settings", "icon" }); + personalNotesWiget = { .name = "Personal notes", .type = WidgetType::WIDGET_CVAR_COMBOBOX }; static const char* notesDisabledTooltip = "Disabled because tracker is set to floating and display combo is enabled."; @@ -2413,7 +2396,7 @@ void RegisterItemTrackerWidgets() { .LabelPosition(LabelPositions::Far) .Color(THEME_COLOR) .ComboMap(displayTypes)) - .Callback([](WidgetInfo& info) { shouldUpdateVectors = true; }); + .Callback([](WidgetInfo& info) { RefreshItemTrackerMainWindow(); }); ; SohGui::mSohMenu->AddSearchWidget({ personalNotesWiget, "Randomizer", "Item Tracker", "General Settings" }); @@ -2434,7 +2417,7 @@ void RegisterItemTrackerWidgets() { } void RegisterItemTracker() { - COND_HOOK(OnLoadFile, true, [](int32_t fileNum) { shouldUpdateVectors = true; }); + COND_HOOK(OnLoadFile, true, [](int32_t fileNum) { RefreshItemTrackerMainWindow(); }); } static RegisterShipInitFunc registerItemTracker(RegisterItemTracker); diff --git a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h index a33e1c5fa4..5e9b136bfb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h +++ b/soh/soh/Enhancements/randomizer/randomizer_item_tracker.h @@ -1,15 +1,29 @@ #pragma once +#include "ship/window/gui/GuiWindow.h" +#include #include #include #include +#include void DrawItemAmmo(int itemId); +void RefreshItemTrackerMainWindow(); + +typedef enum ItemKind { + ITEM_KIND_ITEM, + ITEM_KIND_QUEST, + ITEM_KIND_RG, + ITEM_KIND_SPECIAL, + ITEM_KIND_DUMMY, +} ItemKind; typedef struct ItemTrackerItem { uint32_t id; - std::string name; - std::string nameFaded; + ItemKind kind; + std::string displayName; + std::string iconName; + std::string fadedIconName; uint32_t data; void (*drawFunc)(ItemTrackerItem); } ItemTrackerItem; @@ -18,27 +32,44 @@ bool HasSong(ItemTrackerItem); bool HasQuestItem(ItemTrackerItem); bool HasEquipment(ItemTrackerItem); -#define ITEM_TRACKER_ITEM(id, data, drawFunc) \ - { id, #id, #id "_Faded", data, drawFunc } +#define ITEM_TRACKER_ITEM(id, displayName, data, drawFunc) \ + { id, ITEM_KIND_ITEM, displayName, #id, #id "_Faded", data, drawFunc } +#define ITEM_TRACKER_ITEM_CUSTOM(id, displayName, iconName, data, drawFunc) \ + { id, ITEM_KIND_ITEM, displayName, #iconName, #iconName "_Faded", data, drawFunc } -#define ITEM_TRACKER_ITEM_CUSTOM(id, name, nameFaded, data, drawFunc) \ - { id, #name, #nameFaded "_Faded", data, drawFunc } +#define ITEM_TRACKER_QUEST(id, displayName, data, drawFunc) \ + { id, ITEM_KIND_QUEST, displayName, #id, #id "_Faded", data, drawFunc } +#define ITEM_TRACKER_QUEST_CUSTOM(id, displayName, iconName, data, drawFunc) \ + { id, ITEM_KIND_QUEST, displayName, #iconName, #iconName "_Faded", data, drawFunc } -static std::vector itemTrackerWindowIDs = { "Item Tracker", - "Inventory Items Tracker", - "Equipment Items Tracker", - "Misc Items Tracker", - "Dungeon Rewards Tracker", - "Songs Tracker", - "Dungeon Items Tracker", - "Greg Tracker", - "Triforce Piece Tracker", - "Boss Soul Tracker", - "Ocarina Button Tracker", - "Overworld Key Tracker", - "Fishing Pole Tracker", - "Personal Notes", - "Total Checks" }; +#define ITEM_TRACKER_RG(id, displayName, data, drawFunc) \ + { id, ITEM_KIND_RG, displayName, #id, #id "_Faded", data, drawFunc } +#define ITEM_TRACKER_RG_CUSTOM(id, displayName, iconName, data, drawFunc) \ + { id, ITEM_KIND_RG, displayName, #iconName, #iconName "_Faded", data, drawFunc } + +#define IM_COL_WHITE IM_COL32(255, 255, 255, 255) +#define IM_COL_RED IM_COL32(255, 0, 0, 255) +#define IM_COL_GREEN IM_COL32(0, 255, 0, 255) +#define IM_COL_GRAY IM_COL32(155, 155, 155, 255) +#define IM_COL_PURPLE IM_COL32(180, 90, 200, 255) +#define IM_COL_LIGHT_YELLOW IM_COL32(255, 255, 130, 255) + +static std::array itemTrackerWindowIDs = { "Item Tracker", + "Inventory Items Tracker", + "Equipment Items Tracker", + "Misc Items Tracker", + "Dungeon Rewards Tracker", + "Songs Tracker", + "Dungeon Items Tracker", + "Greg Tracker", + "Triforce Piece Tracker", + "Boss Soul Tracker", + "Ocarina Button Tracker", + "Overworld Key Tracker", + "Silver Rupee Tracker", + "Fishing Pole Tracker", + "Personal Notes", + "Total Checks" }; void ItemTracker_LoadFromPreset(const nlohmann::json& trackerInfo); typedef struct ItemTrackerDungeon { diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 392f69ff10..926cd5c215 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -408,6 +408,12 @@ void SetStartingItems() { } } + if (Randomizer_GetSettingValue(RSK_SHUFFLE_SILVER) == RO_SHUFFLE_SILVER_STARTWITH) { + for (int rg = (int)RG_SHADOW_SILVER_BLADES; rg <= (int)RG_GANONS_CASTLE_MQ_SILVER_SHADOW; rg++) { + *Randomizer::SilverFieldFromSaveContext(&gSaveContext, (RandomizerGet)rg) = 10; + } + } + if (Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) { gSaveContext.inventory.dungeonItems[SCENE_FOREST_TEMPLE] |= 1; // Forest gSaveContext.inventory.dungeonItems[SCENE_FIRE_TEMPLE] |= 1; // Fire diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index adaf02fd35..5fe7d8ed13 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1071,6 +1071,7 @@ void Settings::CreateOptions() { }); OPT_U8(RSK_SHUFFLE_FREESTANDING, "Shuffle Freestanding Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleFreestanding"), mOptionDescriptions[RSK_SHUFFLE_FREESTANDING], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_FREESTANDING_OFF); OPT_U8(RSK_SHUFFLE_WONDER_ITEMS, "Shuffle Wonder Items", {"Off", "Dungeons", "Overworld", "All Items"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleWonderItems"), mOptionDescriptions[RSK_SHUFFLE_WONDER_ITEMS], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_WONDER_ITEMS_OFF); + OPT_U8(RSK_SHUFFLE_SILVER, "Shuffle Silver Rupees", {"Off", "On", "Wallet", "Start With"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleSilver"), mOptionDescriptions[RSK_SHUFFLE_SILVER], WIDGET_CVAR_COMBOBOX, RO_SHUFFLE_SILVER_OFF); OPT_U8(RSK_FISHSANITY, "Fishsanity", {"Off", "Shuffle only Hyrule Loach", "Shuffle Fishing Pond", "Shuffle Overworld Fish", "Shuffle Both"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("Fishsanity"), mOptionDescriptions[RSK_FISHSANITY], WIDGET_CVAR_COMBOBOX, RO_FISHSANITY_OFF); OPT_CALLBACK(RSK_FISHSANITY, { // Hide fishing pond settings if we aren't shuffling the fishing pond @@ -2030,6 +2031,7 @@ void Settings::CreateOptions() { &mOptions[RSK_FISHSANITY_AGE_SPLIT], &mOptions[RSK_SHUFFLE_FREESTANDING], &mOptions[RSK_SHUFFLE_WONDER_ITEMS], + &mOptions[RSK_SHUFFLE_SILVER], &mOptions[RSK_SHUFFLE_BEEHIVES], &mOptions[RSK_SHUFFLE_COWS], &mOptions[RSK_SHUFFLE_POTS], @@ -2309,6 +2311,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], &mOptions[RSK_SHUFFLE_FREESTANDING], &mOptions[RSK_SHUFFLE_WONDER_ITEMS], + &mOptions[RSK_SHUFFLE_SILVER], &mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES], &mOptions[RSK_SHUFFLE_STONE_FAIRIES], &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index 31c5006f33..d714862d3c 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -537,4 +537,29 @@ std::vector StaticData::overworldKeys = { RG_HYLIA_LAB_KEY, RG_FISHING_HOLE_KEY, }; + +std::vector StaticData::silverRupees = { + RG_SHADOW_SILVER_BLADES, + RG_SHADOW_SILVER_PIT, + RG_SHADOW_SILVER_SPIKES, + RG_SPIRIT_SILVER_CHILD, + RG_SPIRIT_SILVER_SUN, + RG_SPIRIT_SILVER_BOULDERS, + RG_BOTW_SILVER, + RG_ICE_CAVERN_SILVER_BLADES, + RG_ICE_CAVERN_SILVER_BLOCK, + RG_GTG_SILVER_SLOPE, + RG_GTG_SILVER_LAVA, + RG_GTG_SILVER_WATER, + RG_GANONS_CASTLE_SILVER_LIGHT, + RG_GANONS_CASTLE_SILVER_FOREST, + RG_GANONS_CASTLE_SILVER_FIRE, + RG_GANONS_CASTLE_SILVER_SPIRIT, + RG_DODONGOS_CAVERN_MQ_SILVER, + RG_SHADOW_MQ_SILVER_INVISIBLE_BLADES, + RG_SPIRIT_MQ_SILVER_LOBBY, + RG_SPIRIT_MQ_SILVER_BIG_WALL, + RG_GANONS_CASTLE_MQ_SILVER_WATER, + RG_GANONS_CASTLE_MQ_SILVER_SHADOW, +}; } // namespace Rando diff --git a/soh/soh/Enhancements/randomizer/static_data.h b/soh/soh/Enhancements/randomizer/static_data.h index 3773ebacce..56f3e795a8 100644 --- a/soh/soh/Enhancements/randomizer/static_data.h +++ b/soh/soh/Enhancements/randomizer/static_data.h @@ -62,6 +62,7 @@ class StaticData { static void RegisterFairyLocations(); static void RegisterPotLocations(); static void RegisterFreestandingLocations(); + static void RegisterSilverLocations(); static void RegisterGrassLocations(); static void RegisterCrateLocations(); static void RegisterRockLocations(); @@ -91,11 +92,14 @@ class StaticData { static std::unordered_map staticHintInfoMap; static std::unordered_map stoneParamsToHint; static std::unordered_map grottoChestParamsToHint; + static std::unordered_map silverToArea; + static std::set constantSilvers; static std::unordered_map trickToEnum; static std::array hintTextTable; static std::vector normalBottles; static std::vector beanSouls; static std::vector overworldKeys; + static std::vector silverRupees; static std::map RandoGetToRandInf; static std::unordered_map> itemRestrictions; static std::set restrictFW; diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 8e80660e31..079b2b3fca 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -1,3 +1,4 @@ +// vim: ft=cpp #pragma once #define BTN_CUSTOM_MODIFIER1 0x0040 @@ -143,4 +144,4 @@ extern "C" { uint64_t GetUnixTimestamp(); #ifdef __cplusplus }; -#endif \ No newline at end of file +#endif diff --git a/soh/soh/ResourceManagerHelpers.cpp b/soh/soh/ResourceManagerHelpers.cpp index 2818e7e862..aa7601df5c 100644 --- a/soh/soh/ResourceManagerHelpers.cpp +++ b/soh/soh/ResourceManagerHelpers.cpp @@ -175,7 +175,7 @@ u32 IsSceneMasterQuest(s16 sceneNum) { } if (IS_RANDO) { - auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeons()->GetDungeonFromScene(sceneNum); + auto dungeon = OTRGlobals::Instance->gRandoContext->GetDungeonFromScene((SceneID)sceneNum); if (dungeon != nullptr && dungeon->IsMQ()) { return true; } diff --git a/soh/soh/SaveManager.cpp b/soh/soh/SaveManager.cpp index afb3e1d5c7..e3c08c48c9 100644 --- a/soh/soh/SaveManager.cpp +++ b/soh/soh/SaveManager.cpp @@ -229,6 +229,34 @@ void SaveManager::LoadRandomizer() { SaveManager::Instance->LoadData("triforcePiecesCollected", gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected); SaveManager::Instance->LoadData("bombchuUpgradeLevel", gSaveContext.ship.quest.data.randomizer.bombchuUpgradeLevel); + SaveManager::Instance->LoadData("silverShadowBlades", gSaveContext.ship.quest.data.randomizer.silverShadowBlades); + SaveManager::Instance->LoadData("silverShadowPit", gSaveContext.ship.quest.data.randomizer.silverShadowPit); + SaveManager::Instance->LoadData("silverShadowSpikes", gSaveContext.ship.quest.data.randomizer.silverShadowSpikes); + SaveManager::Instance->LoadData("silverSpiritChild", gSaveContext.ship.quest.data.randomizer.silverSpiritChild); + SaveManager::Instance->LoadData("silverSpiritSun", gSaveContext.ship.quest.data.randomizer.silverSpiritSun); + SaveManager::Instance->LoadData("silverSpiritBoulders", + gSaveContext.ship.quest.data.randomizer.silverSpiritBoulders); + SaveManager::Instance->LoadData("silverBotw", gSaveContext.ship.quest.data.randomizer.silverBotw); + SaveManager::Instance->LoadData("silverIceCavernBlades", + gSaveContext.ship.quest.data.randomizer.silverIceCavernBlades); + SaveManager::Instance->LoadData("silverIceCavernBlock", + gSaveContext.ship.quest.data.randomizer.silverIceCavernBlock); + SaveManager::Instance->LoadData("silverGtgSlope", gSaveContext.ship.quest.data.randomizer.silverGtgSlope); + SaveManager::Instance->LoadData("silverGtgLava", gSaveContext.ship.quest.data.randomizer.silverGtgLava); + SaveManager::Instance->LoadData("silverGtgWater", gSaveContext.ship.quest.data.randomizer.silverGtgWater); + SaveManager::Instance->LoadData("silverGanonLight", gSaveContext.ship.quest.data.randomizer.silverGanonLight); + SaveManager::Instance->LoadData("silverGanonForest", gSaveContext.ship.quest.data.randomizer.silverGanonForest); + SaveManager::Instance->LoadData("silverGanonFire", gSaveContext.ship.quest.data.randomizer.silverGanonFire); + SaveManager::Instance->LoadData("silverGanonSpirit", gSaveContext.ship.quest.data.randomizer.silverGanonSpirit); + SaveManager::Instance->LoadData("silverMqDodongosCavern", + gSaveContext.ship.quest.data.randomizer.silverMqDodongosCavern); + SaveManager::Instance->LoadData("silverMqShadowInvisibleBlades", + gSaveContext.ship.quest.data.randomizer.silverMqShadowInvisibleBlades); + SaveManager::Instance->LoadData("silverMqSpiritLobby", gSaveContext.ship.quest.data.randomizer.silverMqSpiritLobby); + SaveManager::Instance->LoadData("silverMqSpiritBigWall", + gSaveContext.ship.quest.data.randomizer.silverMqSpiritBigWall); + SaveManager::Instance->LoadData("silverMqGanonWater", gSaveContext.ship.quest.data.randomizer.silverMqGanonWater); + SaveManager::Instance->LoadData("silverMqGanonShadow", gSaveContext.ship.quest.data.randomizer.silverMqGanonShadow); SaveManager::Instance->LoadData("pendingIceTrapCount", gSaveContext.ship.pendingIceTrapCount); @@ -383,6 +411,34 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f SaveManager::Instance->SaveData("triforcePiecesCollected", saveContext->ship.quest.data.randomizer.triforcePiecesCollected); SaveManager::Instance->SaveData("bombchuUpgradeLevel", saveContext->ship.quest.data.randomizer.bombchuUpgradeLevel); + SaveManager::Instance->SaveData("silverShadowBlades", gSaveContext.ship.quest.data.randomizer.silverShadowBlades); + SaveManager::Instance->SaveData("silverShadowPit", gSaveContext.ship.quest.data.randomizer.silverShadowPit); + SaveManager::Instance->SaveData("silverShadowSpikes", gSaveContext.ship.quest.data.randomizer.silverShadowSpikes); + SaveManager::Instance->SaveData("silverSpiritChild", gSaveContext.ship.quest.data.randomizer.silverSpiritChild); + SaveManager::Instance->SaveData("silverSpiritSun", gSaveContext.ship.quest.data.randomizer.silverSpiritSun); + SaveManager::Instance->SaveData("silverSpiritBoulders", + gSaveContext.ship.quest.data.randomizer.silverSpiritBoulders); + SaveManager::Instance->SaveData("silverBotw", gSaveContext.ship.quest.data.randomizer.silverBotw); + SaveManager::Instance->SaveData("silverIceCavernBlades", + gSaveContext.ship.quest.data.randomizer.silverIceCavernBlades); + SaveManager::Instance->SaveData("silverIceCavernBlock", + gSaveContext.ship.quest.data.randomizer.silverIceCavernBlock); + SaveManager::Instance->SaveData("silverGtgSlope", gSaveContext.ship.quest.data.randomizer.silverGtgSlope); + SaveManager::Instance->SaveData("silverGtgLava", gSaveContext.ship.quest.data.randomizer.silverGtgLava); + SaveManager::Instance->SaveData("silverGtgWater", gSaveContext.ship.quest.data.randomizer.silverGtgWater); + SaveManager::Instance->SaveData("silverGanonLight", gSaveContext.ship.quest.data.randomizer.silverGanonLight); + SaveManager::Instance->SaveData("silverGanonForest", gSaveContext.ship.quest.data.randomizer.silverGanonForest); + SaveManager::Instance->SaveData("silverGanonFire", gSaveContext.ship.quest.data.randomizer.silverGanonFire); + SaveManager::Instance->SaveData("silverGanonSpirit", gSaveContext.ship.quest.data.randomizer.silverGanonSpirit); + SaveManager::Instance->SaveData("silverMqDodongosCavern", + gSaveContext.ship.quest.data.randomizer.silverMqDodongosCavern); + SaveManager::Instance->SaveData("silverMqShadowInvisibleBlades", + gSaveContext.ship.quest.data.randomizer.silverMqShadowInvisibleBlades); + SaveManager::Instance->SaveData("silverMqSpiritLobby", gSaveContext.ship.quest.data.randomizer.silverMqSpiritLobby); + SaveManager::Instance->SaveData("silverMqSpiritBigWall", + gSaveContext.ship.quest.data.randomizer.silverMqSpiritBigWall); + SaveManager::Instance->SaveData("silverMqGanonWater", gSaveContext.ship.quest.data.randomizer.silverMqGanonWater); + SaveManager::Instance->SaveData("silverMqGanonShadow", gSaveContext.ship.quest.data.randomizer.silverMqGanonShadow); SaveManager::Instance->SaveData("pendingIceTrapCount", saveContext->ship.pendingIceTrapCount); diff --git a/soh/soh/SohGui/ImGuiUtils.cpp b/soh/soh/SohGui/ImGuiUtils.cpp index d0264dcead..4be40a681a 100644 --- a/soh/soh/SohGui/ImGuiUtils.cpp +++ b/soh/soh/SohGui/ImGuiUtils.cpp @@ -252,6 +252,14 @@ void RegisterImGuiItemIcons() { ->LoadGuiTexture(entry.second.nameFaded, entry.second.texturePath, "", ImVec4(1, 1, 1, 0.3f)); } + ImVec4 silver = ImVec4(0.7f, 0.7f, 0.7f, 1.0f); + ImVec4 silverFaded = silver; + silverFaded.w = 0.3f; + std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) + ->LoadGuiTexture("ITEM_RUPEE_SILVER", gRupeeCounterIconTex, "", silver); + std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) + ->LoadGuiTexture("ITEM_RUPEE_SILVER_Faded", gRupeeCounterIconTex, "", silverFaded); + for (const auto& entry : questMapping) { std::dynamic_pointer_cast(Ship::Context::GetRawInstance()->GetWindow()->GetGui()) ->LoadGuiTexture(entry.second.name, entry.second.texturePath, "", ImVec4(1, 1, 1, 1)); diff --git a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c index 5337a61bc7..db8dcd5f39 100644 --- a/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c +++ b/soh/src/overlays/actors/ovl_En_G_Switch/z_en_g_switch.c @@ -12,6 +12,7 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "objects/object_tsubo/object_tsubo.h" #include "objects/object_gi_rupy/object_gi_rupy.h" +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/frame_interpolation.h" #define FLAGS (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED) @@ -101,7 +102,7 @@ void EnGSwitch_Init(Actor* thisx, PlayState* play) { // "maximum number of checks" osSyncPrintf(VT_FGCOL(PURPLE) "☆☆☆☆☆ 最大チェック数 ☆☆☆☆☆ %d\n" VT_RST, this->silverCount); osSyncPrintf("\n\n"); - if (Flags_GetSwitch(play, this->switchFlag)) { + if (GameInteractor_Should(VB_SILVER_DESPAWN, Flags_GetSwitch(play, this->switchFlag), this)) { // This is a reference to Hokuto no Ken osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ You are Shock! ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag); Actor_Kill(&this->actor); @@ -119,7 +120,7 @@ void EnGSwitch_Init(Actor* thisx, PlayState* play) { Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); this->actor.draw = EnGSwitch_DrawRupee; this->actor.shape.yOffset = 700.0f; - if (Flags_GetSwitch(play, this->switchFlag)) { + if (GameInteractor_Should(VB_SILVER_DESPAWN, Flags_GetSwitch(play, this->switchFlag), this)) { osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ You are Shock! ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag); Actor_Kill(&this->actor); } else { @@ -211,28 +212,30 @@ void EnGSwitch_WaitForObject(EnGSwitch* this, PlayState* play) { void EnGSwitch_SilverRupeeTracker(EnGSwitch* this, PlayState* play) { static s8 majorScale[] = { 0, 2, 4, 5, 7, 9, 11, 13, 15, 17 }; - if (this->noteIndex < sCollectedCount) { - if (sCollectedCount < (CVarGetInteger(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 0) ? 10 : 5)) { - // "sound?" - osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 音? ☆☆☆☆☆ %d\n" VT_RST, this->noteIndex); - Audio_PlaySoundTransposed(&gSfxDefaultPos, NA_SE_EV_FIVE_COUNT_LUPY, majorScale[this->noteIndex]); - this->noteIndex = sCollectedCount; + if (GameInteractor_Should(VB_SILVER_COUNT_CHECK, true, this)) { + if (this->noteIndex < sCollectedCount) { + if (sCollectedCount < (CVarGetInteger(CVAR_ENHANCEMENT("SilverRupeeJingleExtend"), 0) ? 10 : 5)) { + // "sound?" + osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 音? ☆☆☆☆☆ %d\n" VT_RST, this->noteIndex); + Audio_PlaySoundTransposed(&gSfxDefaultPos, NA_SE_EV_FIVE_COUNT_LUPY, majorScale[this->noteIndex]); + this->noteIndex = sCollectedCount; + } } - } - if (sCollectedCount >= this->silverCount) { - // "It is now the end of the century." - // This another reference to Hokuto no Ken. - osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 時はまさに世紀末〜 ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag); - // "Last!" - osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ らすとぉ! ☆☆☆☆☆ \n" VT_RST); - if ((play->sceneNum == SCENE_GERUDO_TRAINING_GROUND) && (this->actor.room == 2)) { - Flags_SetTempClear(play, this->actor.room); - } else { - Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); - Flags_SetSwitch(play, this->switchFlag); + if (sCollectedCount >= this->silverCount) { + // "It is now the end of the century." + // This another reference to Hokuto no Ken. + osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ 時はまさに世紀末〜 ☆☆☆☆☆ %d\n" VT_RST, this->switchFlag); + // "Last!" + osSyncPrintf(VT_FGCOL(GREEN) "☆☆☆☆☆ らすとぉ! ☆☆☆☆☆ \n" VT_RST); + if ((play->sceneNum == SCENE_GERUDO_TRAINING_GROUND) && (this->actor.room == 2)) { + Flags_SetTempClear(play, this->actor.room); + } else { + Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); + Flags_SetSwitch(play, this->switchFlag); + } + Sfx_PlaySfxCentered(NA_SE_SY_GET_RUPY); + Actor_Kill(&this->actor); } - Sfx_PlaySfxCentered(NA_SE_SY_GET_RUPY); - Actor_Kill(&this->actor); } } @@ -240,7 +243,7 @@ void EnGSwitch_SilverRupeeIdle(EnGSwitch* this, PlayState* play) { Player* player = GET_PLAYER(play); this->actor.shape.rot.y += 0x800; - if (this->actor.xyzDistToPlayerSq < 900.0f) { + if (GameInteractor_Should(VB_SILVER_COLLECT, this->actor.xyzDistToPlayerSq < 900.0f, this)) { Rupees_ChangeBy(5); sCollectedCount++; Sfx_PlaySfxCentered(NA_SE_SY_GET_RUPY);