From 0c9dc9944e8b8c83f591f8de4799a4778987c1b0 Mon Sep 17 00:00:00 2001 From: Demur Rumed Date: Sat, 24 May 2025 21:22:25 +0000 Subject: [PATCH] Shuffle Masks Future improvements can build on this, giving masks abilities, or adding checks for trading mask to someone --- .../3drando/hint_list/hint_list_item.cpp | 9 ++ .../Enhancements/randomizer/3drando/hints.cpp | 2 +- .../randomizer/3drando/item_pool.cpp | 11 ++ .../Enhancements/randomizer/hook_handlers.cpp | 8 +- soh/soh/Enhancements/randomizer/item_list.cpp | 9 ++ .../location_access/overworld/lost_woods.cpp | 4 +- .../location_access/overworld/market.cpp | 8 +- soh/soh/Enhancements/randomizer/logic.cpp | 45 +++++- .../randomizer/option_descriptions.cpp | 9 +- .../Enhancements/randomizer/randomizer.cpp | 129 +++++++----------- .../Enhancements/randomizer/randomizerTypes.h | 26 +++- soh/soh/Enhancements/randomizer/savefile.cpp | 2 +- soh/soh/Enhancements/randomizer/settings.cpp | 15 +- soh/src/code/z_parameter.c | 2 +- .../ovl_file_choose/z_file_choose.c | 7 +- .../misc/ovl_kaleido_scope/z_kaleido_item.c | 6 +- 16 files changed, 179 insertions(+), 113 deletions(-) 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 f5195c91d..7cd7e87ab 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 @@ -2073,6 +2073,15 @@ void StaticData::HintTable_Init_Item() { CustomMessage("a rightward tone", /*german*/"ein rechtsseitiger Ton", /*french*/"une tonalité vers la droite")}); // /*spanish*/un tono hacia la derecha + hintTextTable[RHT_MASK_KEATON] = HintText(CustomMessage("a keaton mask", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_MASK_SKULL] = HintText(CustomMessage("a skull mask", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_MASK_SPOOKY] = HintText(CustomMessage("a spooky mask", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_MASK_BUNNY] = HintText(CustomMessage("a bunny hood", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_MASK_GORON] = HintText(CustomMessage("a goron mask", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_MASK_ZORA] = HintText(CustomMessage("a zora mask", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_MASK_GERUDO] = HintText(CustomMessage("a gerudo mask", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_MASK_TRUTH] = HintText(CustomMessage("a mask of truth", /*german*/"!!!", /*french*/"!!!"), {CustomMessage("a mask", /*german*/"!!!", /*french*/"!!!")}); + hintTextTable[RHT_FISHING_POLE] = HintText(CustomMessage("a fishing pole", /*german*/"eine Angelrute", /*french*/"une canne à pêche"), // /*spanish*/caña de pescar { diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index d8a3f67ee..3ac649977 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -278,7 +278,7 @@ std::vector>> conditionalAlways std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() { auto ctx = Rando::Context::GetInstance(); - return !ctx->GetOption(RSK_MASK_SHOP_HINT) && !ctx->GetOption(RSK_COMPLETE_MASK_QUEST); + return !ctx->GetOption(RSK_MASK_SHOP_HINT) && !ctx->GetOption(RSK_MASK_QUEST); }), std::make_pair(RC_SONG_FROM_OCARINA_OF_TIME, []() { diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 3e6588646..3b0de8f08 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -587,6 +587,17 @@ void GenerateItemPool() { AddItemToMainPool(RG_SKELETON_KEY); } + if (ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_SHUFFLE)) { + AddItemToMainPool(RG_MASK_KEATON); + AddItemToMainPool(RG_MASK_SKULL); + AddItemToMainPool(RG_MASK_SPOOKY); + AddItemToMainPool(RG_MASK_BUNNY); + AddItemToMainPool(RG_MASK_GORON); + AddItemToMainPool(RG_MASK_ZORA); + AddItemToMainPool(RG_MASK_GERUDO); + AddItemToMainPool(RG_MASK_TRUTH); + } + if (ctx->GetOption(RSK_SHUFFLE_SWIM)) { AddItemToMainPool(RG_PROGRESSIVE_SCALE); } diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index d73cebca7..8b88fb2a1 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -24,6 +24,7 @@ extern "C" { #include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h" #include "src/overlays/actors/ovl_Bg_Jya_Bigmirror/z_bg_jya_bigmirror.h" #include "src/overlays/actors/ovl_En_Si/z_en_si.h" +#include "src/overlays/actors/ovl_En_Ossan/z_en_ossan.h" #include "src/overlays/actors/ovl_En_Shopnuts/z_en_shopnuts.h" #include "src/overlays/actors/ovl_En_Dns/z_en_dns.h" #include "src/overlays/actors/ovl_En_Gb/z_en_gb.h" @@ -315,7 +316,7 @@ void RandomizerOnPlayerUpdateForRCQueueHandler() { iceTrapScale = 0.0f; randomizerQueuedCheck = rc; randomizerQueuedItemEntry = getItemEntry; - SPDLOG_INFO("Queueing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, + SPDLOG_INFO("Queuing Item mod {} item {} from RC {}", getItemEntry.modIndex, getItemEntry.itemId, static_cast(rc)); if ( // Skipping ItemGet animation incompatible with checks that require closing a text box to finish @@ -2020,6 +2021,11 @@ void RandomizerOnActorInitHandler(void* actorRef) { } } + if (actor->id == ACTOR_EN_OSSAN && actor->params == OSSAN_TYPE_MASK && + RAND_GET_OPTION(RSK_MASK_QUEST) == RO_MASK_QUEST_SHUFFLE) { + Actor_Kill(actor); + } + if (actor->id == ACTOR_BG_TREEMOUTH && LINK_IS_ADULT && RAND_GET_OPTION(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF && (RAND_GET_OPTION(RSK_FOREST) == RO_CLOSED_FOREST_OFF || diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 7f22fe83f..2307ccd1a 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -349,6 +349,15 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "C-Rechts-Taste der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); + itemTable[RG_MASK_KEATON] = Item(RG_MASK_KEATON, Text{ "Keaton Mask", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_KEATON, true, LOGIC_NONE, RHT_MASK_KEATON, RG_MASK_KEATON, OBJECT_GI_KI_TAN_MASK, GID_MASK_KEATON, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MASK_SKULL] = Item(RG_MASK_SKULL, Text{ "Skull Mask", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_SKULL, true, LOGIC_NONE, RHT_MASK_SKULL, RG_MASK_SKULL, OBJECT_GI_SKJ_MASK, GID_MASK_SKULL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MASK_SPOOKY] = Item(RG_MASK_SPOOKY, Text{ "Spooky Mask", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_SPOOKY, true, LOGIC_NONE, RHT_MASK_SPOOKY, RG_MASK_SPOOKY, OBJECT_GI_REDEAD_MASK, GID_MASK_SPOOKY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MASK_BUNNY] = Item(RG_MASK_BUNNY, Text{ "Bunny Hood", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_BUNNY, true, LOGIC_NONE, RHT_MASK_BUNNY, RG_MASK_BUNNY, OBJECT_GI_RABIT_MASK, GID_MASK_BUNNY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MASK_GORON] = Item(RG_MASK_GORON, Text{ "Goron Mask", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_GORON, true, LOGIC_NONE, RHT_MASK_GORON, RG_MASK_GORON, OBJECT_GI_GOLONMASK, GID_MASK_GORON, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MASK_ZORA] = Item(RG_MASK_ZORA, Text{ "Zora Mask", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_ZORA, true, LOGIC_NONE, RHT_MASK_ZORA, RG_MASK_ZORA, OBJECT_GI_ZORAMASK, GID_MASK_ZORA, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MASK_GERUDO] = Item(RG_MASK_GERUDO, Text{ "Gerudo Mask", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_GERUDO, true, LOGIC_NONE, RHT_MASK_GERUDO, RG_MASK_GERUDO, OBJECT_GI_GERUDOMASK, GID_MASK_GERUDO, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MASK_TRUTH] = Item(RG_MASK_TRUTH, Text{ "Mask of Truth", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_MASK_TRUTH, true, LOGIC_NONE, RHT_MASK_TRUTH, RG_MASK_TRUTH, OBJECT_GI_TRUTH_MASK, GID_MASK_TRUTH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp index 6c6bdb536..c56342016 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -111,8 +111,8 @@ void RegionTable_Init_LostWoods() { areaTable[RR_DEKU_THEATER] = Region("Deku Theater", SCENE_GROTTOS, {}, { //Locations - LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->IsChild && logic->BorrowSkullMask), - LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->IsChild && logic->BorrowRightMasks), + LOCATION(RC_DEKU_THEATER_SKULL_MASK, logic->CanUse(RG_MASK_SKULL)), + LOCATION(RC_DEKU_THEATER_MASK_OF_TRUTH, logic->CanUse(RG_MASK_TRUTH)), }, { //Exits Entrance(RR_LW_BEYOND_MIDO, []{return true;}), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index 4f62d437f..01a641dcf 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -142,10 +142,10 @@ void RegionTable_Init_Market() { //If it is forced on/a setting, a copy of these events should be added to root //it also doesn't need you to open kak gate, but that might be best treated as a bug EventAccess(&logic->CanBorrowMasks, []{return logic->HasItem(RG_ZELDAS_LETTER) && logic->KakarikoVillageGateOpen;}), - EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), - EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), - EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), - EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_COMPLETE_MASK_QUEST) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowSkullMask, []{return ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowSpookyMask, []{return ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowBunnyHood, []{return ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->CanBorrowMasks;}), + EventAccess(&logic->BorrowRightMasks, []{return ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->CanBorrowMasks;}), }, { //Locations LOCATION(RC_MASK_SHOP_HINT, true), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index eea79e92d..a5f9acc63 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -123,6 +123,31 @@ bool Logic::HasItem(RandomizerGet itemName) { return CheckQuestItem(RandoGetToQuestItem.at(itemName)); case RG_DOUBLE_DEFENSE: return GetSaveContext()->isDoubleDefenseAcquired; + // Masks + case RG_MASK_SKULL: + switch (ctx->GetOption(RSK_MASK_QUEST).Get()) { + case RO_MASK_QUEST_VANILLA: + return BorrowSkullMask; + case RO_MASK_QUEST_COMPLETED: + return HasItem(RG_ZELDAS_LETTER); + case RO_MASK_QUEST_SHUFFLE: + return HasItem(RG_ZELDAS_LETTER) && CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_SKULL); + default: + assert(false); + return false; + } + case RG_MASK_TRUTH: + switch (ctx->GetOption(RSK_MASK_QUEST).Get()) { + case RO_MASK_QUEST_VANILLA: + return BorrowRightMasks; + case RO_MASK_QUEST_COMPLETED: + return HasItem(RG_ZELDAS_LETTER); + case RO_MASK_QUEST_SHUFFLE: + return HasItem(RG_ZELDAS_LETTER) && CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH); + default: + assert(false); + return false; + } case RG_FISHING_POLE: case RG_ZELDAS_LETTER: case RG_WEIRD_EGG: @@ -340,6 +365,9 @@ bool Logic::CanUse(RandomizerGet itemName) { return IsChild; case RG_MAGIC_BEAN: return IsChild; + case RG_MASK_SKULL: + case RG_MASK_TRUTH: + return IsChild; // Songs case RG_ZELDAS_LULLABY: @@ -1470,6 +1498,14 @@ std::map Logic::RandoGetToRandInf = { { RG_OCARINA_C_DOWN_BUTTON, RAND_INF_HAS_OCARINA_C_DOWN }, { RG_OCARINA_C_LEFT_BUTTON, RAND_INF_HAS_OCARINA_C_LEFT }, { RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT }, + { RG_MASK_KEATON, RAND_INF_CHILD_TRADES_HAS_MASK_KEATON }, + { RG_MASK_SKULL, RAND_INF_CHILD_TRADES_HAS_MASK_SKULL }, + { RG_MASK_SPOOKY, RAND_INF_CHILD_TRADES_HAS_MASK_SPOOKY }, + { RG_MASK_BUNNY, RAND_INF_CHILD_TRADES_HAS_MASK_BUNNY }, + { RG_MASK_GORON, RAND_INF_CHILD_TRADES_HAS_MASK_GORON }, + { RG_MASK_ZORA, RAND_INF_CHILD_TRADES_HAS_MASK_ZORA }, + { RG_MASK_GERUDO, RAND_INF_CHILD_TRADES_HAS_MASK_GERUDO }, + { RG_MASK_TRUTH, RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH }, { RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY }, { RG_GREG_RUPEE, RAND_INF_GREG_FOUND }, { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, @@ -1836,6 +1872,14 @@ void Logic::ApplyItemEffect(Item& item, bool state) { case RG_OCARINA_C_DOWN_BUTTON: case RG_OCARINA_C_LEFT_BUTTON: case RG_OCARINA_C_RIGHT_BUTTON: + case RG_MASK_KEATON: + case RG_MASK_SKULL: + case RG_MASK_SPOOKY: + case RG_MASK_BUNNY: + case RG_MASK_GORON: + case RG_MASK_ZORA: + case RG_MASK_GERUDO: + case RG_MASK_TRUTH: case RG_GREG_RUPEE: case RG_FISHING_POLE: case RG_GUARD_HOUSE_KEY: @@ -2354,7 +2398,6 @@ void Logic::Reset(bool resetSaveContext /*= true*/) { // Adult logic FreedEpona = false; - // BigPoe = false; // Trade Quest Events WakeUpAdultTalon = false; diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 50d11d9b2..315cf3bef 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -604,8 +604,13 @@ void Settings::CreateOptionDescriptions() { "Start with Zelda's Letter and the item Impa would normally give you and skip the sequence up " "until after meeting Zelda. Disables the ability to shuffle Weird Egg."; mOptionDescriptions[RSK_SKIP_EPONA_RACE] = "Epona can be summoned with Epona's Song without needing to race Ingo."; - mOptionDescriptions[RSK_COMPLETE_MASK_QUEST] = - "Once the Happy Mask Shop is opened, all masks will be available to be borrowed."; + mOptionDescriptions[RSK_MASK_QUEST] = + "How masks are acquired.\n" + "Vanilla - Mask trade quest.\n" + "\n" + "Completed - Once the Happy Mask Shop is opened, all masks will be available to be borrowed.\n" + "\n" + "Shuffle - Happy Mask Shop never opens, masks are shuffled with rest of items."; mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG] = "Start with the ability to summon Pierre the Scarecrow. Pulling out an Ocarina in the usual locations will " "automatically summon him.\n" diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 5f9027d82..29e192dce 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -423,46 +423,33 @@ std::unordered_map spoilerFileDungeonToScene = { { "Ganon's Castle", SCENE_INSIDE_GANONS_CASTLE } }; -std::unordered_map getItemIdToItemId = { - { GI_BOW, ITEM_BOW }, - { GI_ARROW_FIRE, ITEM_ARROW_FIRE }, - { GI_DINS_FIRE, ITEM_DINS_FIRE }, - { GI_SLINGSHOT, ITEM_SLINGSHOT }, - { GI_OCARINA_FAIRY, ITEM_OCARINA_FAIRY }, - { GI_OCARINA_OOT, ITEM_OCARINA_TIME }, - { GI_HOOKSHOT, ITEM_HOOKSHOT }, - { GI_LONGSHOT, ITEM_LONGSHOT }, - { GI_ARROW_ICE, ITEM_ARROW_ICE }, - { GI_FARORES_WIND, ITEM_FARORES_WIND }, - { GI_BOOMERANG, ITEM_BOOMERANG }, - { GI_LENS, ITEM_LENS }, - { GI_HAMMER, ITEM_HAMMER }, - { GI_ARROW_LIGHT, ITEM_ARROW_LIGHT }, - { GI_NAYRUS_LOVE, ITEM_NAYRUS_LOVE }, - { GI_BOTTLE, ITEM_BOTTLE }, - { GI_POTION_RED, ITEM_POTION_RED }, - { GI_POTION_GREEN, ITEM_POTION_GREEN }, - { GI_POTION_BLUE, ITEM_POTION_BLUE }, - { GI_FAIRY, ITEM_FAIRY }, - { GI_FISH, ITEM_FISH }, - { GI_MILK_BOTTLE, ITEM_MILK_BOTTLE }, - { GI_LETTER_RUTO, ITEM_LETTER_RUTO }, - { GI_BLUE_FIRE, ITEM_BLUE_FIRE }, - { GI_BUGS, ITEM_BUG }, - { GI_BIG_POE, ITEM_BIG_POE }, - { GI_POE, ITEM_POE }, - { GI_WEIRD_EGG, ITEM_WEIRD_EGG }, - { GI_LETTER_ZELDA, ITEM_LETTER_ZELDA }, - { GI_POCKET_EGG, ITEM_POCKET_EGG }, - { GI_COJIRO, ITEM_COJIRO }, - { GI_ODD_MUSHROOM, ITEM_ODD_MUSHROOM }, - { GI_ODD_POTION, ITEM_ODD_POTION }, - { GI_SAW, ITEM_SAW }, - { GI_SWORD_BROKEN, ITEM_SWORD_BROKEN }, - { GI_PRESCRIPTION, ITEM_PRESCRIPTION }, - { GI_FROG, ITEM_FROG }, - { GI_EYEDROPS, ITEM_EYEDROPS }, - { GI_CLAIM_CHECK, ITEM_CLAIM_CHECK }, +// used for items that only set a rand inf when obtained +std::map randomizerGetToRandInf = { + { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, + { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, + { RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER }, + { RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG }, + { RG_BULLET_BAG_INF, RAND_INF_HAS_INFINITE_BULLET_BAG }, + { RG_STICK_UPGRADE_INF, RAND_INF_HAS_INFINITE_STICK_UPGRADE }, + { RG_NUT_UPGRADE_INF, RAND_INF_HAS_INFINITE_NUT_UPGRADE }, + { RG_MAGIC_INF, RAND_INF_HAS_INFINITE_MAGIC_METER }, + { RG_BOMBCHU_INF, RAND_INF_HAS_INFINITE_BOMBCHUS }, + { RG_WALLET_INF, RAND_INF_HAS_INFINITE_MONEY }, + { RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY }, + { RG_OCARINA_A_BUTTON, RAND_INF_HAS_OCARINA_A }, + { RG_OCARINA_C_UP_BUTTON, RAND_INF_HAS_OCARINA_C_UP }, + { RG_OCARINA_C_DOWN_BUTTON, RAND_INF_HAS_OCARINA_C_DOWN }, + { RG_OCARINA_C_LEFT_BUTTON, RAND_INF_HAS_OCARINA_C_LEFT }, + { RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT }, + { RG_GOHMA_SOUL, RAND_INF_GOHMA_SOUL }, + { RG_KING_DODONGO_SOUL, RAND_INF_KING_DODONGO_SOUL }, + { RG_BARINADE_SOUL, RAND_INF_BARINADE_SOUL }, + { RG_PHANTOM_GANON_SOUL, RAND_INF_PHANTOM_GANON_SOUL }, + { RG_VOLVAGIA_SOUL, RAND_INF_VOLVAGIA_SOUL }, + { RG_MORPHA_SOUL, RAND_INF_MORPHA_SOUL }, + { RG_BONGO_BONGO_SOUL, RAND_INF_BONGO_BONGO_SOUL }, + { RG_TWINROVA_SOUL, RAND_INF_TWINROVA_SOUL }, + { RG_GANON_SOUL, RAND_INF_GANON_SOUL }, }; #ifdef _MSC_VER @@ -776,6 +763,10 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerCheck(Randomizer } ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGet randoGet) { + if (randomizerGetToRandInf.find(randoGet) != randomizerGetToRandInf.end()) { + return Flags_GetRandomizerInf(randomizerGetToRandInf.find(randoGet)->second) ? CANT_OBTAIN_ALREADY_HAVE + : CAN_OBTAIN; + } // This is needed since Plentiful item pool also adds a third progressive wallet // but we should not get Tycoon's Wallet from it if it is off. @@ -1146,18 +1137,6 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe case RG_LIGHT_MEDALLION: return !CHECK_QUEST_ITEM(QUEST_MEDALLION_LIGHT) ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE; - // Ocarina Buttons - case RG_OCARINA_A_BUTTON: - return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_A) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN; - case RG_OCARINA_C_LEFT_BUTTON: - return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_LEFT) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN; - case RG_OCARINA_C_RIGHT_BUTTON: - return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_RIGHT) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN; - case RG_OCARINA_C_UP_BUTTON: - return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_UP) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN; - case RG_OCARINA_C_DOWN_BUTTON: - return Flags_GetRandomizerInf(RAND_INF_HAS_OCARINA_C_DOWN) ? CANT_OBTAIN_ALREADY_HAVE : CAN_OBTAIN; - case RG_RECOVERY_HEART: case RG_GREEN_RUPEE: case RG_GREG_RUPEE: @@ -5391,7 +5370,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { void Randomizer::CreateCustomMessages() { // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = { { + const std::array getItemMessages = { { GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn&wirklich gefunden!", "Félicitation! Vous avez trouvé %gGreg%w!"), GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!", @@ -5712,6 +5691,15 @@ void Randomizer::CreateCustomMessages() { "Vous obtenez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en " "jouez!"), + GIMESSAGE(RG_MASK_KEATON, ITEM_MASK_KEATON, "You found the Keaton Mask!", "!!!", "!!!"), + GIMESSAGE(RG_MASK_SKULL, ITEM_MASK_SKULL, "You found the Skull Mask!", "!!!", "!!!"), + GIMESSAGE(RG_MASK_SPOOKY, ITEM_MASK_SPOOKY, "You found the Spooky Mask!", "!!!", "!!!"), + GIMESSAGE(RG_MASK_BUNNY, ITEM_MASK_BUNNY, "You found the Bunny Mask!", "!!!", "!!!"), + GIMESSAGE(RG_MASK_GORON, ITEM_MASK_GORON, "You found the Goron Mask!", "!!!", "!!!"), + GIMESSAGE(RG_MASK_ZORA, ITEM_MASK_ZORA, "You found the Zora Mask!", "!!!", "!!!"), + GIMESSAGE(RG_MASK_GERUDO, ITEM_MASK_GERUDO, "You found the Gerudo Mask!", "!!!", "!!!"), + GIMESSAGE(RG_MASK_TRUTH, ITEM_MASK_TRUTH, "You found the Mask of Truth!", "!!!", "!!!"), + GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!", "Du hast die %rBronzene Schuppe%w&erhalten! Die Fähigkeit zu&Schwimmen ist nun dein!", "Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"), @@ -5823,35 +5811,6 @@ void Randomizer_GameplayStats_SetTimestamp(uint16_t item) { extern "C" u8 Return_Item_Entry(GetItemEntry itemEntry, u8 returnItem); -// used for items that only set a rand inf when obtained -std::map randomizerGetToRandInf = { - { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }, - { RG_BRONZE_SCALE, RAND_INF_CAN_SWIM }, - { RG_QUIVER_INF, RAND_INF_HAS_INFINITE_QUIVER }, - { RG_BOMB_BAG_INF, RAND_INF_HAS_INFINITE_BOMB_BAG }, - { RG_BULLET_BAG_INF, RAND_INF_HAS_INFINITE_BULLET_BAG }, - { RG_STICK_UPGRADE_INF, RAND_INF_HAS_INFINITE_STICK_UPGRADE }, - { RG_NUT_UPGRADE_INF, RAND_INF_HAS_INFINITE_NUT_UPGRADE }, - { RG_MAGIC_INF, RAND_INF_HAS_INFINITE_MAGIC_METER }, - { RG_BOMBCHU_INF, RAND_INF_HAS_INFINITE_BOMBCHUS }, - { RG_WALLET_INF, RAND_INF_HAS_INFINITE_MONEY }, - { RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY }, - { RG_OCARINA_A_BUTTON, RAND_INF_HAS_OCARINA_A }, - { RG_OCARINA_C_UP_BUTTON, RAND_INF_HAS_OCARINA_C_UP }, - { RG_OCARINA_C_DOWN_BUTTON, RAND_INF_HAS_OCARINA_C_DOWN }, - { RG_OCARINA_C_LEFT_BUTTON, RAND_INF_HAS_OCARINA_C_LEFT }, - { RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT }, - { RG_GOHMA_SOUL, RAND_INF_GOHMA_SOUL }, - { RG_KING_DODONGO_SOUL, RAND_INF_KING_DODONGO_SOUL }, - { RG_BARINADE_SOUL, RAND_INF_BARINADE_SOUL }, - { RG_PHANTOM_GANON_SOUL, RAND_INF_PHANTOM_GANON_SOUL }, - { RG_VOLVAGIA_SOUL, RAND_INF_VOLVAGIA_SOUL }, - { RG_MORPHA_SOUL, RAND_INF_MORPHA_SOUL }, - { RG_BONGO_BONGO_SOUL, RAND_INF_BONGO_BONGO_SOUL }, - { RG_TWINROVA_SOUL, RAND_INF_TWINROVA_SOUL }, - { RG_GANON_SOUL, RAND_INF_GANON_SOUL }, -}; - extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { if (giEntry.modIndex != MOD_RANDOMIZER) { LUSLOG_WARN( @@ -6040,6 +5999,12 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) { Flags_SetRandomizerInf( (RandomizerInf)((int)RAND_INF_GUARD_HOUSE_UNLOCKED + ((item - RG_GUARD_HOUSE_KEY) * 2) + 1)); return Return_Item_Entry(giEntry, RG_NONE); + } else if (item >= RG_MASK_KEATON && item <= RG_MASK_TRUTH) { + Flags_SetRandomizerInf((RandomizerInf)((int)RAND_INF_CHILD_TRADES_HAS_MASK_KEATON + (item - RG_MASK_KEATON))); + if (INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_NONE) { + INV_CONTENT(ITEM_TRADE_CHILD) = (int)ITEM_MASK_KEATON + (item - RG_MASK_KEATON); + } + return Return_Item_Entry(giEntry, RG_NONE); } switch (item) { diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 15a2fbd37..c87cd12e9 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -4043,6 +4043,14 @@ typedef enum { RG_HOOKSHOT, RG_LONGSHOT, RG_SCARECROW, + RG_MASK_KEATON, + RG_MASK_SKULL, + RG_MASK_SPOOKY, + RG_MASK_BUNNY, + RG_MASK_GORON, + RG_MASK_ZORA, + RG_MASK_GERUDO, + RG_MASK_TRUTH, // Overworld keys RG_GUARD_HOUSE_KEY, @@ -4069,6 +4077,7 @@ typedef enum { RG_BACK_TOWER_KEY, RG_HYLIA_LAB_KEY, RG_FISHING_HOLE_KEY, + // Logic Only RG_DISTANT_SCARECROW, RG_STICKS, @@ -5204,6 +5213,14 @@ typedef enum { RHT_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, + RHT_MASK_KEATON, + RHT_MASK_SKULL, + RHT_MASK_SPOOKY, + RHT_MASK_BUNNY, + RHT_MASK_GORON, + RHT_MASK_ZORA, + RHT_MASK_GERUDO, + RHT_MASK_TRUTH, RHT_BRONZE_SCALE, RHT_FISHING_POLE, RHT_SKELETON_KEY, @@ -5868,7 +5885,7 @@ typedef enum { RSK_SHUFFLE_CHEST_MINIGAME, RSK_BIG_POE_COUNT, RSK_SKIP_EPONA_RACE, - RSK_COMPLETE_MASK_QUEST, + RSK_MASK_QUEST, RSK_SKIP_SCARECROWS_SONG, RSK_SKULLS_SUNS_SONG, RSK_SHUFFLE_ADULT_TRADE, @@ -6236,6 +6253,13 @@ typedef enum { RO_STARTING_OCARINA_TIME, } RandoOptionStartingOcarina; +// Mask Quest Settings (vanilla, completed, shuffle) +typedef enum { + RO_MASK_QUEST_VANILLA, + RO_MASK_QUEST_COMPLETED, + RO_MASK_QUEST_SHUFFLE, +} RandoOptionMaskQuest; + // Item Pool Settings typedef enum { RO_ITEM_POOL_PLENTIFUL, diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index 51101f6fa..c55534eb0 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -402,7 +402,7 @@ extern "C" void Randomizer_InitSaveFile() { } // complete mask quest - if (Randomizer_GetSettingValue(RSK_COMPLETE_MASK_QUEST)) { + if (Randomizer_GetSettingValue(RSK_MASK_QUEST) == RO_MASK_QUEST_COMPLETED) { Flags_SetInfTable(INFTABLE_GATE_GUARD_PUT_ON_KEATON_MASK); Flags_SetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE); diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 5f8c60ac0..7d8ae4a8d 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -270,7 +270,7 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_SKIP_EPONA_RACE, "Skip Epona Race", {"Don't Skip", "Skip"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SkipEponaRace"), mOptionDescriptions[RSK_SKIP_EPONA_RACE], WidgetType::Checkbox, RO_GENERIC_DONT_SKIP); OPT_BOOL(RSK_SKIP_SCARECROWS_SONG, "Skip Scarecrow's Song", CVAR_RANDOMIZER_SETTING("SkipScarecrowsSong"), mOptionDescriptions[RSK_SKIP_SCARECROWS_SONG]); OPT_U8(RSK_BIG_POE_COUNT, "Big Poe Target Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("BigPoeTargetCount"), mOptionDescriptions[RSK_BIG_POE_COUNT], WidgetType::Slider, 10); - OPT_BOOL(RSK_COMPLETE_MASK_QUEST, "Complete Mask Quest", CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_COMPLETE_MASK_QUEST]); + OPT_U8(RSK_MASK_QUEST, "Mask Quest", {"Vanilla", "Completed", "Shuffle"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_MASK_QUEST], WidgetType::Combobox, 0); OPT_U8(RSK_GOSSIP_STONE_HINTS, "Gossip Stone Hints", {"No Hints", "Need Nothing", "Mask of Truth", "Stone of Agony"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("GossipStoneHints"), mOptionDescriptions[RSK_GOSSIP_STONE_HINTS], WidgetType::Combobox, RO_GOSSIP_STONES_NEED_NOTHING, false, IMFLAG_NONE); OPT_U8(RSK_HINT_CLARITY, "Hint Clarity", {"Obscure", "Ambiguous", "Clear"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintClarity"), mOptionDescriptions[RSK_HINT_CLARITY], WidgetType::Combobox, RO_HINT_CLARITY_CLEAR, true, IMFLAG_INDENT); OPT_U8(RSK_HINT_DISTRIBUTION, "Hint Distribution", {"Useless", "Balanced", "Strong", "Very Strong"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("HintDistribution"), mOptionDescriptions[RSK_HINT_DISTRIBUTION], WidgetType::Combobox, RO_HINT_DIST_BALANCED, true, IMFLAG_UNINDENT); @@ -1246,7 +1246,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_FISHING_POLE], &mOptions[RSK_SHUFFLE_DEKU_STICK_BAG], &mOptions[RSK_SHUFFLE_DEKU_NUT_BAG], - &mOptions[RSK_SHUFFLE_FREESTANDING], + &mOptions[RSK_MASK_QUEST], }, WidgetContainerType::COLUMN); mOptionGroups[RSG_SHUFFLE_NPCS_IMGUI] = @@ -1336,11 +1336,11 @@ void Settings::CreateOptions() { &mOptionGroups[RSG_SHUFFLE_DUNGEON_ITEMS_IMGUI], }, WidgetContainerType::TABLE); - mOptionGroups[RSG_TIMESAVERS_IMGUI] = OptionGroup::SubGroup( - "Timesavers", - { &mOptions[RSK_BIG_POE_COUNT], &mOptions[RSK_SKIP_CHILD_ZELDA], &mOptions[RSK_SKIP_EPONA_RACE], - &mOptions[RSK_COMPLETE_MASK_QUEST], &mOptions[RSK_SKIP_SCARECROWS_SONG] }, - WidgetContainerType::COLUMN); + mOptionGroups[RSG_TIMESAVERS_IMGUI] = + OptionGroup::SubGroup("Timesavers", + { &mOptions[RSK_BIG_POE_COUNT], &mOptions[RSK_SKIP_CHILD_ZELDA], + &mOptions[RSK_SKIP_EPONA_RACE], &mOptions[RSK_SKIP_SCARECROWS_SONG] }, + WidgetContainerType::COLUMN); mOptionGroups[RSG_ITEM_POOL_HINTS_IMGUI] = OptionGroup::SubGroup("", { &mOptions[RSK_ITEM_POOL], @@ -1605,7 +1605,6 @@ void Settings::CreateOptions() { &mOptions[RSK_SKIP_EPONA_RACE], &mOptions[RSK_SKIP_SCARECROWS_SONG], &mOptions[RSK_BIG_POE_COUNT], - &mOptions[RSK_COMPLETE_MASK_QUEST], }); mOptionGroups[RSG_MISC] = OptionGroup("Miscellaneous Settings", { diff --git a/soh/src/code/z_parameter.c b/soh/src/code/z_parameter.c index 0fc923070..e170c3570 100644 --- a/soh/src/code/z_parameter.c +++ b/soh/src/code/z_parameter.c @@ -2121,7 +2121,7 @@ u8 Item_Give(PlayState* play, u8 item) { } } } - // update the adult/child equips when rando'd (accounting for equp swapped hookshot as child) + // update the adult/child equips when rando'd (accounting for equip swapped hookshot as child) if (IS_RANDO && LINK_IS_CHILD) { for (i = 1; i < ARRAY_COUNT(gSaveContext.adultEquips.buttonItems); i++) { if (gSaveContext.adultEquips.buttonItems[i] == ITEM_HOOKSHOT) { diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 8fa504748..cea1a8753 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -356,12 +356,7 @@ u8 ShouldRenderItem(s16 fileIndex, u8 item) { return 0; } - if (item == ITEM_MASK_KEATON && (HasItem(fileIndex, ITEM_WEIRD_EGG) || HasItem(fileIndex, ITEM_CHICKEN) || - HasItem(fileIndex, ITEM_LETTER_ZELDA) || HasItem(fileIndex, ITEM_MASK_SKULL) || - HasItem(fileIndex, ITEM_MASK_SPOOKY) || HasItem(fileIndex, ITEM_MASK_BUNNY) || - HasItem(fileIndex, ITEM_MASK_GORON) || HasItem(fileIndex, ITEM_MASK_ZORA) || - HasItem(fileIndex, ITEM_MASK_GERUDO) || HasItem(fileIndex, ITEM_MASK_TRUTH) || - HasItem(fileIndex, ITEM_SOLD_OUT))) { + if (item == ITEM_MASK_KEATON && !HasItem(fileIndex, ITEM_MASK_KEATON)) { return 0; } diff --git a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c index beef301c4..e40f96dc3 100644 --- a/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c +++ b/soh/src/overlays/misc/ovl_kaleido_scope/z_kaleido_item.c @@ -323,9 +323,9 @@ void KaleidoScope_HandleItemCycleExtras(PlayState* play, u8 slot, bool canCycle, bool CanMaskSelect() { if (IS_RANDO) { - return CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0) && - Flags_GetRandomizerInf( - RAND_INF_ZELDAS_LETTER); /* || Randomizer_GetSettingValue(RSK_SHUFFLE_CHILD_TRADE) */ + return (CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0) && Flags_GetRandomizerInf(RAND_INF_ZELDAS_LETTER) && + Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD)) || + Randomizer_GetSettingValue(RSK_MASK_QUEST) == RO_MASK_QUEST_SHUFFLE; } // only allow mask select when: