From 3175ea9c203dc33e5e0d9f0d05907e6750385a56 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20Dub=C3=A9?= <159546+serprex@users.noreply.github.com> Date: Mon, 31 Aug 2026 17:13:25 +0000 Subject: [PATCH] Remove completed mask quest option, add all masks to starting items menu (#7104) Fix masks not rendering properly with completed mask quest Remove completed mask quest option, add all masks to starting items menu logic: handle starting with masks being able to skip ahead a bit in trade sequence --- .../Rando Seed Settings - Advanced.json | 2 +- .../Rando Seed Settings - Beginner.json | 3 +- .../Rando Seed Settings - Standard.json | 2 +- soh/soh/Enhancements/Items/MaskSelect.cpp | 4 +- .../Enhancements/randomizer/3drando/hints.cpp | 2 +- .../randomizer/3drando/item_pool.cpp | 16 +-- .../randomizer/3drando/starting_inventory.cpp | 7 ++ .../Enhancements/randomizer/hook_handlers.cpp | 3 +- .../location_access/overworld/graveyard.cpp | 2 +- .../overworld/hyrule_field.cpp | 2 +- .../location_access/overworld/kakariko.cpp | 2 +- .../location_access/overworld/lost_woods.cpp | 2 +- .../location_access/overworld/market.cpp | 9 +- soh/soh/Enhancements/randomizer/logic.cpp | 36 +++--- .../randomizer/option_descriptions.cpp | 9 +- .../randomizer/randomizerEnums/LogicVal.h | 8 +- .../randomizerEnums/RandomizerOptions.h | 7 -- .../randomizerEnums/RandomizerSettingKey.h | 9 +- soh/soh/Enhancements/randomizer/savefile.cpp | 53 ++++---- soh/soh/Enhancements/randomizer/settings.cpp | 116 +++++++++--------- soh/soh/SohGui/SohMenuEnhancements.cpp | 6 +- soh/soh/SohGui/SohMenuStartingItems.cpp | 13 ++ soh/soh/config/ConfigUpdaters.cpp | 18 +++ .../misc/ovl_kaleido_scope/z_kaleido_item.c | 14 +-- 24 files changed, 174 insertions(+), 171 deletions(-) diff --git a/soh/assets/custom/presets/Rando Seed Settings - Advanced.json b/soh/assets/custom/presets/Rando Seed Settings - Advanced.json index 922ba329d4..88cad1fe5a 100644 --- a/soh/assets/custom/presets/Rando Seed Settings - Advanced.json +++ b/soh/assets/custom/presets/Rando Seed Settings - Advanced.json @@ -9,7 +9,6 @@ "BombchuBag": 1, "BossKeysanity": 5, "ClosedForest": 2, - "CompleteMaskQuest": 1, "CuccosToReturn": 1, "DampeHint": 1, "DoorOfTime": 2, @@ -46,6 +45,7 @@ "ShuffleKeyRings": 2, "ShuffleKeyRingsRandomCount": 4, "ShuffleKokiriSword": 1, + "ShuffleMasks": 1, "ShuffleMasterSword": 1, "ShuffleMerchants": 3, "ShuffleOcarinas": 1, diff --git a/soh/assets/custom/presets/Rando Seed Settings - Beginner.json b/soh/assets/custom/presets/Rando Seed Settings - Beginner.json index 3adc3d0b08..945ce0f80c 100644 --- a/soh/assets/custom/presets/Rando Seed Settings - Beginner.json +++ b/soh/assets/custom/presets/Rando Seed Settings - Beginner.json @@ -12,7 +12,6 @@ "BlueFireArrows": 1, "BossKeysanity": 2, "ClosedForest": 2, - "CompleteMaskQuest": 1, "CuccosToReturn": 1, "DampeHint": 1, "DoorOfTime": 2, @@ -33,11 +32,13 @@ "SariaHint": 1, "SheikLAHint": 0, "ShuffleGanonBossKey": 8, + "ShuffleMasks": 1, "ShuffleOcarinas": 1, "ShuffleWeirdEgg": 2, "SkipEponaRace": 1, "SkipScarecrowsSong": 1, "StartingKokiriSword": 1, + "StartingBunnyHood": 1, "StartingMapsCompasses": 0, "StartingOcarina": 1, "StartingZeldasLetter": 1, diff --git a/soh/assets/custom/presets/Rando Seed Settings - Standard.json b/soh/assets/custom/presets/Rando Seed Settings - Standard.json index 60bbed3f80..2ebfe4f952 100644 --- a/soh/assets/custom/presets/Rando Seed Settings - Standard.json +++ b/soh/assets/custom/presets/Rando Seed Settings - Standard.json @@ -13,7 +13,6 @@ "BombchuBag": 1, "BossKeysanity": 2, "ClosedForest": 2, - "CompleteMaskQuest": 1, "CuccosToReturn": 1, "DampeHint": 1, "DoorOfTime": 2, @@ -42,6 +41,7 @@ "ShuffleKeyRings": 2, "ShuffleKeyRingsRandomCount": 8, "ShuffleKokiriSword": 1, + "ShuffleMasks": 1, "ShuffleMerchants": 1, "ShuffleOcarinas": 1, "ShuffleScrubs": 2, diff --git a/soh/soh/Enhancements/Items/MaskSelect.cpp b/soh/soh/Enhancements/Items/MaskSelect.cpp index e0e5ecaa8d..d90a4ee77b 100644 --- a/soh/soh/Enhancements/Items/MaskSelect.cpp +++ b/soh/soh/Enhancements/Items/MaskSelect.cpp @@ -8,7 +8,7 @@ extern "C" { static void RegisterMaskSelectFixes() { // Fix mask quest so replacing SOLD OUT with mask select doesn't break quest - COND_VB_SHOULD(VB_HAPPY_MASK_SHOP_CHECK_SOLD_OUT, CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0), { + COND_VB_SHOULD(VB_HAPPY_MASK_SHOP_CHECK_SOLD_OUT, CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0) || IS_RANDO, { Actor* actor = va_arg(args, Actor*); if (actor->params == OSSAN_TYPE_MASK && (Flags_GetItemGetInf(ITEMGETINF_3B) && !Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE)) || @@ -20,4 +20,4 @@ static void RegisterMaskSelectFixes() { }); } -static RegisterShipInitFunc initFunc(RegisterMaskSelectFixes, { CVAR_ENHANCEMENT("MaskSelect") }); +static RegisterShipInitFunc initFunc(RegisterMaskSelectFixes, { CVAR_ENHANCEMENT("MaskSelect"), "IS_RANDO" }); diff --git a/soh/soh/Enhancements/randomizer/3drando/hints.cpp b/soh/soh/Enhancements/randomizer/3drando/hints.cpp index 39134196ea..a1493de60e 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hints.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hints.cpp @@ -302,7 +302,7 @@ struct ConditionalAlwaysHint { std::vector conditionalAlwaysHints = { // clang-format off { RC_MARKET_10_BIG_POES, RSK_BIG_POES_HINT, []() { return Rando::Context::GetInstance()->GetOption(RSK_BIG_POE_COUNT).Get() > 3; } }, - { RC_DEKU_THEATER_MASK_OF_TRUTH, RSK_MASK_SHOP_HINT, []() { return !Rando::Context::GetInstance()->GetOption(RSK_MASK_QUEST); } }, + { RC_DEKU_THEATER_MASK_OF_TRUTH, RSK_MASK_SHOP_HINT, []() { return !Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_MASKS); } }, { RC_SONG_FROM_OCARINA_OF_TIME, RSK_OOT_HINT, []() { return StonesRequiredBySettings() < 2; } }, { RC_HF_OCARINA_OF_TIME_ITEM, RSK_OOT_HINT, []() { return StonesRequiredBySettings() < 2; } }, { RC_SHEIK_IN_KAKARIKO, RSK_NONE, []() { return MedallionsRequiredBySettings() < 5; } }, diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp index 68ae12bd54..c63f60e8b3 100644 --- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp @@ -415,15 +415,15 @@ void GenerateItemPool() { AddFixedItemToPool(RG_SKELETON_KEY, 1); } - if (ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_SHUFFLE)) { - AddItemToPool(RG_KEATON_MASK, 2, 1, 1, 1); - AddItemToPool(RG_SKULL_MASK, 2, 1, 1, 1); - AddItemToPool(RG_SPOOKY_MASK, 2, 1, 1, 1); + if (ctx->GetOption(RSK_SHUFFLE_MASKS)) { + if (!ctx->GetOption(RSK_STARTING_KEATON_MASK)) AddItemToPool(RG_KEATON_MASK, 2, 1, 1, 1); + if (!ctx->GetOption(RSK_STARTING_SKULL_MASK)) AddItemToPool(RG_SKULL_MASK, 2, 1, 1, 1); + if (!ctx->GetOption(RSK_STARTING_SPOOKY_MASK)) AddItemToPool(RG_SPOOKY_MASK, 2, 1, 1, 1); if (!ctx->GetOption(RSK_STARTING_BUNNY_HOOD)) AddItemToPool(RG_BUNNY_HOOD, 2, 1, 1, 1); - AddItemToPool(RG_GORON_MASK, 2, 1, 1, 1); - AddItemToPool(RG_ZORA_MASK, 2, 1, 1, 1); - AddItemToPool(RG_GERUDO_MASK, 2, 1, 1, 1); - AddItemToPool(RG_MASK_OF_TRUTH, 2, 1, 1, 1); + if (!ctx->GetOption(RSK_STARTING_GORON_MASK)) AddItemToPool(RG_GORON_MASK, 2, 1, 1, 1); + if (!ctx->GetOption(RSK_STARTING_ZORA_MASK)) AddItemToPool(RG_ZORA_MASK, 2, 1, 1, 1); + if (!ctx->GetOption(RSK_STARTING_GERUDO_MASK)) AddItemToPool(RG_GERUDO_MASK, 2, 1, 1, 1); + if (!ctx->GetOption(RSK_STARTING_MASK_OF_TRUTH)) AddItemToPool(RG_MASK_OF_TRUTH, 2, 1, 1, 1); } if (ctx->GetOption(RSK_ROCS_FEATHER)) { diff --git a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp index 7e8b280cfd..a873834a2b 100644 --- a/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp @@ -120,7 +120,14 @@ void GenerateStartingInventory() { if (ctx->GetOption(RSK_SHUFFLE_ZELDAS_LETTER)) { AddItemToInventory(RG_ZELDAS_LETTER, ctx->GetOption(RSK_STARTING_ZELDAS_LETTER) ? 1 : 0); } + AddItemToInventory(RG_KEATON_MASK, ctx->GetOption(RSK_STARTING_KEATON_MASK) ? 1 : 0); + AddItemToInventory(RG_SKULL_MASK, ctx->GetOption(RSK_STARTING_SKULL_MASK) ? 1 : 0); + AddItemToInventory(RG_SPOOKY_MASK, ctx->GetOption(RSK_STARTING_SPOOKY_MASK) ? 1 : 0); AddItemToInventory(RG_BUNNY_HOOD, ctx->GetOption(RSK_STARTING_BUNNY_HOOD) ? 1 : 0); + AddItemToInventory(RG_GORON_MASK, ctx->GetOption(RSK_STARTING_GORON_MASK) ? 1 : 0); + AddItemToInventory(RG_ZORA_MASK, ctx->GetOption(RSK_STARTING_ZORA_MASK) ? 1 : 0); + AddItemToInventory(RG_GERUDO_MASK, ctx->GetOption(RSK_STARTING_GERUDO_MASK) ? 1 : 0); + AddItemToInventory(RG_MASK_OF_TRUTH, ctx->GetOption(RSK_STARTING_MASK_OF_TRUTH) ? 1 : 0); AddItemToInventory(RG_CLAIM_CHECK, ctx->GetOption(RSK_STARTING_CLAIM_CHECK) ? 1 : 0); AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).Get()); AddItemToInventory(RG_ZELDAS_LULLABY, ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY) ? 1 : 0); diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp index 3afae3e083..c147984350 100644 --- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp +++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp @@ -2426,8 +2426,7 @@ void RandomizerOnActorInitHandler(void* actorRef) { } } - if (actor->id == ACTOR_EN_OSSAN && actor->params == OSSAN_TYPE_MASK && - RAND_GET_OPTION(RSK_MASK_QUEST).Is(RO_MASK_QUEST_SHUFFLE)) { + if (actor->id == ACTOR_EN_OSSAN && actor->params == OSSAN_TYPE_MASK && RAND_GET_OPTION(RSK_SHUFFLE_MASKS)) { Actor_Kill(actor); } diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp index 30bb9c47f1..aa42b38dba 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp @@ -10,7 +10,7 @@ void RegionTable_Init_Graveyard() { EVENT_ACCESS(LOGIC_PLANT_GRAVEYARD_BEAN, CanPlantBean(RG_GRAVEYARD_BEAN_SOUL)), EVENT_ACCESS(LOGIC_FAIRY_ACCESS, (logic->AtDay && logic->CanUse(RG_STICKS)) || (logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_GRAVEYARD_BEAN) && logic->CanUse(RG_SONG_OF_STORMS))), EVENT_ACCESS(LOGIC_BUG_ACCESS, logic->HasItem(RG_POWER_BRACELET)), - EVENT_ACCESS(LOGIC_BORROW_BUNNY_HOOD, logic->IsChild && logic->AtDay && logic->Get(LOGIC_BORROW_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)), + EVENT_ACCESS(LOGIC_SOLD_SPOOKY_MASK, logic->IsChild && logic->AtDay && logic->HasItem(RG_SPOOKY_MASK) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)), }, { //Locations LOCATION(RC_GRAVEYARD_FREESTANDING_POH, (((logic->IsAdult && logic->BeanPlanted(LOGIC_PLANT_GRAVEYARD_BEAN)) || logic->CanUse(RG_LONGSHOT)) && logic->CanBreakCrates()) || (ctx->GetTrickOption(RT_GY_POH) && logic->CanUse(RG_BOOMERANG))), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp index bc9afbd920..7713ca8be4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/hyrule_field.cpp @@ -8,7 +8,7 @@ void RegionTable_Init_HyruleField() { areaTable[RR_HYRULE_FIELD] = Region("Hyrule Field", SCENE_HYRULE_FIELD, { //Events EVENT_ACCESS(LOGIC_BIG_POE_KILL, logic->HasBottle() && logic->CanUse(RG_FAIRY_BOW) && (logic->SummonEpona() || ctx->GetTrickOption(RT_HF_BIG_POE_WITHOUT_EPONA))), - EVENT_ACCESS(LOGIC_BORROW_RIGHT_MASKS, logic->IsChild && logic->Get(LOGIC_BORROW_BUNNY_HOOD) && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)), + EVENT_ACCESS(LOGIC_SOLD_BUNNY_HOOD, logic->IsChild && logic->HasItem(RG_BUNNY_HOOD) && logic->HasItem(RG_KOKIRI_EMERALD) && logic->HasItem(RG_GORON_RUBY) && logic->HasItem(RG_ZORA_SAPPHIRE) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)), }, { //Locations LOCATION(RC_HF_OCARINA_OF_TIME_ITEM, logic->IsChild && logic->StoneCount() == 3 && logic->HasItem(RG_BRONZE_SCALE)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp index 9f344dd503..f50aedfa9f 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp @@ -11,7 +11,7 @@ void RegionTable_Init_Kakariko() { //Open Gate setting is applied in RR_ROOT EVENT_ACCESS(LOGIC_KAKARIKO_GATE_OPEN, logic->IsChild && logic->HasItem(RG_ZELDAS_LETTER)), //Needs wallet to be able to get another mask after selling Keaton - EVENT_ACCESS(LOGIC_BORROW_SKULL_MASK, logic->IsChild && logic->Get(LOGIC_CAN_BORROW_MASKS) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)), + EVENT_ACCESS(LOGIC_SOLD_KEATON_MASK, logic->IsChild && logic->Get(LOGIC_KAKARIKO_GATE_OPEN) && logic->HasItem(RG_KEATON_MASK) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_HYLIAN)), }, { //Locations LOCATION(RC_SHEIK_IN_KAKARIKO, logic->IsAdult && logic->HasItem(RG_FOREST_MEDALLION) && logic->HasItem(RG_FIRE_MEDALLION) && logic->HasItem(RG_WATER_MEDALLION)), 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 f6c8c7c6ff..fc327ff5b4 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lost_woods.cpp @@ -15,7 +15,7 @@ void RegionTable_Init_LostWoods() { EVENT_ACCESS(LOGIC_PLANT_LOST_WOODS_BRIDGE_BEAN, CanPlantBean(RG_LOST_WOODS_BRIDGE_BEAN_SOUL)), EVENT_ACCESS(LOGIC_FAIRY_ACCESS, logic->IsChild && logic->BeanPlanted(LOGIC_PLANT_LOST_WOODS_BRIDGE_BEAN) && logic->CanUse(RG_SONG_OF_STORMS)), EVENT_ACCESS(LOGIC_BUG_ACCESS, logic->IsChild && logic->CanCutShrubs()), - EVENT_ACCESS(LOGIC_BORROW_SPOOKY_MASK, logic->IsChild && logic->Get(LOGIC_BORROW_SKULL_MASK) && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_KOKIRI) && logic->HasItem(RG_SPEAK_HYLIAN)), + EVENT_ACCESS(LOGIC_SOLD_SKULL_MASK, logic->IsChild && logic->HasItem(RG_SKULL_MASK) && logic->CanUse(RG_SARIAS_SONG) && logic->HasItem(RG_CHILD_WALLET) && logic->HasItem(RG_SPEAK_KOKIRI) && logic->HasItem(RG_SPEAK_HYLIAN)), }, { //Locations LOCATION(RC_LW_SKULL_KID, logic->IsChild && logic->CanUse(RG_SARIAS_SONG)), diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp index bb4e610d83..248669cbef 100644 --- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp +++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp @@ -149,14 +149,7 @@ void RegionTable_Init_Market() { areaTable[RR_MARKET_MASK_SHOP] = Region("Market Mask Shop", SCENE_HAPPY_MASK_SHOP, { //Events - //Currently, mask swap in menu doesn't need access to the mask shop - //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 - EVENT_ACCESS(LOGIC_CAN_BORROW_MASKS, logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_KAKARIKO_GATE_OPEN)), - EVENT_ACCESS(LOGIC_BORROW_SKULL_MASK, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)), - EVENT_ACCESS(LOGIC_BORROW_SPOOKY_MASK, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)), - EVENT_ACCESS(LOGIC_BORROW_BUNNY_HOOD, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)), - EVENT_ACCESS(LOGIC_BORROW_RIGHT_MASKS, ctx->GetOption(RSK_MASK_QUEST).Is(RO_MASK_QUEST_COMPLETED) && logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_CAN_BORROW_MASKS)), + EVENT_ACCESS(LOGIC_CAN_BORROW_MASKS, logic->HasItem(RG_SPEAK_HYLIAN) && logic->Get(LOGIC_KAKARIKO_GATE_OPEN)), }, { //Locations LOCATION(RC_MASK_SHOP_HINT, true), diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp index b363a0e8bf..13ced6261c 100644 --- a/soh/soh/Enhancements/randomizer/logic.cpp +++ b/soh/soh/Enhancements/randomizer/logic.cpp @@ -124,30 +124,22 @@ bool Logic::HasItem(RandomizerGet itemName) { case RG_DOUBLE_DEFENSE: return GetSaveContext()->isDoubleDefenseAcquired; // Masks + case RG_KEATON_MASK: + return CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_KEATON) || + (!ctx->GetOption(RSK_SHUFFLE_MASKS) && Get(LOGIC_CAN_BORROW_MASKS)); case RG_SKULL_MASK: - switch (ctx->GetOption(RSK_MASK_QUEST).Get()) { - case RO_MASK_QUEST_VANILLA: - return Get(LOGIC_BORROW_SKULL_MASK); - case RO_MASK_QUEST_COMPLETED: - return Get(LOGIC_KAKARIKO_GATE_OPEN); - case RO_MASK_QUEST_SHUFFLE: - return CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_SKULL); - default: - assert(false); - return false; - } + return CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_SKULL) || + (!ctx->GetOption(RSK_SHUFFLE_MASKS) && Get(LOGIC_CAN_BORROW_MASKS) && Get(LOGIC_SOLD_KEATON_MASK)); + case RG_SPOOKY_MASK: + return CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_SPOOKY) || + (!ctx->GetOption(RSK_SHUFFLE_MASKS) && Get(LOGIC_CAN_BORROW_MASKS) && Get(LOGIC_SOLD_SKULL_MASK)); + case RG_BUNNY_HOOD: + return CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_BUNNY) || + (!ctx->GetOption(RSK_SHUFFLE_MASKS) && Get(LOGIC_CAN_BORROW_MASKS) && Get(LOGIC_SOLD_SPOOKY_MASK)); case RG_MASK_OF_TRUTH: - switch (ctx->GetOption(RSK_MASK_QUEST).Get()) { - case RO_MASK_QUEST_VANILLA: - return Get(LOGIC_BORROW_RIGHT_MASKS); - case RO_MASK_QUEST_COMPLETED: - return Get(LOGIC_KAKARIKO_GATE_OPEN); - case RO_MASK_QUEST_SHUFFLE: - return CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH); - default: - assert(false); - return false; - } + return CheckRandoInf(RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH) || + (!ctx->GetOption(RSK_SHUFFLE_MASKS) && Get(LOGIC_CAN_BORROW_MASKS) && Get(LOGIC_SOLD_KEATON_MASK) && + Get(LOGIC_SOLD_SKULL_MASK) && Get(LOGIC_SOLD_SPOOKY_MASK) && Get(LOGIC_SOLD_BUNNY_HOOD)); case RG_POWER_BRACELET: case RG_CHILD_WALLET: case RG_FISHING_POLE: diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp index 4912b9fbbe..4c3210dcac 100644 --- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp +++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp @@ -709,13 +709,8 @@ void Settings::CreateOptionDescriptions() { mOptionDescriptions[RSK_SKIP_CHILD_STEALTH] = "The crawlspace into Hyrule Castle goes straight to Zelda, skipping the guards."; mOptionDescriptions[RSK_SKIP_EPONA_RACE] = "Epona can be summoned with Epona's Song without needing to race Ingo."; - 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 the rest of the items."; + mOptionDescriptions[RSK_SHUFFLE_MASKS] = + "The Happy Mask Shop never opens, masks are shuffled with the rest of the 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/randomizerEnums/LogicVal.h b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h index 8adc2dc685..fde3575865 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/LogicVal.h @@ -201,10 +201,10 @@ 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) -RANDO_ENUM_ITEM(LOGIC_BORROW_SPOOKY_MASK) -RANDO_ENUM_ITEM(LOGIC_BORROW_BUNNY_HOOD) -RANDO_ENUM_ITEM(LOGIC_BORROW_RIGHT_MASKS) +RANDO_ENUM_ITEM(LOGIC_SOLD_KEATON_MASK) +RANDO_ENUM_ITEM(LOGIC_SOLD_SKULL_MASK) +RANDO_ENUM_ITEM(LOGIC_SOLD_SPOOKY_MASK) +RANDO_ENUM_ITEM(LOGIC_SOLD_BUNNY_HOOD) RANDO_ENUM_ITEM(LOGIC_FREED_EPONA) RANDO_ENUM_ITEM(LOGIC_DEKU_TREE_CLEAR) RANDO_ENUM_ITEM(LOGIC_DODONGOS_CAVERN_CLEAR) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h index 6ed8fac87d..b84cd7c692 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerOptions.h @@ -343,13 +343,6 @@ RANDO_ENUM_ITEM(RO_STARTING_BGS_GIANTS_KNIFE) RANDO_ENUM_ITEM(RO_STARTING_BGS_BIGGORON_SWORD) RANDO_ENUM_END(RandoOptionStartingBiggoronSword) -// Mask Quest Settings (vanilla, completed, shuffle) -RANDO_ENUM_BEGIN(RandoOptionMaskQuest) -RANDO_ENUM_ITEM(RO_MASK_QUEST_VANILLA) -RANDO_ENUM_ITEM(RO_MASK_QUEST_COMPLETED) -RANDO_ENUM_ITEM(RO_MASK_QUEST_SHUFFLE) -RANDO_ENUM_END(RandoOptionMaskQuest) - // Item Pool Settings RANDO_ENUM_BEGIN(RandoOptionItemPool) RANDO_ENUM_ITEM(RO_ITEM_POOL_PLENTIFUL) diff --git a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h index 4e457e91a1..4b85ab349a 100644 --- a/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h +++ b/soh/soh/Enhancements/randomizer/randomizerEnums/RandomizerSettingKey.h @@ -183,7 +183,7 @@ RANDO_ENUM_ITEM(RSK_FULL_WALLETS) RANDO_ENUM_ITEM(RSK_SHUFFLE_CHEST_MINIGAME) RANDO_ENUM_ITEM(RSK_BIG_POE_COUNT) RANDO_ENUM_ITEM(RSK_SKIP_EPONA_RACE) -RANDO_ENUM_ITEM(RSK_MASK_QUEST) +RANDO_ENUM_ITEM(RSK_SHUFFLE_MASKS) RANDO_ENUM_ITEM(RSK_SKIP_SCARECROWS_SONG) RANDO_ENUM_ITEM(RSK_SKIP_PLANTING_BEANS) RANDO_ENUM_ITEM(RSK_SKULLS_SUNS_SONG) @@ -307,7 +307,14 @@ RANDO_ENUM_ITEM(RSK_SHUFFLE_SIGNS) RANDO_ENUM_ITEM(RSK_ROCS_FEATHER) RANDO_ENUM_ITEM(RSK_SHUFFLE_ICICLES) RANDO_ENUM_ITEM(RSK_SHUFFLE_RED_ICE) +RANDO_ENUM_ITEM(RSK_STARTING_KEATON_MASK) +RANDO_ENUM_ITEM(RSK_STARTING_SKULL_MASK) +RANDO_ENUM_ITEM(RSK_STARTING_SPOOKY_MASK) RANDO_ENUM_ITEM(RSK_STARTING_BUNNY_HOOD) +RANDO_ENUM_ITEM(RSK_STARTING_GORON_MASK) +RANDO_ENUM_ITEM(RSK_STARTING_ZORA_MASK) +RANDO_ENUM_ITEM(RSK_STARTING_GERUDO_MASK) +RANDO_ENUM_ITEM(RSK_STARTING_MASK_OF_TRUTH) RANDO_ENUM_ITEM(RSK_PROGRESSIVE_GORON_SWORD) RANDO_ENUM_ITEM(RSK_MAX) RANDO_ENUM_END(RandomizerSettingKey) diff --git a/soh/soh/Enhancements/randomizer/savefile.cpp b/soh/soh/Enhancements/randomizer/savefile.cpp index ea0c15ca70..3e4db83295 100644 --- a/soh/soh/Enhancements/randomizer/savefile.cpp +++ b/soh/soh/Enhancements/randomizer/savefile.cpp @@ -350,10 +350,27 @@ void SetStartingItems() { Item_Give(NULL, ITEM_GERUDO_CARD); } - if (Randomizer_GetSettingValue(RSK_STARTING_BUNNY_HOOD)) { - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_BUNNY); - if (INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_NONE) { - INV_CONTENT(ITEM_TRADE_CHILD) = ITEM_MASK_BUNNY; + struct StartingMask { + RandomizerSettingKey setting; + RandomizerInf randInf; + uint8_t item; + }; + static const StartingMask startingMasks[] = { + { RSK_STARTING_KEATON_MASK, RAND_INF_CHILD_TRADES_HAS_MASK_KEATON, ITEM_MASK_KEATON }, + { RSK_STARTING_SKULL_MASK, RAND_INF_CHILD_TRADES_HAS_MASK_SKULL, ITEM_MASK_SKULL }, + { RSK_STARTING_SPOOKY_MASK, RAND_INF_CHILD_TRADES_HAS_MASK_SPOOKY, ITEM_MASK_SPOOKY }, + { RSK_STARTING_BUNNY_HOOD, RAND_INF_CHILD_TRADES_HAS_MASK_BUNNY, ITEM_MASK_BUNNY }, + { RSK_STARTING_GORON_MASK, RAND_INF_CHILD_TRADES_HAS_MASK_GORON, ITEM_MASK_GORON }, + { RSK_STARTING_ZORA_MASK, RAND_INF_CHILD_TRADES_HAS_MASK_ZORA, ITEM_MASK_ZORA }, + { RSK_STARTING_GERUDO_MASK, RAND_INF_CHILD_TRADES_HAS_MASK_GERUDO, ITEM_MASK_GERUDO }, + { RSK_STARTING_MASK_OF_TRUTH, RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH, ITEM_MASK_TRUTH }, + }; + for (const auto& mask : startingMasks) { + if (Randomizer_GetSettingValue(mask.setting)) { + Flags_SetRandomizerInf(mask.randInf); + if (INV_CONTENT(ITEM_TRADE_CHILD) == ITEM_NONE) { + INV_CONTENT(ITEM_TRADE_CHILD) = mask.item; + } } } @@ -617,11 +634,8 @@ extern "C" void Randomizer_InitSaveFile() { gSaveContext.sceneFlags[SCENE_WATER_TEMPLE].swch |= (1 << 0x15); } - int doorOfTime = Randomizer_GetSettingValue(RSK_DOOR_OF_TIME); - switch (doorOfTime) { - case RO_DOOROFTIME_OPEN: - Flags_SetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME); - break; + if (Randomizer_GetSettingValue(RSK_DOOR_OF_TIME) == RO_DOOROFTIME_OPEN) { + Flags_SetEventChkInf(EVENTCHKINF_OPENED_THE_DOOR_OF_TIME); } if (Randomizer_GetSettingValue(RSK_GERUDO_FORTRESS) == RO_GF_CARPENTERS_FAST || @@ -655,25 +669,4 @@ extern "C" void Randomizer_InitSaveFile() { Item_Give(NULL, ITEM_GERUDO_CARD); } } - - // 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); - - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_KEATON); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_SKULL); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_SPOOKY); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_BUNNY); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_GORON); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_ZORA); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_GERUDO); - Flags_SetRandomizerInf(RAND_INF_CHILD_TRADES_HAS_MASK_TRUTH); - - gSaveContext.itemGetInf[3] |= 0x100; // Sold Keaton Mask - gSaveContext.itemGetInf[3] |= 0x200; // Sold Skull Mask - gSaveContext.itemGetInf[3] |= 0x400; // Sold Spooky Mask - gSaveContext.itemGetInf[3] |= 0x800; // Bunny Hood related - gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth - } } diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp index 2ab5783dde..cee99f0070 100644 --- a/soh/soh/Enhancements/randomizer/settings.cpp +++ b/soh/soh/Enhancements/randomizer/settings.cpp @@ -1352,7 +1352,7 @@ void Settings::CreateOptions() { mOptions[RSK_BIG_POES_HINT].Enable(); } }); - OPT_U8(RSK_MASK_QUEST, "Mask Quest", {"Vanilla", "Completed", "Shuffle"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("CompleteMaskQuest"), mOptionDescriptions[RSK_MASK_QUEST], WIDGET_CVAR_COMBOBOX, 0); + OPT_BOOL(RSK_SHUFFLE_MASKS, "Shuffle Masks", CVAR_RANDOMIZER_SETTING("ShuffleMasks"), mOptionDescriptions[RSK_SHUFFLE_MASKS]); 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], WIDGET_CVAR_COMBOBOX, RO_GOSSIP_STONES_NEED_NOTHING, false, nullptr, IMFLAG_NONE); OPT_CALLBACK(RSK_GOSSIP_STONE_HINTS, { if (CVarGetInteger(CVAR_RANDOMIZER_SETTING("GossipStoneHints"), RO_GOSSIP_STONES_NEED_NOTHING) == @@ -1445,7 +1445,14 @@ void Settings::CreateOptions() { OPT_BOOL(RSK_STARTING_ZELDAS_LETTER, "Start with Zelda's Letter", CVAR_RANDOMIZER_SETTING("StartingZeldasLetter")); OPT_BOOL(RSK_STARTING_CLAIM_CHECK, "Start with Claim Check", CVAR_RANDOMIZER_SETTING("StartingClaimCheck")); OPT_BOOL(RSK_STARTING_GERUDO_CARD, "Start with Gerudo Card", CVAR_RANDOMIZER_SETTING("StartingGerudoCard")); + OPT_BOOL(RSK_STARTING_KEATON_MASK, "Start with Keaton Mask", CVAR_RANDOMIZER_SETTING("StartingKeatonMask")); + OPT_BOOL(RSK_STARTING_SKULL_MASK, "Start with Skull Mask", CVAR_RANDOMIZER_SETTING("StartingSkullMask")); + OPT_BOOL(RSK_STARTING_SPOOKY_MASK, "Start with Spooky Mask", CVAR_RANDOMIZER_SETTING("StartingSpookyMask")); OPT_BOOL(RSK_STARTING_BUNNY_HOOD, "Start with Bunny Hood", CVAR_RANDOMIZER_SETTING("StartingBunnyHood")); + OPT_BOOL(RSK_STARTING_GORON_MASK, "Start with Goron Mask", CVAR_RANDOMIZER_SETTING("StartingGoronMask")); + OPT_BOOL(RSK_STARTING_ZORA_MASK, "Start with Zora Mask", CVAR_RANDOMIZER_SETTING("StartingZoraMask")); + OPT_BOOL(RSK_STARTING_GERUDO_MASK, "Start with Gerudo Mask", CVAR_RANDOMIZER_SETTING("StartingGerudoMask")); + OPT_BOOL(RSK_STARTING_MASK_OF_TRUTH, "Start with Mask of Truth", CVAR_RANDOMIZER_SETTING("StartingMaskOfTruth")); OPT_U8(RSK_STARTING_BIGGORON_SWORD, "Start with Biggoron's Sword", {"Off", "Giant's Knife", "Biggoron's Sword"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StartingBiggoronSword"), "", WIDGET_CVAR_COMBOBOX, 0); OPT_BOOL(RSK_FULL_WALLETS, "Full Wallets", {"No", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FullWallets"), mOptionDescriptions[RSK_FULL_WALLETS], WIDGET_CVAR_CHECKBOX, RO_GENERIC_OFF); OPT_BOOL(RSK_STARTING_ZELDAS_LULLABY, "Start with Zelda's Lullaby", CVAR_RANDOMIZER_SETTING("StartingZeldasLullaby"), "", IMFLAG_NONE); @@ -1870,7 +1877,6 @@ void Settings::CreateOptions() { &mOptions[RSK_FULL_WALLETS], &mOptions[RSK_SLINGBOW_BREAK_BEEHIVES], &mOptions[RSK_SWORDLESS_EPONA_ITEMS], - &mOptions[RSK_MASK_QUEST], &mOptions[RSK_SKIP_CHILD_STEALTH], &mOptions[RSK_EARLY_GRANNYS_SHOP], &mOptions[RSK_SKIP_PLANTING_BEANS], @@ -2011,41 +2017,24 @@ void Settings::CreateOptions() { mOptionGroups[RSG_MENU_SECTION_BASIC_SHUFFLES] = OptionGroup::SubGroup("Shuffle Items", { - &mOptions[RSK_SHUFFLE_SONGS], - &mOptions[RSK_SHUFFLE_TOKENS], - &mOptions[RSK_SHUFFLE_KOKIRI_SWORD], - &mOptions[RSK_SHUFFLE_MASTER_SWORD], - &mOptions[RSK_SHUFFLE_OCARINA], - &mOptions[RSK_SHUFFLE_WEIRD_EGG], - &mOptions[RSK_SHUFFLE_ZELDAS_LETTER], - &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], - &mOptions[RSK_FISHSANITY], - &mOptions[RSK_FISHSANITY_POND_COUNT], - &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], - &mOptions[RSK_SHUFFLE_GRASS], - &mOptions[RSK_SHUFFLE_CRATES], - &mOptions[RSK_SHUFFLE_BOULDERS], - &mOptions[RSK_SHUFFLE_ROCKS], - &mOptions[RSK_SHUFFLE_TREES], - &mOptions[RSK_SHUFFLE_BUSHES], - &mOptions[RSK_SHUFFLE_ICICLES], - &mOptions[RSK_SHUFFLE_RED_ICE], - &mOptions[RSK_SHUFFLE_SIGNS], - &mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES], - &mOptions[RSK_SHUFFLE_ADULT_TRADE], - &mOptions[RSK_SHUFFLE_CHEST_MINIGAME], - &mOptions[RSK_SHUFFLE_100_GS_REWARD], - &mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES], - &mOptions[RSK_SHUFFLE_STONE_FAIRIES], - &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], - &mOptions[RSK_SHUFFLE_SONG_FAIRIES], - &mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES], + &mOptions[RSK_SHUFFLE_SONGS], &mOptions[RSK_SHUFFLE_TOKENS], + &mOptions[RSK_SHUFFLE_KOKIRI_SWORD], &mOptions[RSK_SHUFFLE_MASTER_SWORD], + &mOptions[RSK_SHUFFLE_OCARINA], &mOptions[RSK_SHUFFLE_WEIRD_EGG], + &mOptions[RSK_SHUFFLE_ZELDAS_LETTER], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], + &mOptions[RSK_SHUFFLE_MASKS], &mOptions[RSK_FISHSANITY], + &mOptions[RSK_FISHSANITY_POND_COUNT], &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], + &mOptions[RSK_SHUFFLE_GRASS], &mOptions[RSK_SHUFFLE_CRATES], + &mOptions[RSK_SHUFFLE_BOULDERS], &mOptions[RSK_SHUFFLE_ROCKS], + &mOptions[RSK_SHUFFLE_TREES], &mOptions[RSK_SHUFFLE_BUSHES], + &mOptions[RSK_SHUFFLE_ICICLES], &mOptions[RSK_SHUFFLE_RED_ICE], + &mOptions[RSK_SHUFFLE_SIGNS], &mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES], + &mOptions[RSK_SHUFFLE_ADULT_TRADE], &mOptions[RSK_SHUFFLE_CHEST_MINIGAME], + &mOptions[RSK_SHUFFLE_100_GS_REWARD], &mOptions[RSK_SHUFFLE_FOUNTAIN_FAIRIES], + &mOptions[RSK_SHUFFLE_STONE_FAIRIES], &mOptions[RSK_SHUFFLE_BEAN_FAIRIES], + &mOptions[RSK_SHUFFLE_SONG_FAIRIES], &mOptions[RSK_SHUFFLE_BUTTERFLY_FAIRIES], }, WidgetContainerType::SECTION); mOptionGroups[RSG_MENU_COLUMN_BASIC_SHUFFLES] = @@ -2283,6 +2272,7 @@ void Settings::CreateOptions() { &mOptions[RSK_SHUFFLE_WEIRD_EGG], &mOptions[RSK_SHUFFLE_ZELDAS_LETTER], &mOptions[RSK_SHUFFLE_GERUDO_MEMBERSHIP_CARD], + &mOptions[RSK_SHUFFLE_MASKS], &mOptions[RSK_SHUFFLE_MERCHANTS], &mOptions[RSK_MERCHANT_PRICES], &mOptions[RSK_MERCHANT_PRICES_FIXED_PRICE], @@ -2357,27 +2347,30 @@ void Settings::CreateOptions() { &mOptions[RSK_KEYRINGS_GANONS_CASTLE], &mOptions[RSK_KEYRINGS_CHEST_GAME], }); - mOptionGroups[RSG_STARTING_ITEMS] = - OptionGroup::SubGroup("Items", { &mOptions[RSK_STARTING_OCARINA], &mOptions[RSK_STARTING_KOKIRI_SWORD], - &mOptions[RSK_STARTING_MASTER_SWORD], &mOptions[RSK_STARTING_DEKU_SHIELD], - &mOptions[RSK_STARTING_HYLIAN_SHIELD], &mOptions[RSK_STARTING_MIRROR_SHIELD], - &mOptions[RSK_STARTING_GORON_TUNIC], &mOptions[RSK_STARTING_ZORA_TUNIC], - &mOptions[RSK_STARTING_IRON_BOOTS], &mOptions[RSK_STARTING_HOVER_BOOTS], - &mOptions[RSK_STARTING_MEGATON_HAMMER], &mOptions[RSK_STARTING_BOOMERANG], - &mOptions[RSK_STARTING_LENS_OF_TRUTH], &mOptions[RSK_STARTING_DINS_FIRE], - &mOptions[RSK_STARTING_FARORES_WIND], &mOptions[RSK_STARTING_NAYRUS_LOVE], - &mOptions[RSK_STARTING_FIRE_ARROWS], &mOptions[RSK_STARTING_ICE_ARROWS], - &mOptions[RSK_STARTING_LIGHT_ARROWS], &mOptions[RSK_STARTING_STONE_OF_AGONY], - &mOptions[RSK_STARTING_HOOKSHOT], &mOptions[RSK_STARTING_BOW], - &mOptions[RSK_STARTING_SLINGSHOT], &mOptions[RSK_STARTING_BOMB_BAG], - &mOptions[RSK_STARTING_STRENGTH], &mOptions[RSK_STARTING_SCALE], - &mOptions[RSK_STARTING_WALLET], &mOptions[RSK_STARTING_MAGIC_METER], - &mOptions[RSK_STARTING_BOMBCHU_BAG], &mOptions[RSK_STARTING_BOTTLE_1], - &mOptions[RSK_STARTING_BOTTLE_2], &mOptions[RSK_STARTING_BOTTLE_3], - &mOptions[RSK_STARTING_BOTTLE_4], &mOptions[RSK_STARTING_WEIRD_EGG], - &mOptions[RSK_STARTING_ZELDAS_LETTER], &mOptions[RSK_STARTING_CLAIM_CHECK], - &mOptions[RSK_STARTING_GERUDO_CARD], &mOptions[RSK_STARTING_BIGGORON_SWORD], - &mOptions[RSK_STARTING_BUNNY_HOOD] }); + mOptionGroups[RSG_STARTING_ITEMS] = OptionGroup::SubGroup( + "Items", { &mOptions[RSK_STARTING_OCARINA], &mOptions[RSK_STARTING_KOKIRI_SWORD], + &mOptions[RSK_STARTING_MASTER_SWORD], &mOptions[RSK_STARTING_DEKU_SHIELD], + &mOptions[RSK_STARTING_HYLIAN_SHIELD], &mOptions[RSK_STARTING_MIRROR_SHIELD], + &mOptions[RSK_STARTING_GORON_TUNIC], &mOptions[RSK_STARTING_ZORA_TUNIC], + &mOptions[RSK_STARTING_IRON_BOOTS], &mOptions[RSK_STARTING_HOVER_BOOTS], + &mOptions[RSK_STARTING_MEGATON_HAMMER], &mOptions[RSK_STARTING_BOOMERANG], + &mOptions[RSK_STARTING_LENS_OF_TRUTH], &mOptions[RSK_STARTING_DINS_FIRE], + &mOptions[RSK_STARTING_FARORES_WIND], &mOptions[RSK_STARTING_NAYRUS_LOVE], + &mOptions[RSK_STARTING_FIRE_ARROWS], &mOptions[RSK_STARTING_ICE_ARROWS], + &mOptions[RSK_STARTING_LIGHT_ARROWS], &mOptions[RSK_STARTING_STONE_OF_AGONY], + &mOptions[RSK_STARTING_HOOKSHOT], &mOptions[RSK_STARTING_BOW], + &mOptions[RSK_STARTING_SLINGSHOT], &mOptions[RSK_STARTING_BOMB_BAG], + &mOptions[RSK_STARTING_STRENGTH], &mOptions[RSK_STARTING_SCALE], + &mOptions[RSK_STARTING_WALLET], &mOptions[RSK_STARTING_MAGIC_METER], + &mOptions[RSK_STARTING_BOMBCHU_BAG], &mOptions[RSK_STARTING_BOTTLE_1], + &mOptions[RSK_STARTING_BOTTLE_2], &mOptions[RSK_STARTING_BOTTLE_3], + &mOptions[RSK_STARTING_BOTTLE_4], &mOptions[RSK_STARTING_WEIRD_EGG], + &mOptions[RSK_STARTING_ZELDAS_LETTER], &mOptions[RSK_STARTING_CLAIM_CHECK], + &mOptions[RSK_STARTING_GERUDO_CARD], &mOptions[RSK_STARTING_BIGGORON_SWORD], + &mOptions[RSK_STARTING_BUNNY_HOOD], &mOptions[RSK_STARTING_KEATON_MASK], + &mOptions[RSK_STARTING_SKULL_MASK], &mOptions[RSK_STARTING_SPOOKY_MASK], + &mOptions[RSK_STARTING_GORON_MASK], &mOptions[RSK_STARTING_ZORA_MASK], + &mOptions[RSK_STARTING_GERUDO_MASK], &mOptions[RSK_STARTING_MASK_OF_TRUTH] }); mOptionGroups[RSG_STARTING_SONGS] = OptionGroup::SubGroup("Ocarina Songs", { &mOptions[RSK_STARTING_ZELDAS_LULLABY], @@ -3159,6 +3152,13 @@ void Settings::RandomizeAllSettings() { case RSK_STARTING_GERUDO_CARD: case RSK_STARTING_BIGGORON_SWORD: case RSK_STARTING_BUNNY_HOOD: + case RSK_STARTING_KEATON_MASK: + case RSK_STARTING_SKULL_MASK: + case RSK_STARTING_SPOOKY_MASK: + case RSK_STARTING_GORON_MASK: + case RSK_STARTING_ZORA_MASK: + case RSK_STARTING_GERUDO_MASK: + case RSK_STARTING_MASK_OF_TRUTH: continue; default: break; diff --git a/soh/soh/SohGui/SohMenuEnhancements.cpp b/soh/soh/SohGui/SohMenuEnhancements.cpp index 5efbdcdba2..84db38733c 100644 --- a/soh/soh/SohGui/SohMenuEnhancements.cpp +++ b/soh/soh/SohGui/SohMenuEnhancements.cpp @@ -1014,10 +1014,8 @@ void SohMenu::AddMenuEnhancements() { AddWidget(path, "Mask Select in Inventory", WIDGET_CVAR_CHECKBOX) .CVar(CVAR_ENHANCEMENT("MaskSelect")) .PreFunc([](WidgetInfo& info) { - info.options->disabled = - OTRGlobals::Instance->gRandoContext->GetOption(RSK_MASK_QUEST).IsNot(RO_MASK_QUEST_VANILLA); - info.options->disabledTooltip = - "This setting is forcefully enabled when Mask Quest is Completed from the start or Shuffled."; + info.options->disabled = IS_RANDO; + info.options->disabledTooltip = "This setting is forcefully enabled in randomizer."; }) .Options(CheckboxOptions().Tooltip( "After completing the mask trading sub-quest, press A and any direction on the mask " diff --git a/soh/soh/SohGui/SohMenuStartingItems.cpp b/soh/soh/SohGui/SohMenuStartingItems.cpp index 173f9531dd..5fbb1a31a9 100644 --- a/soh/soh/SohGui/SohMenuStartingItems.cpp +++ b/soh/soh/SohGui/SohMenuStartingItems.cpp @@ -311,8 +311,21 @@ void DrawStartingItemsMenu(WidgetInfo& info) { "you get the item Impa would give and skip everything up to meeting Zelda."); } } + StartingItemToggle(RSK_STARTING_KEATON_MASK, ITEM_MASK_KEATON); + ImGui::SameLine(); + StartingItemToggle(RSK_STARTING_SKULL_MASK, ITEM_MASK_SKULL); + ImGui::SameLine(); + StartingItemToggle(RSK_STARTING_SPOOKY_MASK, ITEM_MASK_SPOOKY); ImGui::SameLine(); StartingItemToggle(RSK_STARTING_BUNNY_HOOD, ITEM_MASK_BUNNY); + ImGui::SameLine(); + StartingItemToggle(RSK_STARTING_GORON_MASK, ITEM_MASK_GORON); + ImGui::SameLine(); + StartingItemToggle(RSK_STARTING_ZORA_MASK, ITEM_MASK_ZORA); + ImGui::SameLine(); + StartingItemToggle(RSK_STARTING_GERUDO_MASK, ITEM_MASK_GERUDO); + ImGui::SameLine(); + StartingItemToggle(RSK_STARTING_MASK_OF_TRUTH, ITEM_MASK_TRUTH); ImGui::SeparatorText("Songs"); StartingSongToggle(RSK_STARTING_ZELDAS_LULLABY, QUEST_SONG_LULLABY); diff --git a/soh/soh/config/ConfigUpdaters.cpp b/soh/soh/config/ConfigUpdaters.cpp index b27223eb02..2f6d9b7176 100644 --- a/soh/soh/config/ConfigUpdaters.cpp +++ b/soh/soh/config/ConfigUpdaters.cpp @@ -1671,5 +1671,23 @@ void ConfigVersion7Updater::Update(Ship::Config* conf) { // Kakariko Gate setting removed; the gate opens when starting with an unshuffled letter CVarClear("gRandoSettings.KakarikoGate"); + + // Mask Quest: Completed was dropped, it's now starting with every mask, and the setting is Shuffle Masks + switch (CVarGetInteger("gRandoSettings.CompleteMaskQuest", 0)) { + case 1: // Completed + CVarSetInteger("gRandoSettings.StartingKeatonMask", 1); + CVarSetInteger("gRandoSettings.StartingSkullMask", 1); + CVarSetInteger("gRandoSettings.StartingSpookyMask", 1); + CVarSetInteger("gRandoSettings.StartingBunnyHood", 1); + CVarSetInteger("gRandoSettings.StartingGoronMask", 1); + CVarSetInteger("gRandoSettings.StartingZoraMask", 1); + CVarSetInteger("gRandoSettings.StartingGerudoMask", 1); + CVarSetInteger("gRandoSettings.StartingMaskOfTruth", 1); + [[fallthrough]]; + case 2: // Shuffle + CVarSetInteger("gRandoSettings.ShuffleMasks", 1); + break; + } + CVarClear("gRandoSettings.CompleteMaskQuest"); } } // namespace SOH 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 073e10c54f..2209a1e774 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 @@ -322,20 +322,14 @@ void KaleidoScope_HandleItemCycleExtras(PlayState* play, u8 slot, bool canCycle, bool CanMaskSelect() { if (IS_RANDO) { - return ((CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0) || - Randomizer_GetSettingValue(RSK_MASK_QUEST) != RO_MASK_QUEST_VANILLA) && - Flags_GetRandomizerInf(RAND_INF_ZELDAS_LETTER) && - Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD)) || - Randomizer_GetSettingValue(RSK_MASK_QUEST) == RO_MASK_QUEST_SHUFFLE; + return true; } - // only allow mask select when: // the shop is open: // * zelda's letter check: Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) // * kak gate check: Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD) // and the mask quest is complete: Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE) - return (CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0) || - Randomizer_GetSettingValue(RSK_MASK_QUEST) != RO_MASK_QUEST_VANILLA) && + return CVarGetInteger(CVAR_ENHANCEMENT("MaskSelect"), 0) && Flags_GetEventChkInf(EVENTCHKINF_PAID_BACK_BUNNY_HOOD_FEE) && Flags_GetEventChkInf(EVENTCHKINF_OBTAINED_ZELDAS_LETTER) && Flags_GetInfTable(INFTABLE_SHOWED_ZELDAS_LETTER_TO_GATE_GUARD); @@ -344,7 +338,7 @@ bool CanMaskSelect() { void KaleidoScope_HandleItemCycles(PlayState* play) { // handle the mask select KaleidoScope_HandleItemCycleExtras( - play, SLOT_TRADE_CHILD, IS_RANDO || CanMaskSelect(), + play, SLOT_TRADE_CHILD, CanMaskSelect(), IS_RANDO ? Randomizer_GetPrevChildTradeItem() : (INV_CONTENT(ITEM_TRADE_CHILD) <= ITEM_MASK_KEATON || INV_CONTENT(ITEM_TRADE_CHILD) > ITEM_MASK_TRUTH ? ITEM_MASK_TRUTH @@ -368,7 +362,7 @@ void KaleidoScope_HandleItemCycles(PlayState* play) { void KaleidoScope_DrawItemCycles(PlayState* play) { // draw the mask select KaleidoScope_DrawItemCycleExtras( - play, SLOT_TRADE_CHILD, IS_RANDO || CanMaskSelect(), + play, SLOT_TRADE_CHILD, CanMaskSelect(), IS_RANDO ? Randomizer_GetPrevChildTradeItem() : (INV_CONTENT(ITEM_TRADE_CHILD) <= ITEM_MASK_KEATON || INV_CONTENT(ITEM_TRADE_CHILD) > ITEM_MASK_TRUTH ? ITEM_MASK_TRUTH