diff --git a/soh/assets/custom/objects/object_housekey/Hilite_new b/soh/assets/custom/objects/object_housekey/Hilite_new
new file mode 100644
index 000000000..5438695fa
Binary files /dev/null and b/soh/assets/custom/objects/object_housekey/Hilite_new differ
diff --git a/soh/assets/custom/objects/object_housekey/HouseKey_Tag b/soh/assets/custom/objects/object_housekey/HouseKey_Tag
new file mode 100644
index 000000000..4939ef966
Binary files /dev/null and b/soh/assets/custom/objects/object_housekey/HouseKey_Tag differ
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL b/soh/assets/custom/objects/object_housekey/gHouseKeyDL
new file mode 100644
index 000000000..3d6787c3c
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_0 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_0
new file mode 100644
index 000000000..4c8002a6a
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_0
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_1 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_1
new file mode 100644
index 000000000..06fdafc2d
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_1
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_2 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_2
new file mode 100644
index 000000000..a606298d1
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_tri_2
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_0 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_0
new file mode 100644
index 000000000..cd0885c1c
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_0
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_1 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_1
new file mode 100644
index 000000000..c4f2d8850
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_1
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_2 b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_2
new file mode 100644
index 000000000..dc377511e
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/gHouseKeyDL_vtx_2
@@ -0,0 +1,93 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeymetal b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeymetal
new file mode 100644
index 000000000..90c65bd06
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeymetal
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeyringmetal b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeyringmetal
new file mode 100644
index 000000000..d7d19e315
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeyringmetal
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeytag b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeytag
new file mode 100644
index 000000000..05f2afc64
--- /dev/null
+++ b/soh/assets/custom/objects/object_housekey/mat_gHouseKeyDL_f3dlite_housekeytag
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/soh/assets/soh_assets.h b/soh/assets/soh_assets.h
index 78f4d281e..4cf6a4266 100644
--- a/soh/assets/soh_assets.h
+++ b/soh/assets/soh_assets.h
@@ -237,6 +237,9 @@ static const ALIGN_ASSET(2) char gKeyringKeysShadowTempleMQDL[] = dgKeyringKeysS
#define dgKeyringKeysGanonsCastleMQDL "__OTR__objects/object_keyring/gKeyringKeysGanonsCastleMQDL"
static const ALIGN_ASSET(2) char gKeyringKeysGanonsCastleMQDL[] = dgKeyringKeysGanonsCastleMQDL;
+#define dgHouseKeyDL "__OTR__objects/object_housekey/gHouseKeyDL"
+static const ALIGN_ASSET(2) char gHouseKeyDL[] = dgHouseKeyDL;
+
// overlays
#define dgOptionsDividerChangeLangVtx "__OTR__overlays/ovl_file_choose/gOptionsDividerChangeLangVtx"
static const ALIGN_ASSET(2) char gOptionsDividerChangeLangVtx[] = dgOptionsDividerChangeLangVtx;
diff --git a/soh/soh/Enhancements/debugger/debugSaveEditor.h b/soh/soh/Enhancements/debugger/debugSaveEditor.h
index 8eb939ec8..2a77b9b0a 100644
--- a/soh/soh/Enhancements/debugger/debugSaveEditor.h
+++ b/soh/soh/Enhancements/debugger/debugSaveEditor.h
@@ -1551,6 +1551,55 @@ const std::vector flagTables = {
{ RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY, "RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY" },
{ RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY, "RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY" },
+
+ { RAND_INF_GUARD_HOUSE_UNLOCKED, "RAND_INF_GUARD_HOUSE_UNLOCKED" },
+ { RAND_INF_GUARD_HOUSE_KEY_OBTAINED, "RAND_INF_GUARD_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_MARKET_BAZAAR_UNLOCKED, "RAND_INF_MARKET_BAZAAR_UNLOCKED" },
+ { RAND_INF_MARKET_BAZAAR_KEY_OBTAINED, "RAND_INF_MARKET_BAZAAR_KEY_OBTAINED" },
+ { RAND_INF_MARKET_POTION_SHOP_UNLOCKED, "RAND_INF_MARKET_POTION_SHOP_UNLOCKED" },
+ { RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED, "RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED" },
+ { RAND_INF_MASK_SHOP_UNLOCKED, "RAND_INF_MASK_SHOP_UNLOCKED" },
+ { RAND_INF_MASK_SHOP_KEY_OBTAINED, "RAND_INF_MASK_SHOP_KEY_OBTAINED" },
+ { RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED, "RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED" },
+ { RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED, "RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED" },
+ { RAND_INF_BOMBCHU_BOWLING_UNLOCKED, "RAND_INF_BOMBCHU_BOWLING_UNLOCKED" },
+ { RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED, "RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED" },
+ { RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED, "RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED" },
+ { RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED, "RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED" },
+ { RAND_INF_BOMBCHU_SHOP_UNLOCKED, "RAND_INF_BOMBCHU_SHOP_UNLOCKED" },
+ { RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED, "RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED" },
+ { RAND_INF_RICHARDS_HOUSE_UNLOCKED, "RAND_INF_RICHARDS_HOUSE_UNLOCKED" },
+ { RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED, "RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_ALLEY_HOUSE_UNLOCKED, "RAND_INF_ALLEY_HOUSE_UNLOCKED" },
+ { RAND_INF_ALLEY_HOUSE_KEY_OBTAINED, "RAND_INF_ALLEY_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_KAK_BAZAAR_UNLOCKED, "RAND_INF_KAK_BAZAAR_UNLOCKED" },
+ { RAND_INF_KAK_BAZAAR_KEY_OBTAINED, "RAND_INF_KAK_BAZAAR_KEY_OBTAINED" },
+ { RAND_INF_KAK_POTION_SHOP_UNLOCKED, "RAND_INF_KAK_POTION_SHOP_UNLOCKED" },
+ { RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED, "RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED" },
+ { RAND_INF_BOSS_HOUSE_UNLOCKED, "RAND_INF_BOSS_HOUSE_UNLOCKED" },
+ { RAND_INF_BOSS_HOUSE_KEY_OBTAINED, "RAND_INF_BOSS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED, "RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED" },
+ { RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED, "RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED" },
+ { RAND_INF_SKULLTULA_HOUSE_UNLOCKED, "RAND_INF_SKULLTULA_HOUSE_UNLOCKED" },
+ { RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED, "RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_IMPAS_HOUSE_UNLOCKED, "RAND_INF_IMPAS_HOUSE_UNLOCKED" },
+ { RAND_INF_IMPAS_HOUSE_KEY_OBTAINED, "RAND_INF_IMPAS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_WINDMILL_UNLOCKED, "RAND_INF_WINDMILL_UNLOCKED" },
+ { RAND_INF_WINDMILL_KEY_OBTAINED, "RAND_INF_WINDMILL_KEY_OBTAINED" },
+ { RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED, "RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED" },
+ { RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED, "RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED" },
+ { RAND_INF_DAMPES_HUT_UNLOCKED, "RAND_INF_DAMPES_HUT_UNLOCKED" },
+ { RAND_INF_DAMPES_HUT_KEY_OBTAINED, "RAND_INF_DAMPES_HUT_KEY_OBTAINED" },
+ { RAND_INF_TALONS_HOUSE_UNLOCKED, "RAND_INF_TALONS_HOUSE_UNLOCKED" },
+ { RAND_INF_TALONS_HOUSE_KEY_OBTAINED, "RAND_INF_TALONS_HOUSE_KEY_OBTAINED" },
+ { RAND_INF_STABLES_UNLOCKED, "RAND_INF_STABLES_UNLOCKED" },
+ { RAND_INF_STABLES_KEY_OBTAINED, "RAND_INF_STABLES_KEY_OBTAINED" },
+ { RAND_INF_BACK_TOWER_UNLOCKED, "RAND_INF_BACK_TOWER_UNLOCKED" },
+ { RAND_INF_BACK_TOWER_KEY_OBTAINED, "RAND_INF_BACK_TOWER_KEY_OBTAINED" },
+ { RAND_INF_HYLIA_LAB_UNLOCKED, "RAND_INF_HYLIA_LAB_UNLOCKED" },
+ { RAND_INF_HYLIA_LAB_KEY_OBTAINED, "RAND_INF_HYLIA_LAB_KEY_OBTAINED" },
+ { RAND_INF_FISHING_HOLE_UNLOCKED, "RAND_INF_FISHING_HOLE_UNLOCKED" },
+ { RAND_INF_FISHING_HOLE_KEY_OBTAINED, "RAND_INF_FISHING_HOLE_KEY_OBTAINED" },
} },
};
diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor.h b/soh/soh/Enhancements/game-interactor/GameInteractor.h
index 8c449ccdb..8810a2301 100644
--- a/soh/soh/Enhancements/game-interactor/GameInteractor.h
+++ b/soh/soh/Enhancements/game-interactor/GameInteractor.h
@@ -304,6 +304,13 @@ typedef enum {
VB_FROGS_GO_TO_IDLE,
// Vanilla condition: var >= gSaveContext.health) && (gSaveContext.health > 0
VB_HEALTH_METER_BE_CRITICAL,
+ VB_CONSUME_SMALL_KEY,
+ // Vanilla condition: gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] <= 0
+ VB_NOT_HAVE_SMALL_KEY,
+ // Vanilla condition: !Flags_GetSwitch(play, this->actor.params & 0x3F)
+ VB_DOOR_BE_LOCKED,
+ // Vanilla condition: ((doorActor->params >> 7) & 7) == 3
+ VB_DOOR_PLAY_SCENE_TRANSITION,
/*** Play Cutscenes ***/
diff --git a/soh/soh/Enhancements/mods.cpp b/soh/soh/Enhancements/mods.cpp
index 1753dc30c..90b8272da 100644
--- a/soh/soh/Enhancements/mods.cpp
+++ b/soh/soh/Enhancements/mods.cpp
@@ -1133,7 +1133,7 @@ void RegisterOpenAllHours() {
GameInteractor::Instance->RegisterGameHook([](void* refActor) {
Actor* actor = static_cast(refActor);
- if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR)) {
+ if (CVarGetInteger(CVAR_ENHANCEMENT("OpenAllHours"), 0) && (actor->id == ACTOR_EN_DOOR) && (!IS_RANDO || !OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS))) {
switch (actor->params) {
case 4753: // Night Market Bazaar
case 1678: // Night Potion Shop
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 89c290a40..867da2b2c 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
@@ -1361,7 +1361,18 @@ void StaticData::HintTable_Init_Item() {
// /*spanish*/un destructor de cerraduras final
CustomMessage("a final lockpick", /*german*/"ein finaler Dietrich", /*french*/"un crochet à porte final")});
// /*spanish*/una apertura portentosa final
-
+ hintTextTable[RHT_OVERWORLD_KEY] = HintText(CustomMessage("an Overworld Key", /*german*/"ein Überwelt-Schlüssel", /*french*/"une clé de l'Overworld"),
+ // /*spanish*/una llave del mundo exterior
+ {
+ CustomMessage("a small key", /*german*/"ein kleiner Schlüssel", /*french*/"une petite clé")
+ // /*spanish*/una llave
+ }, {
+ CustomMessage("a key to the world", /*german*/"ein Schlüssel zur Welt", /*french*/"une clé du monde"),
+ // /*spanish*/una llave al mundo
+ CustomMessage("a key to the kingdom", /*german*/"ein Schlüssel zum Königreich", /*french*/"une clé du royaume"),
+ // /*spanish*/una llave al reino
+ CustomMessage("a key to the universe", /*german*/"ein Schlüssel zum Universum", /*french*/"une clé de l'univers")});
+ // /*spanish*/una llave al universo
hintTextTable[RHT_FOREST_TEMPLE_KEY_RING] = HintText(CustomMessage("a Forest Temple Key Ring", /*german*/"ein Schlüsselbund des Waldtempels", /*french*/"un trousseau de clés du Temple de la Forêt"),
// /*spanish*/un llavero del Templo del Bosque
{
diff --git a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
index cee278220..b09d57dc4 100644
--- a/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
+++ b/soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
@@ -1276,6 +1276,33 @@ void GenerateItemPool() {
}
}
+ if (ctx->GetOption(RSK_LOCK_OVERWORLD_DOORS)) {
+ AddItemToPool(ItemPool, RG_GUARD_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_MARKET_BAZAAR_KEY);
+ AddItemToPool(ItemPool, RG_MARKET_POTION_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_MASK_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_MARKET_SHOOTING_GALLERY_KEY);
+ AddItemToPool(ItemPool, RG_BOMBCHU_BOWLING_KEY);
+ AddItemToPool(ItemPool, RG_TREASURE_CHEST_GAME_BUILDING_KEY);
+ AddItemToPool(ItemPool, RG_BOMBCHU_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_RICHARDS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_ALLEY_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_KAK_BAZAAR_KEY);
+ AddItemToPool(ItemPool, RG_KAK_POTION_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_BOSS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_GRANNYS_POTION_SHOP_KEY);
+ AddItemToPool(ItemPool, RG_SKULLTULA_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_IMPAS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_WINDMILL_KEY);
+ AddItemToPool(ItemPool, RG_KAK_SHOOTING_GALLERY_KEY);
+ AddItemToPool(ItemPool, RG_DAMPES_HUT_KEY);
+ AddItemToPool(ItemPool, RG_TALONS_HOUSE_KEY);
+ AddItemToPool(ItemPool, RG_STABLES_KEY);
+ AddItemToPool(ItemPool, RG_BACK_TOWER_KEY);
+ AddItemToPool(ItemPool, RG_HYLIA_LAB_KEY);
+ AddItemToPool(ItemPool, RG_FISHING_HOLE_KEY);
+ }
+
//Shopsanity
if (
ctx->GetOption(RSK_SHOPSANITY).Is(RO_SHOPSANITY_OFF) ||
diff --git a/soh/soh/Enhancements/randomizer/LockOverworldDoors.cpp b/soh/soh/Enhancements/randomizer/LockOverworldDoors.cpp
new file mode 100644
index 000000000..e48a5763f
--- /dev/null
+++ b/soh/soh/Enhancements/randomizer/LockOverworldDoors.cpp
@@ -0,0 +1,154 @@
+#include
+#include "soh/OTRGlobals.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
+#include "soh/ShipInit.hpp"
+
+extern "C" {
+extern PlayState* gPlayState;
+#include "macros.h"
+#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
+}
+
+#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
+
+using SceneDoorParamsPair = std::pair;
+std::map lookupTable = {
+ {{ SCENE_MARKET_ENTRANCE_DAY, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_ENTRANCE_NIGHT, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_ENTRANCE_RUINS, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_GUARD_HOUSE, 447 }, RAND_INF_GUARD_HOUSE_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 4543 }, RAND_INF_MARKET_BAZAAR_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 4753 }, RAND_INF_MARKET_BAZAAR_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 1471 }, RAND_INF_MARKET_POTION_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 1678 }, RAND_INF_MARKET_POTION_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 3519 }, RAND_INF_MASK_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 3728 }, RAND_INF_MASK_SHOP_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 2495 }, RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 2703 }, RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_SHOOTING_GALLERY, 447 }, RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 5567 }, RAND_INF_BOMBCHU_BOWLING_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 5567 }, RAND_INF_BOMBCHU_BOWLING_UNLOCKED },
+ {{ SCENE_BOMBCHU_BOWLING_ALLEY, 447 }, RAND_INF_BOMBCHU_BOWLING_UNLOCKED },
+ {{ SCENE_MARKET_DAY, 653 }, RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED },
+ {{ SCENE_MARKET_NIGHT, 447 }, RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED },
+ {{ SCENE_TREASURE_BOX_SHOP, 6591 }, RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_DAY, 2689 }, RAND_INF_BOMBCHU_SHOP_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_NIGHT, 2495 }, RAND_INF_BOMBCHU_SHOP_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_DAY, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_NIGHT, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_DOG_LADY_HOUSE, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_DOG_LADY_HOUSE, 447 }, RAND_INF_RICHARDS_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_HOUSE, 447 }, RAND_INF_ALLEY_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_DAY, 1665 }, RAND_INF_ALLEY_HOUSE_UNLOCKED },
+ {{ SCENE_BACK_ALLEY_NIGHT, 1471 }, RAND_INF_ALLEY_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 6801 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Adult Night
+ {{ SCENE_KAKARIKO_VILLAGE, 6591 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Adult Day
+ {{ SCENE_KAKARIKO_VILLAGE, 6813 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Child Day
+ {{ SCENE_KAKARIKO_VILLAGE, 6814 }, RAND_INF_KAK_BAZAAR_UNLOCKED }, // Child Night
+ {{ SCENE_KAKARIKO_VILLAGE, 8871 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Child Day/Night Rear
+ {{ SCENE_KAKARIKO_VILLAGE, 8846 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Adult Night Rear
+ {{ SCENE_KAKARIKO_VILLAGE, 8639 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Adult Day Rear
+ {{ SCENE_KAKARIKO_VILLAGE, 7822 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Adult Night
+ {{ SCENE_KAKARIKO_VILLAGE, 7615 }, RAND_INF_KAK_POTION_SHOP_UNLOCKED }, // Child Day/Night and Adult Day
+ {{ SCENE_KAKARIKO_VILLAGE, 2495 }, RAND_INF_BOSS_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_CENTER_GUEST_HOUSE, 447 }, RAND_INF_BOSS_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 3750 }, RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED }, // Child
+ {{ SCENE_KAKARIKO_VILLAGE, 3519 }, RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED }, // Adult
+ {{ SCENE_POTION_SHOP_GRANNY, 447 }, RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 5567 }, RAND_INF_SKULLTULA_HOUSE_UNLOCKED },
+ {{ SCENE_HOUSE_OF_SKULLTULA, 447 }, RAND_INF_SKULLTULA_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 1471 }, RAND_INF_IMPAS_HOUSE_UNLOCKED },
+ {{ SCENE_IMPAS_HOUSE, 447 }, RAND_INF_IMPAS_HOUSE_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 447 }, RAND_INF_WINDMILL_UNLOCKED },
+ {{ SCENE_WINDMILL_AND_DAMPES_GRAVE, 2495 }, RAND_INF_WINDMILL_UNLOCKED },
+ {{ SCENE_KAKARIKO_VILLAGE, 4543 }, RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED }, // Day
+ {{ SCENE_KAKARIKO_VILLAGE, 4751 }, RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED }, // Night
+ {{ SCENE_SHOOTING_GALLERY, 447 }, RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED },
+ {{ SCENE_GRAVEYARD, 645 }, RAND_INF_DAMPES_HUT_UNLOCKED }, // Child Day
+ {{ SCENE_GRAVEYARD, 447 }, RAND_INF_DAMPES_HUT_UNLOCKED }, // Child Evening & Adult
+ {{ SCENE_GRAVEYARD, 774 }, RAND_INF_DAMPES_HUT_UNLOCKED }, // Child Night (After Dampes Tour)
+ {{ SCENE_GRAVEKEEPERS_HUT, 447 }, RAND_INF_DAMPES_HUT_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 2495 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 2473 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 2729 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_BUILDINGS, 1471 }, RAND_INF_TALONS_HOUSE_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 1471 }, RAND_INF_STABLES_UNLOCKED },
+ {{ SCENE_STABLE, 447 }, RAND_INF_STABLES_UNLOCKED },
+ {{ SCENE_LON_LON_RANCH, 447 }, RAND_INF_BACK_TOWER_UNLOCKED },
+ {{ SCENE_LON_LON_BUILDINGS, 447 }, RAND_INF_BACK_TOWER_UNLOCKED },
+ {{ SCENE_LAKE_HYLIA, 447 }, RAND_INF_HYLIA_LAB_UNLOCKED },
+ {{ SCENE_LAKESIDE_LABORATORY, 447 }, RAND_INF_HYLIA_LAB_UNLOCKED },
+ {{ SCENE_LAKE_HYLIA, 1471 }, RAND_INF_FISHING_HOLE_UNLOCKED },
+ {{ SCENE_FISHING_POND, 447 }, RAND_INF_FISHING_HOLE_UNLOCKED },
+};
+
+static void OnDoorInit(void* actorRef) {
+ EnDoor* enDoor = static_cast(actorRef);
+ enDoor->randomizerInf = RAND_INF_MAX;
+
+ auto it = lookupTable.find({gPlayState->sceneNum, enDoor->actor.params});
+ if (it != lookupTable.end()) {
+ if (it->second == RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED && gSaveContext.entranceIndex == 0x3B) {
+ // Adult shooting gallery uses same scene and door params as child, so we manually handle it
+ enDoor->randomizerInf = RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED;
+ } else {
+ enDoor->randomizerInf = it->second;
+ }
+ if (!Flags_GetRandomizerInf(enDoor->randomizerInf)) {
+ // We don't want to override checkable doors, we still want those to not be openable even if they have a key
+ if (((enDoor->actor.params >> 7) & 7) != DOOR_CHECKABLE) {
+ enDoor->actor.params = (enDoor->actor.params & ~0x380) | (DOOR_LOCKED << 7);
+ enDoor->actionFunc = EnDoor_SetupType;
+ } else {
+ enDoor->lockTimer = 10;
+ }
+ }
+ }
+}
+
+void RegisterLockOverworldDoors() {
+ bool shouldRegister = IS_RANDO && RAND_GET_OPTION(RSK_LOCK_OVERWORLD_DOORS);
+
+ COND_ID_HOOK(OnActorInit, ACTOR_EN_DOOR, shouldRegister, OnDoorInit);
+
+ COND_VB_SHOULD(VB_CONSUME_SMALL_KEY, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
+ Flags_SetRandomizerInf(enDoor->randomizerInf);
+ *should = false;
+ }
+ });
+
+ COND_VB_SHOULD(VB_NOT_HAVE_SMALL_KEY, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
+ *should = !Flags_GetRandomizerInf((RandomizerInf)(enDoor->randomizerInf + 1));
+ }
+ });
+
+ COND_VB_SHOULD(VB_DOOR_BE_LOCKED, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (enDoor->randomizerInf >= RAND_INF_GUARD_HOUSE_UNLOCKED && enDoor->randomizerInf <= RAND_INF_FISHING_HOLE_KEY_OBTAINED) {
+ *should = !Flags_GetRandomizerInf(enDoor->randomizerInf);
+ }
+ });
+
+ // The door actor uses the same param to indicate if a door should be locked or be a scene transition, so it cannot be both. Here we're
+ // overriding the check for scene transition to also check if the door is being unlocked and should be a scene transition.
+ COND_VB_SHOULD(VB_DOOR_PLAY_SCENE_TRANSITION, shouldRegister, {
+ EnDoor* enDoor = va_arg(args, EnDoor*);
+
+ if (!*should && (
+ enDoor->actor.id == ACTOR_EN_DOOR &&
+ ((enDoor->actor.params >> 7) & 7) == 1 &&
+ enDoor->randomizerInf != RAND_INF_MAX
+ )) {
+ *should = true;
+ }
+ });
+}
+
+static RegisterShipInitFunc initFunc(RegisterLockOverworldDoors, { "IS_RANDO" });
diff --git a/soh/soh/Enhancements/randomizer/draw.cpp b/soh/soh/Enhancements/randomizer/draw.cpp
index fd07fe3fd..0a89e4dae 100644
--- a/soh/soh/Enhancements/randomizer/draw.cpp
+++ b/soh/soh/Enhancements/randomizer/draw.cpp
@@ -1229,3 +1229,18 @@ extern "C" void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry*
CLOSE_DISPS(play->state.gfxCtx);
}
}
+
+extern "C" void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry) {
+ OPEN_DISPS(play->state.gfxCtx);
+
+ Gfx_SetupDL_25Opa(play->state.gfxCtx);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx, (char*)__FILE__, __LINE__),
+ G_MTX_MODELVIEW | G_MTX_LOAD);
+
+ gSPDisplayList(POLY_OPA_DISP++, (Gfx*)gHouseKeyDL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
diff --git a/soh/soh/Enhancements/randomizer/draw.h b/soh/soh/Enhancements/randomizer/draw.h
index 31ac2c1fb..3fc5c86b4 100644
--- a/soh/soh/Enhancements/randomizer/draw.h
+++ b/soh/soh/Enhancements/randomizer/draw.h
@@ -25,6 +25,7 @@ void Randomizer_DrawSkeletonKey(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawMysteryItem(PlayState* play, GetItemEntry getItemEntry);
void Randomizer_DrawBombchuBagInLogic(PlayState* play, GetItemEntry* getItemEntry);
void Randomizer_DrawBombchuBag(PlayState* play, GetItemEntry* getItemEntry);
+void Randomizer_DrawOverworldKey(PlayState* play, GetItemEntry* getItemEntry);
#define GET_ITEM_MYSTERY \
{ ITEM_NONE_FE, 0, 0, 0, 0, MOD_RANDOMIZER, MOD_RANDOMIZER, ITEM_NONE_FE, 0, false, ITEM_FROM_NPC, ITEM_CATEGORY_JUNK, ITEM_NONE_FE, MOD_RANDOMIZER, (CustomDrawFunc)Randomizer_DrawMysteryItem }
diff --git a/soh/soh/Enhancements/randomizer/hook_handlers.cpp b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
index d1ba2f9ea..689d1c396 100644
--- a/soh/soh/Enhancements/randomizer/hook_handlers.cpp
+++ b/soh/soh/Enhancements/randomizer/hook_handlers.cpp
@@ -2370,6 +2370,8 @@ void RandomizerRegisterHooks() {
static uint32_t shuffleFreestandingOnVanillaBehaviorHook = 0;
GameInteractor::Instance->RegisterGameHook([](int32_t fileNum) {
+ ShipInit::Init("IS_RANDO");
+
randomizerQueuedChecks = std::queue();
randomizerQueuedCheck = RC_UNKNOWN_CHECK;
randomizerQueuedItemEntry = GET_ITEM_NONE;
diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp
index 6aee0a775..0b94aab39 100644
--- a/soh/soh/Enhancements/randomizer/item_list.cpp
+++ b/soh/soh/Enhancements/randomizer/item_list.cpp
@@ -159,6 +159,54 @@ void Rando::StaticData::InitItemTable() {
itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey);
itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE);
+ itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_GUARD_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MARKET_BAZAAR_KEY] = Item(RG_MARKET_BAZAAR_KEY, Text{ "Market Bazaar Key", "", "Schlüssel für den Basar des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_MARKET_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MARKET_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MARKET_POTION_SHOP_KEY] = Item(RG_MARKET_POTION_SHOP_KEY, Text{ "Market Potion Shop Key", "", "Schlüssel für den Magie-Laden des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MARKET_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MARKET_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MASK_SHOP_KEY] = Item(RG_MASK_SHOP_KEY, Text{ "Mask Shop Key", "", "Schlüssel für den Maskenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MASK_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MASK_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MASK_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_MARKET_SHOOTING_GALLERY_KEY] = Item(RG_MARKET_SHOOTING_GALLERY_KEY, Text{ "Market Shooting Gallery Key", "", "Schlüssel für die Schießbude des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_MARKET_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_MARKET_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BOMBCHU_BOWLING_KEY] = Item(RG_BOMBCHU_BOWLING_KEY, Text{ "Bombchu Bowling Alley Key", "", "Schlüssel für die Minenbowlingbahn" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_BOWLING_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_BOWLING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BOMBCHU_BOWLING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY] = Item(RG_TREASURE_CHEST_GAME_BUILDING_KEY, Text{ "Treasure Chest Game Building Key", "", "Schlüssel für das Haus des Schatzkisten-Pokers" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,RHT_OVERWORLD_KEY, RG_TREASURE_CHEST_GAME_BUILDING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BOMBCHU_SHOP_KEY] = Item(RG_BOMBCHU_SHOP_KEY, Text{ "Bombchu Shop Key", "", "Schlüssel für den Krabbelminenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_SHOP_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BOMBCHU_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_RICHARDS_HOUSE_KEY] = Item(RG_RICHARDS_HOUSE_KEY, Text{ "Richard's House Key", "", "Schlüssel für das Haus von Richard" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_RICHARDS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_RICHARDS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_RICHARDS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_ALLEY_HOUSE_KEY] = Item(RG_ALLEY_HOUSE_KEY, Text{ "Alley House Key", "", "Schlüssel für das Gäßchenhaus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_ALLEY_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_ALLEY_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_ALLEY_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_KAK_BAZAAR_KEY] = Item(RG_KAK_BAZAAR_KEY, Text{ "Kakariko Bazaar Key", "", "Schlüssel für den Basar von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_KAK_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_KAK_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_KAK_POTION_SHOP_KEY] = Item(RG_KAK_POTION_SHOP_KEY, Text{ "Kakariko Potion Shop Key", "", "Schlüssel für den Magie-Laden von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_KAK_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_KAK_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BOSS_HOUSE_KEY] = Item(RG_BOSS_HOUSE_KEY, Text{ "Boss's House Key", "", "Schlüssel für das Haus des Chefs" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOSS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_BOSS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BOSS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_GRANNYS_POTION_SHOP_KEY] = Item(RG_GRANNYS_POTION_SHOP_KEY, Text{ "Granny's Potion Shop Key", "", "Schlüssel für Asas Hexenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GRANNYS_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_GRANNYS_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_GRANNYS_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_SKULLTULA_HOUSE_KEY] = Item(RG_SKULLTULA_HOUSE_KEY, Text{ "Skulltula House Key", "", "Schlüssel für das Skulltula-Haus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_SKULLTULA_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_SKULLTULA_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_SKULLTULA_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_IMPAS_HOUSE_KEY] = Item(RG_IMPAS_HOUSE_KEY, Text{ "Impa's House Key", "", "Schlüssel für das Haus von Impa" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_IMPAS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_IMPAS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_IMPAS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_WINDMILL_KEY] = Item(RG_WINDMILL_KEY, Text{ "Windmill Key", "", "Schlüssel für die Windmühle" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_WINDMILL_KEY, RHT_OVERWORLD_KEY, RG_WINDMILL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_WINDMILL_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_KAK_SHOOTING_GALLERY_KEY] = Item(RG_KAK_SHOOTING_GALLERY_KEY, Text{ "Kakariko Shooting Gallery Key", "", "Schlüssel für die Schießbude von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_KAK_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_KAK_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_DAMPES_HUT_KEY] = Item(RG_DAMPES_HUT_KEY, Text{ "Dampe's Hut Key", "", "Schlüssel für die Hütte von Boris" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_DAMPES_HUT_KEY, RHT_OVERWORLD_KEY, RG_DAMPES_HUT_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_DAMPES_HUT_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_TALONS_HOUSE_KEY] = Item(RG_TALONS_HOUSE_KEY, Text{ "Talon's House Key", "", "Schlüssel für das Haus von Talon" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TALONS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_TALONS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_TALONS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_STABLES_KEY] = Item(RG_STABLES_KEY, Text{ "Stables Key", "", "Schlüssel für die Ställe" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_STABLES_KEY, RHT_OVERWORLD_KEY, RG_STABLES_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_STABLES_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_BACK_TOWER_KEY] = Item(RG_BACK_TOWER_KEY, Text{ "Back Tower Key", "", "Schlüssel für den hinteren Turm" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BACK_TOWER_KEY, RHT_OVERWORLD_KEY, RG_BACK_TOWER_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_BACK_TOWER_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_HYLIA_LAB_KEY] = Item(RG_HYLIA_LAB_KEY, Text{ "Hylia Laboratory Key", "", "Schlüssel für das Hylia-Labor" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_HYLIA_LAB_KEY, RHT_OVERWORLD_KEY, RG_HYLIA_LAB_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_HYLIA_LAB_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
+ itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
+ itemTable[RG_FISHING_HOLE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey);
// Key Rings
itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER);
itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing);
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
index d6ded1312..eb906d227 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/graveyard.cpp
@@ -24,7 +24,7 @@ void RegionTable_Init_Graveyard() {
Entrance(RR_GRAVEYARD_COMPOSERS_GRAVE, []{return logic->CanUse(RG_ZELDAS_LULLABY);}),
Entrance(RR_GRAVEYARD_HEART_PIECE_GRAVE, []{return logic->IsAdult || logic->AtNight;}),
Entrance(RR_GRAVEYARD_DAMPES_GRAVE, []{return logic->IsAdult;}),
- Entrance(RR_GRAVEYARD_DAMPES_HOUSE, []{return logic->IsAdult /*|| logic->AtDampeTime*/;}), //TODO: This needs to be handled in ToD rework
+ Entrance(RR_GRAVEYARD_DAMPES_HOUSE, []{return logic->IsAdult && logic->CanOpenOverworldDoor(RG_DAMPES_HUT_KEY) /*|| logic->AtDampeTime*/;}), //TODO: This needs to be handled in ToD rework
Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
Entrance(RR_GRAVEYARD_WARP_PAD_REGION, []{return false;}),
});
@@ -103,7 +103,7 @@ void RegionTable_Init_Graveyard() {
LOCATION(RC_DAMPE_HINT, logic->IsAdult),
}, {
//Exits
- Entrance(RR_THE_GRAVEYARD, []{return true;}),
+ Entrance(RR_THE_GRAVEYARD, []{return logic->CanOpenOverworldDoor(RG_DAMPES_HUT_KEY);}),
});
areaTable[RR_GRAVEYARD_WARP_PAD_REGION] = Region("Graveyard Warp Pad Region", "Graveyard", {RA_THE_GRAVEYARD}, NO_DAY_NIGHT_CYCLE, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
index 7d22f30a0..d41055f95 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/kakariko.cpp
@@ -33,14 +33,14 @@ void RegionTable_Init_Kakariko() {
}, {
//Exits
Entrance(RR_HYRULE_FIELD, []{return true;}),
- Entrance(RR_KAK_CARPENTER_BOSS_HOUSE, []{return true;}),
- Entrance(RR_KAK_HOUSE_OF_SKULLTULA, []{return true;}),
- Entrance(RR_KAK_IMPAS_HOUSE, []{return true;}),
- Entrance(RR_KAK_WINDMILL, []{return true;}),
- Entrance(RR_KAK_BAZAAR, []{return logic->IsAdult && logic->AtDay;}),
- Entrance(RR_KAK_SHOOTING_GALLERY, []{return logic->IsAdult && logic->AtDay;}),
+ Entrance(RR_KAK_CARPENTER_BOSS_HOUSE, []{return logic->CanOpenOverworldDoor(RG_BOSS_HOUSE_KEY);}),
+ Entrance(RR_KAK_HOUSE_OF_SKULLTULA, []{return logic->CanOpenOverworldDoor(RG_SKULLTULA_HOUSE_KEY);}),
+ Entrance(RR_KAK_IMPAS_HOUSE, []{return logic->CanOpenOverworldDoor(RG_IMPAS_HOUSE_KEY);}),
+ Entrance(RR_KAK_WINDMILL, []{return logic->CanOpenOverworldDoor(RG_WINDMILL_KEY);}),
+ Entrance(RR_KAK_BAZAAR, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_BAZAAR_KEY);}),
+ Entrance(RR_KAK_SHOOTING_GALLERY, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_SHOOTING_GALLERY_KEY);}),
Entrance(RR_KAK_WELL, []{return logic->IsAdult || logic->DrainWell || logic->CanUse(RG_IRON_BOOTS);}),
- Entrance(RR_KAK_POTION_SHOP_FRONT, []{return logic->AtDay || logic->IsChild;}),
+ Entrance(RR_KAK_POTION_SHOP_FRONT, []{return logic->AtDay || logic->IsChild && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}),
Entrance(RR_KAK_REDEAD_GROTTO, []{return logic->CanOpenBombGrotto();}),
Entrance(RR_KAK_IMPAS_LEDGE, []{return (logic->IsChild && logic->AtDay) || (logic->IsAdult && ctx->GetTrickOption(RT_VISIBLE_COLLISION));}),
Entrance(RR_KAK_WATCHTOWER, []{return logic->IsAdult || logic->AtDay || logic->CanKillEnemy(RE_GOLD_SKULLTULA, ED_LONGSHOT) || (ctx->GetTrickOption(RT_KAK_TOWER_GS) && logic->CanJumpslashExceptHammer());}),
@@ -95,8 +95,8 @@ void RegionTable_Init_Kakariko() {
//Exits
Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
Entrance(RR_KAK_OPEN_GROTTO, []{return true;}),
- Entrance(RR_KAK_ODD_POTION_BUILDING, []{return logic->IsAdult;}),
- Entrance(RR_KAK_POTION_SHOP_BACK, []{return logic->IsAdult && logic->AtDay;}),
+ Entrance(RR_KAK_ODD_POTION_BUILDING, []{return logic->IsAdult && logic->CanOpenOverworldDoor(RG_GRANNYS_POTION_SHOP_KEY);}),
+ Entrance(RR_KAK_POTION_SHOP_BACK, []{return logic->IsAdult && logic->AtDay && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}),
});
areaTable[RR_KAK_CARPENTER_BOSS_HOUSE] = Region("Kak Carpenter Boss House", "Kak Carpenter Boss House", {}, NO_DAY_NIGHT_CYCLE, {
@@ -104,7 +104,7 @@ void RegionTable_Init_Kakariko() {
EventAccess(&logic->WakeUpAdultTalon, []{return logic->IsAdult && logic->CanUse(RG_POCKET_EGG);}),
}, {}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_BOSS_HOUSE_KEY);}),
});
areaTable[RR_KAK_HOUSE_OF_SKULLTULA] = Region("Kak House of Skulltula", "Kak House of Skulltula", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -117,7 +117,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_100_GOLD_SKULLTULA_REWARD, logic->GetGSCount() >= 100),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_SKULLTULA_HOUSE_KEY);}),
});
areaTable[RR_KAK_IMPAS_HOUSE] = Region("Kak Impas House", "Kak Impas House", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -125,7 +125,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_IMPAS_HOUSE_COW, logic->CanUse(RG_EPONAS_SONG)),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_IMPAS_HOUSE_KEY);}),
});
areaTable[RR_KAK_IMPAS_HOUSE_BACK] = Region("Kak Impas House Back", "Kak Impas House", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -146,7 +146,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_SONG_FROM_WINDMILL, logic->IsAdult && logic->HasItem(RG_FAIRY_OCARINA)),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_WINDMILL_KEY);}),
});
areaTable[RR_KAK_BAZAAR] = Region("Kak Bazaar", "Kak Bazaar", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -169,7 +169,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_SHOOTING_GALLERY_REWARD, logic->HasItem(RG_CHILD_WALLET) && logic->IsAdult && logic->CanUse(RG_FAIRY_BOW)),
}, {
//Exits
- Entrance(RR_KAKARIKO_VILLAGE, []{return true;}),
+ Entrance(RR_KAKARIKO_VILLAGE, []{return logic->CanOpenOverworldDoor(RG_KAK_SHOOTING_GALLERY_KEY);}),
});
areaTable[RR_KAK_POTION_SHOP_FRONT] = Region("Kak Potion Shop Front", "Kak Potion Shop", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -203,7 +203,7 @@ void RegionTable_Init_Kakariko() {
LOCATION(RC_KAK_GRANNYS_SHOP, logic->IsAdult && (logic->CanUse(RG_ODD_MUSHROOM) || logic->TradeQuestStep(RG_ODD_MUSHROOM))),
}, {
// Exits
- Entrance(RR_KAK_BACKYARD, []{return true;}),
+ Entrance(RR_KAK_BACKYARD, []{return logic->CanOpenOverworldDoor(RG_GRANNYS_POTION_SHOP_KEY);}),
});
areaTable[RR_KAK_REDEAD_GROTTO] = Region("Kak Redead Grotto", "Kak Redead Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
index 148acad13..8833441e9 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lake_hylia.cpp
@@ -44,7 +44,7 @@ void RegionTable_Init_LakeHylia() {
Entrance(RR_ZORAS_DOMAIN, []{return logic->IsChild && (logic->HasItem(RG_SILVER_SCALE) || logic->CanUse(RG_IRON_BOOTS));}),
Entrance(RR_LH_OWL_FLIGHT, []{return logic->IsChild;}),
Entrance(RR_LH_FISHING_ISLAND, []{return ((logic->IsChild || logic->WaterTempleClear) && logic->HasItem(RG_BRONZE_SCALE)) || (logic->IsAdult && (logic->CanUse(RG_SCARECROW) || CanPlantBean(RR_LAKE_HYLIA)));}),
- Entrance(RR_LH_LAB, []{return true;}),
+ Entrance(RR_LH_LAB, []{return logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY);}),
Entrance(RR_WATER_TEMPLE_ENTRYWAY, []{return logic->CanUse(RG_HOOKSHOT) && ((logic->CanUse(RG_IRON_BOOTS) || (ctx->GetTrickOption(RT_LH_WATER_HOOKSHOT) && logic->HasItem(RG_GOLDEN_SCALE))) || (logic->IsAdult && logic->CanUse(RG_LONGSHOT) && logic->HasItem(RG_GOLDEN_SCALE)));}),
Entrance(RR_LH_GROTTO, []{return true;}),
});
@@ -52,7 +52,7 @@ void RegionTable_Init_LakeHylia() {
areaTable[RR_LH_FISHING_ISLAND] = Region("LH Fishing Island", "Lake Hylia", {RA_LAKE_HYLIA}, DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_LAKE_HYLIA, []{return logic->HasItem(RG_BRONZE_SCALE);}),
- Entrance(RR_LH_FISHING_POND, []{return true;}),
+ Entrance(RR_LH_FISHING_POND, []{return logic->CanOpenOverworldDoor(RG_FISHING_HOLE_KEY);}),
});
areaTable[RR_LH_OWL_FLIGHT] = Region("LH Owl Flight", "Lake Hylia", {RA_LAKE_HYLIA}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@@ -70,7 +70,7 @@ void RegionTable_Init_LakeHylia() {
LOCATION(RC_LH_LAB_RIGHT_RUPEE, logic->CanUse(RG_IRON_BOOTS) || logic->HasItem(RG_GOLDEN_SCALE)),
}, {
//Exits
- Entrance(RR_LAKE_HYLIA, []{return true;}),
+ Entrance(RR_LAKE_HYLIA, []{return logic->CanOpenOverworldDoor(RG_HYLIA_LAB_KEY);}),
});
// TODO: should some of these helpers be done via events instead?
@@ -115,7 +115,7 @@ void RegionTable_Init_LakeHylia() {
LOCATION(RC_FISHING_POLE_HINT, true),
}, {
//Exits
- Entrance(RR_LH_FISHING_ISLAND, []{return true;}),
+ Entrance(RR_LH_FISHING_ISLAND, []{return logic->CanOpenOverworldDoor(RG_FISHING_HOLE_KEY);}),
});
areaTable[RR_LH_GROTTO] = Region("LH Grotto", "LH Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
index df73b78d9..fa1d7451e 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/lon_lon_ranch.cpp
@@ -25,9 +25,9 @@ void RegionTable_Init_LonLonRanch() {
}, {
//Exits
Entrance(RR_HYRULE_FIELD, []{return true;}),
- Entrance(RR_LLR_TALONS_HOUSE, []{return true;}),
- Entrance(RR_LLR_STABLES, []{return true;}),
- Entrance(RR_LLR_TOWER, []{return true;}),
+ Entrance(RR_LLR_TALONS_HOUSE, []{return logic->CanOpenOverworldDoor(RG_TALONS_HOUSE_KEY);}),
+ Entrance(RR_LLR_STABLES, []{return logic->CanOpenOverworldDoor(RG_STABLES_KEY);}),
+ Entrance(RR_LLR_TOWER, []{return logic->CanOpenOverworldDoor(RG_BACK_TOWER_KEY);}),
Entrance(RR_LLR_GROTTO, []{return logic->IsChild;}),
});
@@ -39,7 +39,7 @@ void RegionTable_Init_LonLonRanch() {
LOCATION(RC_LLR_TALONS_HOUSE_POT_3, logic->CanBreakPots()),
}, {
//Exits
- Entrance(RR_LON_LON_RANCH, []{return true;}),
+ Entrance(RR_LON_LON_RANCH, []{return logic->CanOpenOverworldDoor(RG_TALONS_HOUSE_KEY);}),
});
areaTable[RR_LLR_STABLES] = Region("LLR Stables", "LLR Stables", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -48,7 +48,7 @@ void RegionTable_Init_LonLonRanch() {
LOCATION(RC_LLR_STABLES_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)),
}, {
//Exits
- Entrance(RR_LON_LON_RANCH, []{return true;}),
+ Entrance(RR_LON_LON_RANCH, []{return logic->CanOpenOverworldDoor(RG_STABLES_KEY);}),
});
areaTable[RR_LLR_TOWER] = Region("LLR Tower", "LLR Tower", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -58,7 +58,7 @@ void RegionTable_Init_LonLonRanch() {
LOCATION(RC_LLR_TOWER_RIGHT_COW, logic->CanUse(RG_EPONAS_SONG)),
}, {
//Exits
- Entrance(RR_LON_LON_RANCH, []{return true;}),
+ Entrance(RR_LON_LON_RANCH, []{return logic->CanOpenOverworldDoor(RG_BACK_TOWER_KEY);}),
});
areaTable[RR_LLR_GROTTO] = Region("LLR Grotto", "LLR Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
diff --git a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
index 384485730..e0ef67aa5 100644
--- a/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
+++ b/soh/soh/Enhancements/randomizer/location_access/overworld/market.cpp
@@ -8,7 +8,7 @@ void RegionTable_Init_Market() {
//Exits
Entrance(RR_HYRULE_FIELD, []{return logic->IsAdult || logic->AtDay;}),
Entrance(RR_THE_MARKET, []{return true;}),
- Entrance(RR_MARKET_GUARD_HOUSE, []{return true;}),
+ Entrance(RR_MARKET_GUARD_HOUSE, []{return logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}),
});
areaTable[RR_THE_MARKET] = Region("Market", "Market", {RA_THE_MARKET}, NO_DAY_NIGHT_CYCLE, {}, {}, {
@@ -16,21 +16,21 @@ void RegionTable_Init_Market() {
Entrance(RR_MARKET_ENTRANCE, []{return true;}),
Entrance(RR_TOT_ENTRANCE, []{return true;}),
Entrance(RR_CASTLE_GROUNDS, []{return true;}),
- Entrance(RR_MARKET_BAZAAR, []{return logic->IsChild && logic->AtDay;}),
- Entrance(RR_MARKET_MASK_SHOP, []{return logic->IsChild && logic->AtDay;}),
- Entrance(RR_MARKET_SHOOTING_GALLERY, []{return logic->IsChild && logic->AtDay;}),
- Entrance(RR_MARKET_BOMBCHU_BOWLING, []{return logic->IsChild;}),
- Entrance(RR_MARKET_TREASURE_CHEST_GAME, []{return logic->IsChild && logic->AtNight;}),
- Entrance(RR_MARKET_POTION_SHOP, []{return logic->IsChild && logic->AtDay;}),
+ Entrance(RR_MARKET_BAZAAR, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MARKET_BAZAAR_KEY);}),
+ Entrance(RR_MARKET_MASK_SHOP, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MASK_SHOP_KEY);}),
+ Entrance(RR_MARKET_SHOOTING_GALLERY, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MARKET_SHOOTING_GALLERY_KEY);}),
+ Entrance(RR_MARKET_BOMBCHU_BOWLING, []{return logic->IsChild && logic->CanOpenOverworldDoor(RG_BOMBCHU_BOWLING_KEY);}),
+ Entrance(RR_MARKET_TREASURE_CHEST_GAME, []{return logic->IsChild && logic->AtNight && logic->CanOpenOverworldDoor(RG_TREASURE_CHEST_GAME_BUILDING_KEY);}),
+ Entrance(RR_MARKET_POTION_SHOP, []{return logic->IsChild && logic->AtDay && logic->CanOpenOverworldDoor(RG_MARKET_POTION_SHOP_KEY);}),
Entrance(RR_MARKET_BACK_ALLEY, []{return logic->IsChild;}),
});
areaTable[RR_MARKET_BACK_ALLEY] = Region("Market Back Alley", "Market", {RA_THE_MARKET}, NO_DAY_NIGHT_CYCLE, {}, {}, {
//Exits
Entrance(RR_THE_MARKET, []{return true;}),
- Entrance(RR_MARKET_BOMBCHU_SHOP, []{return logic->AtNight;}),
- Entrance(RR_MARKET_DOG_LADY_HOUSE, []{return true;}),
- Entrance(RR_MARKET_MAN_IN_GREEN_HOUSE, []{return logic->AtNight;}),
+ Entrance(RR_MARKET_BOMBCHU_SHOP, []{return logic->AtNight && logic->CanOpenOverworldDoor(RG_BOMBCHU_SHOP_KEY);}),
+ Entrance(RR_MARKET_DOG_LADY_HOUSE, []{return logic->CanOpenOverworldDoor(RG_RICHARDS_HOUSE_KEY);}),
+ Entrance(RR_MARKET_MAN_IN_GREEN_HOUSE, []{return logic->AtNight && logic->CanOpenOverworldDoor(RG_ALLEY_HOUSE_KEY);}),
});
areaTable[RR_MARKET_GUARD_HOUSE] = Region("Market Guard House", "Market Guard House", {}, NO_DAY_NIGHT_CYCLE, {
@@ -98,7 +98,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MK_GUARD_HOUSE_ADULT_POT_11, logic->IsAdult && logic->CanBreakPots()),
}, {
//Exits
- Entrance(RR_MARKET_ENTRANCE, []{return true;}),
+ Entrance(RR_MARKET_ENTRANCE, []{return logic->CanOpenOverworldDoor(RG_GUARD_HOUSE_KEY);}),
});
areaTable[RR_MARKET_BAZAAR] = Region("Market Bazaar", "Market Bazaar", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -133,7 +133,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_SHOOTING_GALLERY_REWARD, logic->IsChild && logic->HasItem(RG_CHILD_WALLET)),
}, {
//Exits
- Entrance(RR_THE_MARKET, []{return true;}),
+ Entrance(RR_THE_MARKET, []{return logic->CanOpenOverworldDoor(RG_MARKET_SHOOTING_GALLERY_KEY);}),
});
areaTable[RR_MARKET_BOMBCHU_BOWLING] = Region("Market Bombchu Bowling", "Market Bombchu Bowling", {}, NO_DAY_NIGHT_CYCLE, {
@@ -145,7 +145,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_BOMBCHU_BOWLING_SECOND_PRIZE, logic->CouldPlayBowling && logic->BombchusEnabled()),
}, {
//Exits
- Entrance(RR_THE_MARKET, []{return true;}),
+ Entrance(RR_THE_MARKET, []{return logic->CanOpenOverworldDoor(RG_BOMBCHU_BOWLING_KEY);}),
});
areaTable[RR_MARKET_POTION_SHOP] = Region("Market Potion Shop", "Market Potion Shop", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -179,7 +179,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_TREASURE_CHEST_GAME_ITEM_5, logic->HasItem(RG_CHILD_WALLET) && ((ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_SINGLE_KEYS) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 5)) || (ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME).Is(RO_CHEST_GAME_PACK) && logic->SmallKeys(RR_MARKET_TREASURE_CHEST_GAME, 1)) || (logic->CanUse(RG_LENS_OF_TRUTH) && !ctx->GetOption(RSK_SHUFFLE_CHEST_MINIGAME)))),
}, {
//Exits
- Entrance(RR_THE_MARKET, []{return true;}),
+ Entrance(RR_THE_MARKET, []{return logic->CanOpenOverworldDoor(RG_TREASURE_CHEST_GAME_BUILDING_KEY);}),
});
areaTable[RR_MARKET_BOMBCHU_SHOP] = Region("Market Bombchu Shop", "Market Bombchu Shop", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -202,7 +202,7 @@ void RegionTable_Init_Market() {
LOCATION(RC_MARKET_LOST_DOG, logic->IsChild && logic->AtNight),
}, {
//Exits
- Entrance(RR_MARKET_BACK_ALLEY, []{return true;}),
+ Entrance(RR_MARKET_BACK_ALLEY, []{return logic->CanOpenOverworldDoor(RG_RICHARDS_HOUSE_KEY);}),
});
areaTable[RR_MARKET_MAN_IN_GREEN_HOUSE] = Region("Market Man in Green House", "Market Man in Green House", {}, NO_DAY_NIGHT_CYCLE, {}, {
@@ -212,6 +212,6 @@ void RegionTable_Init_Market() {
LOCATION(RC_MK_BACK_ALLEY_HOUSE_POT_3, logic->CanBreakPots()),
}, {
//Exits
- Entrance(RR_MARKET_BACK_ALLEY, []{return true;}),
+ Entrance(RR_MARKET_BACK_ALLEY, []{return logic->CanOpenOverworldDoor(RG_ALLEY_HOUSE_KEY);}),
});
}
\ No newline at end of file
diff --git a/soh/soh/Enhancements/randomizer/logic.cpp b/soh/soh/Enhancements/randomizer/logic.cpp
index cd65fd006..1be61ccae 100644
--- a/soh/soh/Enhancements/randomizer/logic.cpp
+++ b/soh/soh/Enhancements/randomizer/logic.cpp
@@ -140,6 +140,31 @@ namespace Rando {
case RG_TWINROVA_SOUL:
case RG_GANON_SOUL:
case RG_SKELETON_KEY:
+ // Overworld Keys
+ case RG_GUARD_HOUSE_KEY:
+ case RG_MARKET_BAZAAR_KEY:
+ case RG_MARKET_POTION_SHOP_KEY:
+ case RG_MASK_SHOP_KEY:
+ case RG_MARKET_SHOOTING_GALLERY_KEY:
+ case RG_BOMBCHU_BOWLING_KEY:
+ case RG_TREASURE_CHEST_GAME_BUILDING_KEY:
+ case RG_BOMBCHU_SHOP_KEY:
+ case RG_RICHARDS_HOUSE_KEY:
+ case RG_ALLEY_HOUSE_KEY:
+ case RG_KAK_BAZAAR_KEY:
+ case RG_KAK_POTION_SHOP_KEY:
+ case RG_BOSS_HOUSE_KEY:
+ case RG_GRANNYS_POTION_SHOP_KEY:
+ case RG_SKULLTULA_HOUSE_KEY:
+ case RG_IMPAS_HOUSE_KEY:
+ case RG_WINDMILL_KEY:
+ case RG_KAK_SHOOTING_GALLERY_KEY:
+ case RG_DAMPES_HUT_KEY:
+ case RG_TALONS_HOUSE_KEY:
+ case RG_STABLES_KEY:
+ case RG_BACK_TOWER_KEY:
+ case RG_HYLIA_LAB_KEY:
+ case RG_FISHING_HOLE_KEY:
return CheckRandoInf(RandoGetToRandInf.at(itemName));
// Boss Keys
case RG_EPONA:
@@ -382,6 +407,18 @@ namespace Rando {
}
}
+ bool Logic::CanOpenOverworldDoor(RandomizerGet key) {
+ if (!ctx->GetOption(RSK_LOCK_OVERWORLD_DOORS)) {
+ return true;
+ }
+
+ if (HasItem(RG_SKELETON_KEY)) {
+ return true;
+ }
+
+ return HasItem(key);
+ }
+
uint8_t GetDifficultyValueFromString(Rando::Option& glitchOption) {
return 0;
}
@@ -1293,7 +1330,31 @@ namespace Rando {
{ RG_OCARINA_C_RIGHT_BUTTON, RAND_INF_HAS_OCARINA_C_RIGHT },
{ RG_SKELETON_KEY, RAND_INF_HAS_SKELETON_KEY },
{ RG_GREG_RUPEE, RAND_INF_GREG_FOUND },
- { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND }
+ { RG_FISHING_POLE, RAND_INF_FISHING_POLE_FOUND },
+ { RG_GUARD_HOUSE_KEY, RAND_INF_GUARD_HOUSE_KEY_OBTAINED },
+ { RG_MARKET_BAZAAR_KEY, RAND_INF_MARKET_BAZAAR_KEY_OBTAINED },
+ { RG_MARKET_POTION_SHOP_KEY, RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED },
+ { RG_MASK_SHOP_KEY, RAND_INF_MASK_SHOP_KEY_OBTAINED },
+ { RG_MARKET_SHOOTING_GALLERY_KEY, RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED },
+ { RG_BOMBCHU_BOWLING_KEY, RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED },
+ { RG_TREASURE_CHEST_GAME_BUILDING_KEY, RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED },
+ { RG_BOMBCHU_SHOP_KEY, RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED },
+ { RG_RICHARDS_HOUSE_KEY, RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED },
+ { RG_ALLEY_HOUSE_KEY, RAND_INF_ALLEY_HOUSE_KEY_OBTAINED },
+ { RG_KAK_BAZAAR_KEY, RAND_INF_KAK_BAZAAR_KEY_OBTAINED },
+ { RG_KAK_POTION_SHOP_KEY, RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED },
+ { RG_BOSS_HOUSE_KEY, RAND_INF_BOSS_HOUSE_KEY_OBTAINED },
+ { RG_GRANNYS_POTION_SHOP_KEY, RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED },
+ { RG_SKULLTULA_HOUSE_KEY, RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED },
+ { RG_IMPAS_HOUSE_KEY, RAND_INF_IMPAS_HOUSE_KEY_OBTAINED },
+ { RG_WINDMILL_KEY, RAND_INF_WINDMILL_KEY_OBTAINED },
+ { RG_KAK_SHOOTING_GALLERY_KEY, RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED },
+ { RG_DAMPES_HUT_KEY, RAND_INF_DAMPES_HUT_KEY_OBTAINED },
+ { RG_TALONS_HOUSE_KEY, RAND_INF_TALONS_HOUSE_KEY_OBTAINED },
+ { RG_STABLES_KEY, RAND_INF_STABLES_KEY_OBTAINED },
+ { RG_BACK_TOWER_KEY, RAND_INF_BACK_TOWER_KEY_OBTAINED },
+ { RG_HYLIA_LAB_KEY, RAND_INF_HYLIA_LAB_KEY_OBTAINED },
+ { RG_FISHING_HOLE_KEY, RAND_INF_FISHING_HOLE_KEY_OBTAINED },
};
std::map Logic::RandoGetToDungeonScene = {
@@ -1635,6 +1696,30 @@ namespace Rando {
case RG_OCARINA_C_RIGHT_BUTTON:
case RG_GREG_RUPEE:
case RG_FISHING_POLE:
+ case RG_GUARD_HOUSE_KEY:
+ case RG_MARKET_BAZAAR_KEY:
+ case RG_MARKET_POTION_SHOP_KEY:
+ case RG_MASK_SHOP_KEY:
+ case RG_MARKET_SHOOTING_GALLERY_KEY:
+ case RG_BOMBCHU_BOWLING_KEY:
+ case RG_TREASURE_CHEST_GAME_BUILDING_KEY:
+ case RG_BOMBCHU_SHOP_KEY:
+ case RG_RICHARDS_HOUSE_KEY:
+ case RG_ALLEY_HOUSE_KEY:
+ case RG_KAK_BAZAAR_KEY:
+ case RG_KAK_POTION_SHOP_KEY:
+ case RG_BOSS_HOUSE_KEY:
+ case RG_GRANNYS_POTION_SHOP_KEY:
+ case RG_SKULLTULA_HOUSE_KEY:
+ case RG_IMPAS_HOUSE_KEY:
+ case RG_WINDMILL_KEY:
+ case RG_KAK_SHOOTING_GALLERY_KEY:
+ case RG_DAMPES_HUT_KEY:
+ case RG_TALONS_HOUSE_KEY:
+ case RG_STABLES_KEY:
+ case RG_BACK_TOWER_KEY:
+ case RG_HYLIA_LAB_KEY:
+ case RG_FISHING_HOLE_KEY:
SetRandoInf(RandoGetToRandInf.at(randoGet), state);
break;
case RG_TRIFORCE_PIECE:
diff --git a/soh/soh/Enhancements/randomizer/logic.h b/soh/soh/Enhancements/randomizer/logic.h
index 3aff99d67..ea9d51801 100644
--- a/soh/soh/Enhancements/randomizer/logic.h
+++ b/soh/soh/Enhancements/randomizer/logic.h
@@ -186,6 +186,7 @@ class Logic {
bool HasProjectile(HasProjectileAge age);
bool HasItem(RandomizerGet itemName);
bool HasBossSoul(RandomizerGet itemName);
+ bool CanOpenOverworldDoor(RandomizerGet itemName);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount);
bool SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless, uint8_t requiredAmountGlitched);
bool CanDoGlitch(GlitchType glitch);
diff --git a/soh/soh/Enhancements/randomizer/option_descriptions.cpp b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
index 2e577c51e..ee59b1be4 100644
--- a/soh/soh/Enhancements/randomizer/option_descriptions.cpp
+++ b/soh/soh/Enhancements/randomizer/option_descriptions.cpp
@@ -41,6 +41,7 @@ void Settings::CreateOptionDescriptions() {
"\n"
"Open - Sleeping Waterfall is always open. "
"Link may always enter Zora's Domain.";
+ mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS] = "Add locks to all wooden overworld doors, requiring specific small keys to open them";
mOptionDescriptions[RSK_STARTING_AGE] =
"Choose which age Link will start as.\n\n"
"Starting as adult means you start with the Master Sword in your inventory.\n"
diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp
index 301498bf8..2d0ceb48a 100644
--- a/soh/soh/Enhancements/randomizer/randomizer.cpp
+++ b/soh/soh/Enhancements/randomizer/randomizer.cpp
@@ -3338,7 +3338,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!",
@@ -3386,40 +3386,140 @@ void Randomizer::CreateCustomMessages() {
GIMESSAGE(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %yThieves Hideout &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für das %yDiebesversteck%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %yDiebesversteck%w!",
"Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"),
GIMESSAGE(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %gForest Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %gWaldtempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gWaldtempel%w!",
"Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"),
GIMESSAGE(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %rFire Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %rFeuertempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %rFeuertempel%w!",
"Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"),
GIMESSAGE(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %bWater Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %bWassertempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %bWassertempel%w!",
"Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"),
GIMESSAGE(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %ySpirit Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %yGeistertempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %yGeistertempel%w!",
"Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"),
GIMESSAGE(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %pShadow Temple &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %pSchattentempel%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %pSchattentempel%w!",
"Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"),
GIMESSAGE(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %pBottom of the &Well %wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für den %pGrund des Brunnens%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %pGrund des Brunnens%w!",
"Vous obtenez une %rPetite Clé %w&du %pPuits%w!"),
GIMESSAGE(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %yGerudo Training &Grounds %wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für die %yGerudo-Trainingsarena%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %yGerudo-Trainingsarena%w!",
"Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"),
GIMESSAGE(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL,
"You found a %rGanon's Castle &%wSmall Key!",
- "Du erhältst einen %rKleinen&Schlüssel%w für %rGanons Schloß%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für %rGanons Schloß%w!",
"Vous obtenez une %rPetite Clé %w&du %rChâteau de Ganon%w!"),
+ GIMESSAGE(RG_GUARD_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gGuard House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus der Wachen%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison des Gardes%w!"),
+ GIMESSAGE(RG_MARKET_BAZAAR_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMarket Bazaar%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar des Marktes%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMarché%w!"),
+ GIMESSAGE(RG_MARKET_POTION_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMarket Potion Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden des Marktes%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMarché%w!"),
+ GIMESSAGE(RG_MASK_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMask Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gMaskenladen%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Masques%w!"),
+ GIMESSAGE(RG_MARKET_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gMarket Shooting Gallery%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude des Marktes%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gStand de Tir%w!"),
+ GIMESSAGE(RG_BOMBCHU_BOWLING_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBombchu Bowling Alley%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gMinenbowlingbahn%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gBowling Bombchu%w!"),
+ GIMESSAGE(RG_TREASURE_CHEST_GAME_BUILDING_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gTreasure Chest Game Building%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Schatzkisten-Pokers%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gJeu de la Chasse au Trésor%w!"),
+ GIMESSAGE(RG_BOMBCHU_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBombchu Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gKrabbelminenladen%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Bombchu%w!"),
+ GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gRichard's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de Richard%w!"),
+ GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gRichard's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de Richard%w!"),
+ GIMESSAGE(RG_ALLEY_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&the %gAlley House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus in der Gasse%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de la Ruelle%w!"),
+ GIMESSAGE(RG_KAK_BAZAAR_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gKakariko Bazaar%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar von Kakariko%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMarché de Cocorico%w!"),
+ GIMESSAGE(RG_KAK_POTION_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gKakariko Potion Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden von Kakariko%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Potions de Cocorico%w!"),
+ GIMESSAGE(RG_BOSS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBoss's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Chefs%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison du Boss%w!"),
+ GIMESSAGE(RG_GRANNYS_POTION_SHOP_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gGranny's Potion Shop%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für %gAsas Hexenladen%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMagasin de Potions de Grand-mère%w!"),
+ GIMESSAGE(RG_SKULLTULA_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gSkulltula House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gSkulltula-Haus%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison des Skulltulas%w!"),
+ GIMESSAGE(RG_IMPAS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gImpa's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Impa%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison d'Impa%w!"),
+ GIMESSAGE(RG_WINDMILL_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gWindmill%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gWindmühle%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gMoulin à Vent%w!"),
+ GIMESSAGE(RG_KAK_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gKakariko Shooting Gallery%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude von Kakariko%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gStand de Tir de Cocorico%w!"),
+ GIMESSAGE(RG_DAMPES_HUT_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gDampe's Hut%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gHütte von Boris%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gChalet de Dampe%w!"),
+ GIMESSAGE(RG_TALONS_HOUSE_KEY, ITEM_KEY_SMALL,
+ "You found the key to&%gTalon's House%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Talon%w!",
+ "Vous obtenez une %rPetite Clé %w&de la %gMaison de Talon%w!"),
+ GIMESSAGE(RG_STABLES_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gStables%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für die %gStälle%w!",
+ "Vous obtenez une %rPetite Clé %w&des %gÉcuries%w!"),
+ GIMESSAGE(RG_BACK_TOWER_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gBack Tower%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %ghinteren Turm%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gTour Arrière%w!"),
+ GIMESSAGE(RG_HYLIA_LAB_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gHylia Laboratory%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für das %gHylia-Labor%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gLaboratoire d'Hylia%w!"),
+ GIMESSAGE(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL,
+ "You found the key to the&%gFishing Hole%w!",
+ "Du erhältst einen %rkleinen&Schlüssel%w für den %gFischweiher%w!",
+ "Vous obtenez une %rPetite Clé %w&du %gTrou de Pêche%w!"),
GIMESSAGE(RG_GERUDO_FORTRESS_KEY_RING, ITEM_KEY_SMALL,
"You found a %yThieves Hideout &%wKeyring!",
@@ -3953,6 +4053,9 @@ extern "C" u16 Randomizer_Item_Give(PlayState* play, GetItemEntry giEntry) {
gSaveContext.inventory.dungeonItems[mapIndex] |= bitmask;
return Return_Item_Entry(giEntry, RG_NONE);
+ } else if (item >= RG_GUARD_HOUSE_KEY && item <= RG_FISHING_HOLE_KEY) {
+ Flags_SetRandomizerInf((RandomizerInf)((int)RAND_INF_GUARD_HOUSE_UNLOCKED + ((item - RG_GUARD_HOUSE_KEY) * 2) + 1));
+ 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 d7edb01df..b30ee48ce 100644
--- a/soh/soh/Enhancements/randomizer/randomizerTypes.h
+++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h
@@ -148,6 +148,30 @@ typedef enum {
LOGIC_GANONS_CASTLE_KEYS,
LOGIC_TREASURE_GAME_KEYS,
LOGIC_SKELETON_KEY,
+ LOGIC_GUARD_HOUSE_KEY,
+ LOGIC_MARKET_BAZAAR_KEY,
+ LOGIC_MARKET_POTION_SHOP_KEY,
+ LOGIC_MASK_SHOP_KEY,
+ LOGIC_MARKET_SHOOTING_GALLERY_KEY,
+ LOGIC_BOMBCHU_BOWLING_KEY,
+ LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,
+ LOGIC_BOMBCHU_SHOP_KEY,
+ LOGIC_RICHARDS_HOUSE_KEY,
+ LOGIC_ALLEY_HOUSE_KEY,
+ LOGIC_KAK_BAZAAR_KEY,
+ LOGIC_KAK_POTION_SHOP_KEY,
+ LOGIC_BOSS_HOUSE_KEY,
+ LOGIC_GRANNYS_POTION_SHOP_KEY,
+ LOGIC_SKULLTULA_HOUSE_KEY,
+ LOGIC_IMPAS_HOUSE_KEY,
+ LOGIC_WINDMILL_KEY,
+ LOGIC_KAK_SHOOTING_GALLERY_KEY,
+ LOGIC_DAMPES_HUT_KEY,
+ LOGIC_TALONS_HOUSE_KEY,
+ LOGIC_STABLES_KEY,
+ LOGIC_BACK_TOWER_KEY,
+ LOGIC_HYLIA_LAB_KEY,
+ LOGIC_FISHING_HOLE_KEY,
LOGIC_KOKIRI_EMERALD,
LOGIC_GORON_RUBY,
LOGIC_ZORA_SAPPHIRE,
@@ -3341,6 +3365,30 @@ typedef enum {
RG_HOOKSHOT,
RG_LONGSHOT,
RG_SCARECROW,
+ RG_GUARD_HOUSE_KEY,
+ RG_MARKET_BAZAAR_KEY,
+ RG_MARKET_POTION_SHOP_KEY,
+ RG_MASK_SHOP_KEY,
+ RG_MARKET_SHOOTING_GALLERY_KEY,
+ RG_BOMBCHU_BOWLING_KEY,
+ RG_TREASURE_CHEST_GAME_BUILDING_KEY,
+ RG_BOMBCHU_SHOP_KEY,
+ RG_RICHARDS_HOUSE_KEY,
+ RG_ALLEY_HOUSE_KEY,
+ RG_KAK_BAZAAR_KEY,
+ RG_KAK_POTION_SHOP_KEY,
+ RG_BOSS_HOUSE_KEY,
+ RG_GRANNYS_POTION_SHOP_KEY,
+ RG_SKULLTULA_HOUSE_KEY,
+ RG_IMPAS_HOUSE_KEY,
+ RG_WINDMILL_KEY,
+ RG_KAK_SHOOTING_GALLERY_KEY,
+ RG_DAMPES_HUT_KEY,
+ RG_TALONS_HOUSE_KEY,
+ RG_STABLES_KEY,
+ RG_BACK_TOWER_KEY,
+ RG_HYLIA_LAB_KEY,
+ RG_FISHING_HOLE_KEY,
// Logic Only
RG_DISTANT_SCARECROW,
RG_STICKS,
@@ -4614,6 +4662,7 @@ typedef enum {
RHT_FISHING_POLE,
RHT_SKELETON_KEY,
RHT_EPONA,
+ RHT_OVERWORLD_KEY,
RHT_HINT_MYSTERIOUS,
RHT_MYSTERIOUS_ITEM,
RHT_MYSTERIOUS_ITEM_CAPITAL,
@@ -5300,6 +5349,7 @@ typedef enum {
RSK_SHUFFLE_DEKU_NUT_BAG,
RSK_SHUFFLE_FREESTANDING,
RSK_SHUFFLE_FAIRIES,
+ RSK_LOCK_OVERWORLD_DOORS,
RSK_MAX
} RandomizerSettingKey;
diff --git a/soh/soh/Enhancements/randomizer/randomizer_inf.h b/soh/soh/Enhancements/randomizer/randomizer_inf.h
index c66c06fab..4140752e0 100644
--- a/soh/soh/Enhancements/randomizer/randomizer_inf.h
+++ b/soh/soh/Enhancements/randomizer/randomizer_inf.h
@@ -1272,6 +1272,56 @@ typedef enum {
RAND_INF_SHADOW_TEMPLE_MQ_WIND_HINT_SUN_FAIRY,
RAND_INF_BOTTOM_OF_THE_WELL_MQ_CELL_SUN_FAIRY,
RAND_INF_BOTTOM_OF_THE_WELL_MQ_BASEMENT_SUN_FAIRY,
+
+ RAND_INF_GUARD_HOUSE_UNLOCKED,
+ RAND_INF_GUARD_HOUSE_KEY_OBTAINED,
+ RAND_INF_MARKET_BAZAAR_UNLOCKED,
+ RAND_INF_MARKET_BAZAAR_KEY_OBTAINED,
+ RAND_INF_MARKET_POTION_SHOP_UNLOCKED,
+ RAND_INF_MARKET_POTION_SHOP_KEY_OBTAINED,
+ RAND_INF_MASK_SHOP_UNLOCKED,
+ RAND_INF_MASK_SHOP_KEY_OBTAINED,
+ RAND_INF_MARKET_SHOOTING_GALLERY_UNLOCKED,
+ RAND_INF_MARKET_SHOOTING_GALLERY_KEY_OBTAINED,
+ RAND_INF_BOMBCHU_BOWLING_UNLOCKED,
+ RAND_INF_BOMBCHU_BOWLING_KEY_OBTAINED,
+ RAND_INF_TREASURE_CHEST_GAME_BUILDING_UNLOCKED,
+ RAND_INF_TREASURE_CHEST_GAME_BUILDING_KEY_OBTAINED,
+ RAND_INF_BOMBCHU_SHOP_UNLOCKED,
+ RAND_INF_BOMBCHU_SHOP_KEY_OBTAINED,
+ RAND_INF_RICHARDS_HOUSE_UNLOCKED,
+ RAND_INF_RICHARDS_HOUSE_KEY_OBTAINED,
+ RAND_INF_ALLEY_HOUSE_UNLOCKED,
+ RAND_INF_ALLEY_HOUSE_KEY_OBTAINED,
+ RAND_INF_KAK_BAZAAR_UNLOCKED,
+ RAND_INF_KAK_BAZAAR_KEY_OBTAINED,
+ RAND_INF_KAK_POTION_SHOP_UNLOCKED,
+ RAND_INF_KAK_POTION_SHOP_KEY_OBTAINED,
+ RAND_INF_BOSS_HOUSE_UNLOCKED,
+ RAND_INF_BOSS_HOUSE_KEY_OBTAINED,
+ RAND_INF_GRANNYS_POTION_SHOP_UNLOCKED,
+ RAND_INF_GRANNYS_POTION_SHOP_KEY_OBTAINED,
+ RAND_INF_SKULLTULA_HOUSE_UNLOCKED,
+ RAND_INF_SKULLTULA_HOUSE_KEY_OBTAINED,
+ RAND_INF_IMPAS_HOUSE_UNLOCKED,
+ RAND_INF_IMPAS_HOUSE_KEY_OBTAINED,
+ RAND_INF_WINDMILL_UNLOCKED,
+ RAND_INF_WINDMILL_KEY_OBTAINED,
+ RAND_INF_KAK_SHOOTING_GALLERY_UNLOCKED,
+ RAND_INF_KAK_SHOOTING_GALLERY_KEY_OBTAINED,
+ RAND_INF_DAMPES_HUT_UNLOCKED,
+ RAND_INF_DAMPES_HUT_KEY_OBTAINED,
+ RAND_INF_TALONS_HOUSE_UNLOCKED,
+ RAND_INF_TALONS_HOUSE_KEY_OBTAINED,
+ RAND_INF_STABLES_UNLOCKED,
+ RAND_INF_STABLES_KEY_OBTAINED,
+ RAND_INF_BACK_TOWER_UNLOCKED,
+ RAND_INF_BACK_TOWER_KEY_OBTAINED,
+ RAND_INF_HYLIA_LAB_UNLOCKED,
+ RAND_INF_HYLIA_LAB_KEY_OBTAINED,
+ RAND_INF_FISHING_HOLE_UNLOCKED,
+ RAND_INF_FISHING_HOLE_KEY_OBTAINED,
+
// If you add anything to this list, you need to update the size of randomizerInf in z64save.h to be ceil(RAND_INF_MAX / 16)
RAND_INF_MAX,
diff --git a/soh/soh/Enhancements/randomizer/settings.cpp b/soh/soh/Enhancements/randomizer/settings.cpp
index ef7cb0cd5..b29cccf97 100644
--- a/soh/soh/Enhancements/randomizer/settings.cpp
+++ b/soh/soh/Enhancements/randomizer/settings.cpp
@@ -110,6 +110,7 @@ void Settings::CreateOptions() {
mOptions[RSK_DOOR_OF_TIME] = Option::U8("Door of Time", {"Closed", "Song only", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("DoorOfTime"), mOptionDescriptions[RSK_DOOR_OF_TIME], WidgetType::Combobox);
mOptions[RSK_ZORAS_FOUNTAIN] = Option::U8("Zora's Fountain", {"Closed", "Closed as child", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ZorasFountain"), mOptionDescriptions[RSK_ZORAS_FOUNTAIN]);
mOptions[RSK_SLEEPING_WATERFALL] = Option::U8("Sleeping Waterfall", {"Closed", "Open"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("SleepingWaterfall"), mOptionDescriptions[RSK_SLEEPING_WATERFALL]);
+ mOptions[RSK_LOCK_OVERWORLD_DOORS] = Option::Bool("Lock Overworld Doors", CVAR_RANDOMIZER_SETTING("LockOverworldDoors"), mOptionDescriptions[RSK_LOCK_OVERWORLD_DOORS]);
mOptions[RSK_GERUDO_FORTRESS] = Option::U8("Fortress Carpenters", {"Normal", "Fast", "Free"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("FortressCarpenters"), mOptionDescriptions[RSK_GERUDO_FORTRESS]);
mOptions[RSK_RAINBOW_BRIDGE] = Option::U8("Rainbow Bridge", {"Vanilla", "Always open", "Stones", "Medallions", "Dungeon rewards", "Dungeons", "Tokens", "Greg"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("RainbowBridge"), mOptionDescriptions[RSK_RAINBOW_BRIDGE], WidgetType::Combobox, RO_BRIDGE_VANILLA, false, IMFLAG_NONE);
mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT] = Option::U8("Bridge Stone Count", {NumOpts(0, 4)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("StoneCount"), "", WidgetType::Slider, 3, true);
@@ -551,6 +552,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_DOOR_OF_TIME],
&mOptions[RSK_ZORAS_FOUNTAIN],
&mOptions[RSK_SLEEPING_WATERFALL],
+ &mOptions[RSK_LOCK_OVERWORLD_DOORS],
}, WidgetContainerType::COLUMN);
mOptionGroups[RSG_WORLD_IMGUI] = OptionGroup::SubGroup("World Settings", {
&mOptions[RSK_STARTING_AGE],
@@ -805,6 +807,7 @@ void Settings::CreateOptions() {
&mOptions[RSK_DOOR_OF_TIME],
&mOptions[RSK_ZORAS_FOUNTAIN],
&mOptions[RSK_SLEEPING_WATERFALL],
+ &mOptions[RSK_LOCK_OVERWORLD_DOORS],
&mOptions[RSK_GERUDO_FORTRESS],
&mOptions[RSK_RAINBOW_BRIDGE],
&mOptions[RSK_RAINBOW_BRIDGE_STONE_COUNT],
diff --git a/soh/soh/SohMenuBar.cpp b/soh/soh/SohMenuBar.cpp
index 1edb7e461..1bb47877b 100644
--- a/soh/soh/SohMenuBar.cpp
+++ b/soh/soh/SohMenuBar.cpp
@@ -773,7 +773,9 @@ void DrawEnhancementsMenu() {
UIWidgets::Tooltip("The default response to Kaepora Gaebora is always that you understood what he said");
UIWidgets::PaddedEnhancementCheckbox("Exit Market at Night", CVAR_ENHANCEMENT("MarketSneak"), true, false);
UIWidgets::Tooltip("Allows exiting Hyrule Castle Market Town to Hyrule Field at night by speaking to the guard next to the gate.");
- UIWidgets::PaddedEnhancementCheckbox("Shops and Games Always Open", CVAR_ENHANCEMENT("OpenAllHours"), true, false);
+ bool randoLockedOverworldDoors = IS_RANDO && OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LOCK_OVERWORLD_DOORS);
+ UIWidgets::PaddedEnhancementCheckbox("Shops and Games Always Open", CVAR_ENHANCEMENT("OpenAllHours"), true, false, randoLockedOverworldDoors,
+ "This is not compatible with the Locked Overworld Doors Randomizer option", UIWidgets::CheckboxGraphics::Checkmark);
UIWidgets::Tooltip("Shops and minigames are open both day and night. Requires scene reload to take effect.");
UIWidgets::PaddedEnhancementCheckbox("Link as default file name", CVAR_ENHANCEMENT("LinkDefaultName"), true, false);
UIWidgets::Tooltip("Allows you to have \"Link\" as a premade file name");
diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
index 99ce9729f..8208881d2 100644
--- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
+++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.c
@@ -11,6 +11,7 @@
#include "objects/object_mizu_objects/object_mizu_objects.h"
#include "objects/object_haka_door/object_haka_door.h"
#include "soh/ResourceManagerHelpers.h"
+#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#define FLAGS ACTOR_FLAG_UPDATE_CULLING_DISABLED
@@ -162,7 +163,7 @@ void EnDoor_SetupType(EnDoor* this, PlayState* play) {
}
this->actor.world.rot.y = 0x0000;
if (doorType == DOOR_LOCKED) {
- if (!Flags_GetSwitch(play, this->actor.params & 0x3F)) {
+ if (GameInteractor_Should(VB_DOOR_BE_LOCKED, !Flags_GetSwitch(play, this->actor.params & 0x3F), this)) {
this->lockTimer = 10;
}
} else if (doorType == DOOR_AJAR) {
@@ -201,8 +202,10 @@ void EnDoor_Idle(EnDoor* this, PlayState* play) {
Animation_PlayOnceSetSpeed(&this->skelAnime, D_809FCECC[this->animStyle],
(player->stateFlags1 & PLAYER_STATE1_IN_WATER) ? 0.75f : 1.5f);
if (this->lockTimer != 0) {
- gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]--;
- Flags_SetSwitch(play, this->actor.params & 0x3F);
+ if (GameInteractor_Should(VB_CONSUME_SMALL_KEY, true, this)) {
+ gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex]--;
+ Flags_SetSwitch(play, this->actor.params & 0x3F);
+ }
Audio_PlayActorSound2(&this->actor, NA_SE_EV_CHAIN_KEY_UNLOCK);
}
} else if (!Player_InCsMode(play)) {
@@ -214,7 +217,7 @@ void EnDoor_Idle(EnDoor* this, PlayState* play) {
}
if (ABS(phi_v0) < 0x3000) {
if (this->lockTimer != 0) {
- if (gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] <= 0) {
+ if (GameInteractor_Should(VB_NOT_HAVE_SMALL_KEY, gSaveContext.inventory.dungeonKeys[gSaveContext.mapIndex] <= 0, this)) {
Player* player2 = GET_PLAYER(play);
player2->naviTextId = -0x203;
diff --git a/soh/src/overlays/actors/ovl_En_Door/z_en_door.h b/soh/src/overlays/actors/ovl_En_Door/z_en_door.h
index 4e7ef1279..a21047d74 100644
--- a/soh/src/overlays/actors/ovl_En_Door/z_en_door.h
+++ b/soh/src/overlays/actors/ovl_En_Door/z_en_door.h
@@ -55,6 +55,9 @@ typedef struct EnDoor {
/* 0x0198 */ Vec3s jointTable[5];
/* 0x01B6 */ Vec3s morphTable[5];
/* 0x01D4 */ EnDoorActionFunc actionFunc;
+ // #region SOH [Randomizer]
+ /* */ RandomizerInf randomizerInf;
+ // #endregion
} EnDoor; // size = 0x01D8
#ifdef __cplusplus
diff --git a/soh/src/overlays/actors/ovl_player_actor/z_player.c b/soh/src/overlays/actors/ovl_player_actor/z_player.c
index 7b1454aaf..97a57caeb 100644
--- a/soh/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/soh/src/overlays/actors/ovl_player_actor/z_player.c
@@ -5418,7 +5418,7 @@ s32 Player_ActionHandler_1(Player* this, PlayState* play) {
this->stateFlags1 |= PLAYER_STATE1_IN_CUTSCENE;
Actor_DisableLens(play);
- if (((doorActor->params >> 7) & 7) == 3) {
+ if (GameInteractor_Should(VB_DOOR_PLAY_SCENE_TRANSITION, ((doorActor->params >> 7) & 7) == 3, doorActor)) {
checkPos.x = doorActor->world.pos.x - (sp6C * sp74);
checkPos.y = doorActor->world.pos.y + 10.0f;
checkPos.z = doorActor->world.pos.z - (sp6C * sp78);