merge and update options from develop

This commit is contained in:
Fredrik Andréasson 2025-01-28 02:59:39 +01:00
commit 20ed9deea9
56 changed files with 1442 additions and 1243 deletions

@ -1 +1 @@
Subproject commit 3a6518f5969d7f41f46ea73d524c4db0b3e984f4
Subproject commit 5341b017254a186da3ffe6d681d4e293769f23f4

View File

@ -0,0 +1,203 @@
#include "libultraship/bridge.h"
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
#include "soh/ShipInit.hpp"
#include "soh/Enhancements/randomizer/3drando/random.hpp"
#include "soh/Notification/Notification.h"
#include "soh/OTRGlobals.h"
extern "C" {
#include "variables.h"
#include "functions.h"
#include "macros.h"
extern PlayState* gPlayState;
GetItemEntry ItemTable_RetrieveEntry(s16 modIndex, s16 getItemID);
}
#define CVAR_EXTRA_TRAPS_NAME CVAR_ENHANCEMENT("ExtraTraps.Enabled")
#define CVAR_EXTRA_TRAPS_DEFAULT 0
#define CVAR_EXTRA_TRAPS_VALUE CVarGetInteger(CVAR_EXTRA_TRAPS_NAME, CVAR_EXTRA_TRAPS_DEFAULT)
typedef enum {
ADD_ICE_TRAP,
ADD_BURN_TRAP,
ADD_SHOCK_TRAP,
ADD_KNOCK_TRAP,
ADD_SPEED_TRAP,
ADD_BOMB_TRAP,
ADD_VOID_TRAP,
ADD_AMMO_TRAP,
ADD_KILL_TRAP,
ADD_TELEPORT_TRAP,
ADD_TRAP_MAX
} AltTrapType;
static AltTrapType roll = ADD_TRAP_MAX;
static int statusTimer = -1;
static int eventTimer = -1;
const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Ice"),
CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"),
CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"),
CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Void"),
CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Kill"),
CVAR_ENHANCEMENT("ExtraTraps.Teleport")
};
std::vector<AltTrapType> getEnabledAddTraps () {
std::vector<AltTrapType> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) {
if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues
}
enabledAddTraps.push_back(static_cast<AltTrapType>(i));
}
}
if (enabledAddTraps.size() == 0) {
enabledAddTraps.push_back(ADD_ICE_TRAP);
}
return enabledAddTraps;
};
static void RollRandomTrap(uint32_t seed) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
roll = RandomElement(getEnabledAddTraps());
switch (roll) {
case ADD_ICE_TRAP:
GameInteractor::RawAction::FreezePlayer();
break;
case ADD_BURN_TRAP:
GameInteractor::RawAction::BurnPlayer();
break;
case ADD_SHOCK_TRAP:
GameInteractor::RawAction::ElectrocutePlayer();
break;
case ADD_KNOCK_TRAP:
eventTimer = 3;
break;
case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::State::RunSpeedModifier = -2;
statusTimer = 200;
Notification::Emit({ .message = "Speed Decreased!" });
break;
case ADD_BOMB_TRAP:
eventTimer = 3;
break;
case ADD_VOID_TRAP:
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
eventTimer = 3;
break;
case ADD_AMMO_TRAP:
eventTimer = 3;
Notification::Emit({ .message = "Ammo Halved!" });
break;
case ADD_KILL_TRAP:
GameInteractor::RawAction::SetPlayerHealth(0);
break;
case ADD_TELEPORT_TRAP:
eventTimer = 3;
break;
default:
break;
}
}
static void OnPlayerUpdate() {
Player* player = GET_PLAYER(gPlayState);
if (statusTimer == 0) {
GameInteractor::State::RunSpeedModifier = 0;
}
if (eventTimer == 0) {
switch (roll) {
case ADD_KNOCK_TRAP:
GameInteractor::RawAction::KnockbackPlayer(1);
break;
case ADD_BOMB_TRAP:
GameInteractor::RawAction::SpawnActor(ACTOR_EN_BOM, 1);
break;
case ADD_VOID_TRAP:
Play_TriggerRespawn(gPlayState);
break;
case ADD_AMMO_TRAP:
AMMO(ITEM_STICK) = AMMO(ITEM_STICK) * 0.5;
AMMO(ITEM_NUT) = AMMO(ITEM_NUT) * 0.5;
AMMO(ITEM_SLINGSHOT) = AMMO(ITEM_SLINGSHOT) * 0.5;
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break;
case ADD_TELEPORT_TRAP: {
int entrance;
int index = Random(0, 7);
switch (index) {
case 0:
entrance = GI_TP_DEST_SERENADE;
break;
case 1:
entrance = GI_TP_DEST_REQUIEM;
break;
case 2:
entrance = GI_TP_DEST_BOLERO;
break;
case 3:
entrance = GI_TP_DEST_MINUET;
break;
case 4:
entrance = GI_TP_DEST_NOCTURNE;
break;
case 5:
entrance = GI_TP_DEST_PRELUDE;
break;
default:
entrance = GI_TP_DEST_LINKSHOUSE;
break;
}
GameInteractor::RawAction::TeleportPlayer(entrance);
break;
}
default:
break;
}
}
if (statusTimer >= 0) {
statusTimer--;
}
if (eventTimer >= 0) {
eventTimer--;
}
}
void RegisterExtraTraps() {
COND_HOOK(OnPlayerUpdate, CVAR_EXTRA_TRAPS_VALUE, OnPlayerUpdate);
COND_VB_SHOULD(VB_SHORT_CIRCUIT_GIVE_ITEM_PROCESS, true, {
if (!gSaveContext.ship.pendingIceTrapCount) {
return;
}
Player* player = GET_PLAYER(gPlayState);
*should = true;
gSaveContext.ship.pendingIceTrapCount--;
gSaveContext.ship.stats.count[COUNT_ICE_TRAPS]++;
GameInteractor_ExecuteOnItemReceiveHooks(ItemTable_RetrieveEntry(MOD_RANDOMIZER, RG_ICE_TRAP));
if (CVAR_EXTRA_TRAPS_VALUE) {
RollRandomTrap(gPlayState->sceneNum + player->getItemEntry.drawItemId);
} else {
GameInteractor::RawAction::FreezePlayer();
}
});
}
static RegisterShipInitFunc initFunc(RegisterExtraTraps, { CVAR_EXTRA_TRAPS_NAME });

View File

@ -10,7 +10,7 @@ extern "C" {
#include "variables.h"
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
static bool sEnteredBlueWarp = false;

View File

@ -305,7 +305,7 @@ EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
GetSelectedEnemies();
}
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
uint32_t finalSeed = seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
Random_Init(finalSeed);
uint32_t randomNumber = Random(0, RANDOMIZED_ENEMY_SPAWN_TABLE_SIZE);
return selectedEnemyList[randomNumber];

View File

@ -392,6 +392,7 @@ typedef enum {
/*** Give Items ***/
VB_SHORT_CIRCUIT_GIVE_ITEM_PROCESS,
VB_FREEZE_ON_SKULL_TOKEN,
// Opt: *EnBox
VB_GIVE_ITEM_FROM_CHEST,

View File

@ -125,8 +125,8 @@ namespace Rando {
std::make_shared<KaleidoEntryIconCountRequired>(
gTriforcePieceTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, Color_RGBA8{ 255,255,255,255 }, 0,
yOffset, reinterpret_cast<int*>(&gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected),
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1));
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1,
ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
yOffset += 18;
}
if (ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS)) {

View File

@ -535,7 +535,7 @@ void UpdateMirrorModeState(int32_t sceneNum) {
(sceneNum == SCENE_GANON_BOSS);
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSettings()->GetSeed()
uint32_t seed = sceneNum + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed()
: gSaveContext.ship.stats.fileCreatedAt);
Random_Init(seed);
}
@ -899,162 +899,6 @@ void RegisterBossDefeatTimestamps() {
});
}
typedef enum {
ADD_ICE_TRAP,
ADD_BURN_TRAP,
ADD_SHOCK_TRAP,
ADD_KNOCK_TRAP,
ADD_SPEED_TRAP,
ADD_BOMB_TRAP,
ADD_VOID_TRAP,
ADD_AMMO_TRAP,
ADD_KILL_TRAP,
ADD_TELEPORT_TRAP,
ADD_TRAP_MAX
} AltTrapType;
const char* altTrapTypeCvars[] = {
CVAR_ENHANCEMENT("ExtraTraps.Ice"),
CVAR_ENHANCEMENT("ExtraTraps.Burn"),
CVAR_ENHANCEMENT("ExtraTraps.Shock"),
CVAR_ENHANCEMENT("ExtraTraps.Knockback"),
CVAR_ENHANCEMENT("ExtraTraps.Speed"),
CVAR_ENHANCEMENT("ExtraTraps.Bomb"),
CVAR_ENHANCEMENT("ExtraTraps.Void"),
CVAR_ENHANCEMENT("ExtraTraps.Ammo"),
CVAR_ENHANCEMENT("ExtraTraps.Kill"),
CVAR_ENHANCEMENT("ExtraTraps.Teleport")
};
std::vector<AltTrapType> getEnabledAddTraps () {
std::vector<AltTrapType> enabledAddTraps;
for (int i = 0; i < ADD_TRAP_MAX; i++) {
if (CVarGetInteger(altTrapTypeCvars[i], 0)) {
if (gSaveContext.equips.buttonItems[0] == ITEM_FISHING_POLE && (i == ADD_VOID_TRAP || i == ADD_TELEPORT_TRAP)) {
continue; // don't add void or teleport if you're holding the fishing pole, as this causes issues
}
enabledAddTraps.push_back(static_cast<AltTrapType>(i));
}
}
if (enabledAddTraps.size() == 0) {
enabledAddTraps.push_back(ADD_ICE_TRAP);
}
return enabledAddTraps;
};
void RegisterAltTrapTypes() {
static AltTrapType roll = ADD_TRAP_MAX;
static int statusTimer = -1;
static int eventTimer = -1;
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnItemReceive>([](GetItemEntry itemEntry) {
if (!CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0) || itemEntry.modIndex != MOD_RANDOMIZER || itemEntry.getItemId != RG_ICE_TRAP) {
return;
}
roll = RandomElement(getEnabledAddTraps());
switch (roll) {
case ADD_ICE_TRAP:
GameInteractor::RawAction::FreezePlayer();
break;
case ADD_BURN_TRAP:
GameInteractor::RawAction::BurnPlayer();
break;
case ADD_SHOCK_TRAP:
GameInteractor::RawAction::ElectrocutePlayer();
break;
case ADD_KNOCK_TRAP:
eventTimer = 3;
break;
case ADD_SPEED_TRAP:
Audio_PlaySoundGeneral(NA_SE_VO_KZ_MOVE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
GameInteractor::State::RunSpeedModifier = -2;
statusTimer = 200;
Overlay_DisplayText(10, "Speed Decreased!");
break;
case ADD_BOMB_TRAP:
eventTimer = 3;
break;
case ADD_VOID_TRAP:
Audio_PlaySoundGeneral(NA_SE_EN_GANON_LAUGH, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
eventTimer = 3;
break;
case ADD_AMMO_TRAP:
eventTimer = 3;
Overlay_DisplayText(5, "Ammo Halved!");
break;
case ADD_KILL_TRAP:
GameInteractor::RawAction::SetPlayerHealth(0);
break;
case ADD_TELEPORT_TRAP:
eventTimer = 3;
break;
default:
break;
}
});
GameInteractor::Instance->RegisterGameHook<GameInteractor::OnPlayerUpdate>([]() {
Player* player = GET_PLAYER(gPlayState);
if (statusTimer == 0) {
GameInteractor::State::RunSpeedModifier = 0;
}
if (eventTimer == 0) {
switch (roll) {
case ADD_KNOCK_TRAP:
GameInteractor::RawAction::KnockbackPlayer(1);
break;
case ADD_BOMB_TRAP:
GameInteractor::RawAction::SpawnActor(ACTOR_EN_BOM, 1);
break;
case ADD_VOID_TRAP:
Play_TriggerRespawn(gPlayState);
break;
case ADD_AMMO_TRAP:
AMMO(ITEM_STICK) = AMMO(ITEM_STICK) * 0.5;
AMMO(ITEM_NUT) = AMMO(ITEM_NUT) * 0.5;
AMMO(ITEM_SLINGSHOT) = AMMO(ITEM_SLINGSHOT) * 0.5;
AMMO(ITEM_BOW) = AMMO(ITEM_BOW) * 0.5;
AMMO(ITEM_BOMB) = AMMO(ITEM_BOMB) * 0.5;
AMMO(ITEM_BOMBCHU) = AMMO(ITEM_BOMBCHU) * 0.5;
Audio_PlaySoundGeneral(NA_SE_VO_FR_SMILE_0, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
break;
case ADD_TELEPORT_TRAP: {
int entrance;
int index = 1 + rand() % 10;
switch (index) {
case 1:
entrance = GI_TP_DEST_SERENADE;
break;
case 2:
entrance = GI_TP_DEST_REQUIEM;
break;
case 3:
entrance = GI_TP_DEST_BOLERO;
break;
case 4:
entrance = GI_TP_DEST_MINUET;
break;
case 5:
entrance = GI_TP_DEST_NOCTURNE;
break;
case 6:
entrance = GI_TP_DEST_PRELUDE;
break;
default:
entrance = GI_TP_DEST_LINKSHOUSE;
break;
}
GameInteractor::RawAction::TeleportPlayer(entrance);
break;
}
default:
break;
}
}
statusTimer--;
eventTimer--;
});
}
void UpdateHurtContainerModeState(bool newState) {
static bool hurtEnabled = false;
if (hurtEnabled == newState) {
@ -1363,7 +1207,6 @@ void InitMods() {
RegisterBrokenGiantsKnifeFix();
RegisterEnemyDefeatCounts();
RegisterBossDefeatTimestamps();
RegisterAltTrapTypes();
RegisterRandomizedEnemySizes();
RegisterOpenAllHours();
RegisterToTMedallions();

View File

@ -75,7 +75,7 @@ void DrawPresetSelector(PresetType presetTypeId) {
}
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
if (presetTypeId == PRESET_TYPE_RANDOMIZER){
Rando::Context::GetInstance()->GetSettings()->ReloadOptions();
Rando::Settings::GetInstance()->ReloadOptions();
}
}
ImGui::PopStyleVar(1);

View File

@ -238,10 +238,10 @@ static int GetMaxGSCount() {
int maxBridge = 0;
int maxLACS = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex();
maxBridge = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get();
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex();
maxLACS = ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get();
}
maxBridge = std::max(maxBridge, maxLACS);
//Get the max amount of GS which could be useful from token reward locations
@ -266,7 +266,7 @@ static int GetMaxGSCount() {
maxUseful = 10;
}
//Return max of the two possible reasons tokens could be important, minus the tokens in the starting inventory
return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex();
return std::max(maxUseful, maxBridge) - ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Get();
}
std::string GetShopItemBaseName(std::string itemName) {

View File

@ -894,11 +894,11 @@ hintTextTable[RHT_FIRE_TEMPLE_NEAR_BOSS_CHEST] = HintText(CustomMessage("They sa
/*german*/ "",
/*french*/ "Selon moi, un #coeur dans le Temple du Feu# cache #[[1]]#.", {QM_RED, QM_GREEN}));
hintTextTable[RAND_INF_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a hot arena# reveals #[[1]]#.",
hintTextTable[RHT_FIRE_TEMPLE_MQ_LOOP_STALFOS_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a hot arena# reveals #[[1]]#.",
/*german*/ "!!!",
/*french*/ "Selon moi, #appeler le soleil dans une arène chaude# révèle #[[1]]#.", {QM_RED, QM_GREEN}));
hintTextTable[RAND_INF_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun behind a knight's throne in a volcano# reveals #[[1]]#.",
hintTextTable[RHT_FIRE_TEMPLE_MQ_LOOP_KNUCKLE_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun behind a knight's throne in a volcano# reveals #[[1]]#.",
/*german*/ "!!!",
/*french*/ "Selon moi, #appeler le soleil derrière le trône dun chevalier dans un volcan# révèle #[[1]]#.", {QM_RED, QM_GREEN}));

View File

@ -1950,6 +1950,10 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
hintTextTable[RHT_GF_KITCHEN_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a guarded kitchen# exposes #[[1]]#.", {QM_RED, QM_GREEN}));
hintTextTable[RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun for scrubs in the Lost Woods# reveals #[[1]]#.", { QM_RED, QM_GREEN }));
hintTextTable[RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY] = HintText(CustomMessage("They say that #calling the sun in a royal tomb# reveals #[[1]]#.", { QM_RED, QM_GREEN }));
hintTextTable[RHT_KF_GRASS] = HintText(CustomMessage("They say that #cutting some grass in a forest# reveals #[[1]]#.", { QM_RED, QM_GREEN }));
hintTextTable[RHT_LW_GRASS] = HintText(CustomMessage("They say that #cutting some grass in the woods# reveals #[[1]]#.", { QM_RED, QM_GREEN }));

View File

@ -222,18 +222,18 @@ uint8_t StonesRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t stones = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex();
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 6;
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 6;
} else if ((ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) && (ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON))) {
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 6;
stones = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 6;
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex() });
stones = std::max<uint8_t>({ stones, ctx->GetOption(RSK_LACS_STONE_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 6 )});
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 6 )});
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 6 )});
stones = std::max<uint8_t>({ stones, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 6 )});
}
return stones;
}
@ -242,18 +242,18 @@ uint8_t MedallionsRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t medallions = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex();
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get();
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex() - 3;
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get() - 3;
} else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex() - 3;
medallions = ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get() - 3;
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex() });
medallions = std::max({ medallions, ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get() });
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex() - 3 )});
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get() - 3 )});
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS) && ctx->GetOption(RSK_SHUFFLE_DUNGEON_REWARDS).Is(RO_DUNGEON_REWARDS_END_OF_DUNGEON)) {
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex() - 3 )});
medallions = std::max({ medallions, (uint8_t)(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get() - 3 )});
}
return medallions;
}
@ -262,10 +262,10 @@ uint8_t TokensRequiredBySettings() {
auto ctx = Rando::Context::GetInstance();
uint8_t tokens = 0;
if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex();
tokens = ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get();
}
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
tokens = std::max<uint8_t>({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex() });
tokens = std::max<uint8_t>({ tokens, ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get() });
}
return tokens;
}
@ -273,7 +273,7 @@ uint8_t TokensRequiredBySettings() {
std::vector<std::pair<RandomizerCheck, std::function<bool()>>> conditionalAlwaysHints = {
std::make_pair(RC_MARKET_10_BIG_POES, []() {
auto ctx = Rando::Context::GetInstance();
return ctx->GetOption(RSK_BIG_POE_COUNT).GetContextOptionIndex() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
return ctx->GetOption(RSK_BIG_POE_COUNT).Get() >= 3 && !ctx->GetOption(RSK_BIG_POES_HINT);
}), // Remember, the option's value being 3 means 4 are required
std::make_pair(RC_DEKU_THEATER_MASK_OF_TRUTH, []() {
auto ctx = Rando::Context::GetInstance();
@ -483,7 +483,7 @@ static void CreateTrialHints(uint8_t copies) {
AddGossipStoneHintCopies(copies, HINT_TYPE_HINT_KEY, "Trial", {RHT_ZERO_TRIALS});
} else {
std::vector<TrialInfo*> trials = ctx->GetTrials()->GetTrialList(); //there's probably a way to remove this assignment
if (ctx->GetOption(RSK_TRIAL_COUNT).GetContextOptionIndex() >= 4) {//4 or 5 required trials, get skipped trials
if (ctx->GetOption(RSK_TRIAL_COUNT).Get() >= 4) {//4 or 5 required trials, get skipped trials
trials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsSkipped();});
} else {//1 to 3 trials, get requried trials
auto requiredTrials = FilterFromPool(trials, [](TrialInfo* trial){return trial->IsRequired();});
@ -611,7 +611,7 @@ uint8_t PlaceHints(std::vector<uint8_t>& selectedHints, std::vector<HintDistribu
void CreateStoneHints() {
auto ctx = Rando::Context::GetInstance();
SPDLOG_DEBUG("\nNOW CREATING HINTS\n");
const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).GetContextOptionIndex()];
const HintSetting& hintSetting = hintSettingTable[ctx->GetOption(RSK_HINT_DISTRIBUTION).Get()];
std::vector<HintDistributionSetting> distTable = hintSetting.distTable;
// Apply impa's song exclusions when zelda is skipped
@ -738,7 +738,7 @@ void CreateAdultAltarHint() {
void CreateStaticHintFromData(RandomizerHint hint, StaticHintInfo staticData){
auto ctx = Rando::Context::GetInstance();
if (!ctx->GetHint(hint)->IsEnabled()){
Option option = ctx->GetOption(staticData.setting);
OptionValue& option = ctx->GetOption(staticData.setting);
if ((std::holds_alternative<bool>(staticData.condition) && option.Is(std::get<bool>(staticData.condition))) ||
(std::holds_alternative<uint8_t>(staticData.condition) && option.Is(std::get<uint8_t>(staticData.condition)))){

View File

@ -761,7 +761,7 @@ static void SetMinimalItemPool() {
ReplaceMaxItem(RG_PROGRESSIVE_BOMB_BAG, 1);
ReplaceMaxItem(RG_PIECE_OF_HEART, 0);
// Need an extra heart container when starting with 1 heart to be able to reach 3 hearts
ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() == 18)? 1 : 0);
ReplaceMaxItem(RG_HEART_CONTAINER, (ctx->GetOption(RSK_STARTING_HEARTS).Get() == 18)? 1 : 0);
}
void GenerateItemPool() {
@ -827,7 +827,7 @@ void GenerateItemPool() {
if (ctx->GetOption(RSK_TRIFORCE_HUNT)) {
ctx->possibleIceTrapModels.push_back(RG_TRIFORCE_PIECE);
AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).GetContextOptionIndex() + 1));
AddItemToMainPool(RG_TRIFORCE_PIECE, (ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_TOTAL).Get() + 1));
ctx->PlaceItemInLocation(RC_TRIFORCE_COMPLETED, RG_TRIFORCE); // Win condition
ctx->PlaceItemInLocation(RC_GANON, GetJunkItem(), false, true);
} else {
@ -944,7 +944,7 @@ void GenerateItemPool() {
if (fsMode.IsNot(RO_FISHSANITY_OFF)) {
if (fsMode.Is(RO_FISHSANITY_POND) || fsMode.Is(RO_FISHSANITY_BOTH)) {
// 17 max child pond fish
uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).GetContextOptionIndex();
uint8_t pondCt = ctx->GetOption(RSK_FISHSANITY_POND_COUNT).Get();
for (uint8_t i = 0; i < pondCt; i++) {
AddItemToMainPool(GetJunkItem());
}
@ -1527,7 +1527,7 @@ void GenerateItemPool() {
if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_KAK_TOKENS)) {
ctx->PlaceItemInLocation(RC_KAK_100_GOLD_SKULLTULA_REWARD, RG_GANONS_CASTLE_BOSS_KEY);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).GetContextOptionIndex() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Get() >= RO_GANON_BOSS_KEY_LACS_VANILLA && ctx->GetOption(RSK_GANONS_BOSS_KEY).IsNot(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
ctx->PlaceItemInLocation(RC_TOT_LIGHT_ARROWS_CUTSCENE, RG_GANONS_CASTLE_BOSS_KEY);
} else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_VANILLA)) {
ctx->PlaceItemInLocation(RC_GANONS_TOWER_BOSS_KEY_CHEST, RG_GANONS_CASTLE_BOSS_KEY);

View File

@ -44,12 +44,12 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
return false; // TODO: Not sure if this is correct but I don't think we support this functionality yet anyway.
}
ctx->GetSettings()->SetSeedString(seedInput);
uint32_t seedHash = boost::hash_32<std::string>{}(ctx->GetSettings()->GetSeedString());
ctx->GetSettings()->SetSeed(seedHash & 0xFFFFFFFF);
ctx->SetSeedString(seedInput);
uint32_t seedHash = boost::hash_32<std::string>{}(ctx->GetSeedString());
ctx->SetSeed(seedHash & 0xFFFFFFFF);
ctx->ClearItemLocations();
int ret = Playthrough::Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
int ret = Playthrough::Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);
if (ret < 0) {
if (ret == -1) { // Failed to generate after 5 tries
SPDLOG_ERROR("Failed to generate after 5 tries.");
@ -60,14 +60,6 @@ bool GenerateRandomizer(std::set<RandomizerCheck> excludedLocations, std::set<Ra
}
}
// Restore settings that were set to a specific value for vanilla logic
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
for (Rando::Option* setting : ctx->GetSettings()->VanillaLogicDefaults) {
setting->RestoreDelayedOption();
}
ctx->GetOption(RSK_KEYSANITY).RestoreDelayedOption();
}
StopPerformanceTimer(PT_WHOLE_SEED);
SPDLOG_DEBUG("Full Seed Genration Time: {}ms", GetPerformanceTimer(PT_WHOLE_SEED).count());
SPDLOG_DEBUG("LogicReset time: {}ms", GetPerformanceTimer(PT_LOGIC_RESET).count());

View File

@ -31,10 +31,12 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
Regions::AccessReset();
StopPerformanceTimer(PT_REGION_RESET);
ctx->GetSettings()->FinalizeSettings(excludedLocations, enabledTricks);
ctx->FinalizeSettings(excludedLocations, enabledTricks);
// once the settings have been finalized turn them into a string for hashing
std::string settingsStr;
for (const Rando::OptionGroup& optionGroup : ctx->GetSettings()->GetOptionGroups()) {
auto& optionGroups = Rando::Settings::GetInstance()->GetOptionGroups();
for (size_t i = 0; i < RSG_MAX; i++) {
auto& optionGroup = optionGroups[i];
// don't go through non-menus
if (optionGroup.GetContainsType() == Rando::OptionGroupType::SUBGROUP) {
continue;
@ -43,7 +45,15 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
for (Rando::Option* option : optionGroup.GetOptions()) {
if (option->IsCategory(Rando::OptionCategory::Setting)) {
if (option->GetOptionCount() > 0) {
settingsStr += option->GetSelectedOptionText();
if (i >= RSG_EXCLUDES_KOKIRI_FOREST && i <= RSG_EXCLUDES_GANONS_CASTLE) {
auto locationOption = static_cast<Rando::LocationOption*>(option);
settingsStr += option->GetOptionText(ctx->GetLocationOption(locationOption->GetKey()).Get());
} else if (i == RSG_TRICKS) {
auto trickOption = static_cast<Rando::TrickOption*>(option);
settingsStr += option->GetOptionText(ctx->GetTrickOption(trickOption->GetKey()).Get());
} else {
settingsStr += option->GetOptionText(ctx->GetOption(option->GetKey()).Get());
}
}
}
}
@ -53,9 +63,9 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
settingsStr += (char*)gBuildVersion;
}
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(ctx->GetSettings()->GetSeed()) + settingsStr);
uint32_t finalHash = boost::hash_32<std::string>{}(std::to_string(ctx->GetSeed()) + settingsStr);
Random_Init(finalHash);
ctx->GetSettings()->SetHash(std::to_string(finalHash));
ctx->SetHash(std::to_string(finalHash));
if (ctx->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
@ -94,12 +104,12 @@ int Playthrough_Repeat(std::set<RandomizerCheck> excludedLocations, std::set<Ran
auto ctx = Rando::Context::GetInstance();
uint32_t repeatedSeed = 0;
for (int i = 0; i < count; i++) {
ctx->GetSettings()->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
repeatedSeed = boost::hash_32<std::string>{}(ctx->GetSettings()->GetSeedString());
ctx->GetSettings()->SetSeed(repeatedSeed % 0xFFFFFFFF);
ctx->SetSeedString(std::to_string(rand() % 0xFFFFFFFF));
repeatedSeed = boost::hash_32<std::string>{}(ctx->GetSeedString());
ctx->SetSeed(repeatedSeed % 0xFFFFFFFF);
SPDLOG_DEBUG("testing seed: %d", repeatedSeed);
ClearProgress();
Playthrough_Init(ctx->GetSettings()->GetSeed(), excludedLocations, enabledTricks);
Playthrough_Init(ctx->GetSeed(), excludedLocations, enabledTricks);
SPDLOG_INFO("Seeds Generated: {}", i + 1);
}

View File

@ -156,7 +156,7 @@ int GetPriceFromMax(int max) {
uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSettings) {
auto ctx = Rando::Context::GetInstance();
switch (ctx->GetOption(priceSettings.main).GetContextOptionIndex()){
switch (ctx->GetOption(priceSettings.main).Get()){
case RO_PRICE_VANILLA:
return loc->GetVanillaPrice();
case RO_PRICE_CHEAP_BALANCED:
@ -172,19 +172,19 @@ uint16_t GetPriceFromSettings(Rando::Location *loc, PriceSettingsStruct priceSet
return 150;
}
case RO_PRICE_FIXED:
return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).GetContextOptionIndex() * 5;
return (uint16_t)ctx->GetOption(priceSettings.fixedPrice).Get() * 5;
case RO_PRICE_RANGE:{
uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).GetContextOptionIndex() * 5;
uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).GetContextOptionIndex() * 5;
uint16_t range1 = (uint16_t)ctx->GetOption(priceSettings.range1).Get() * 5;
uint16_t range2 = (uint16_t)ctx->GetOption(priceSettings.range2).Get() * 5;
return range1 < range2 ? Random(range1, range2+1) : Random(range2, range1+1);
}
case RO_PRICE_SET_BY_WALLET:{
bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).GetContextOptionIndex();
uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).GetContextOptionIndex();
uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).GetContextOptionIndex();
uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).GetContextOptionIndex();
uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).GetContextOptionIndex();
uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).GetContextOptionIndex() : 0;
bool isTycoon = ctx->GetOption(RSK_INCLUDE_TYCOON_WALLET).Get();
uint16_t noWeight = ctx->GetOption(priceSettings.noWallet).Get();
uint16_t childWeight = ctx->GetOption(priceSettings.childWallet).Get();
uint16_t adultWeight = ctx->GetOption(priceSettings.adultWallet).Get();
uint16_t giantWeight = ctx->GetOption(priceSettings.giantWallet).Get();
uint16_t tycoonWeight = isTycoon ? ctx->GetOption(priceSettings.tycoonWallet).Get() : 0;
uint16_t totalWeight = noWeight + childWeight + adultWeight + giantWeight + tycoonWeight;
if (totalWeight == 0){ //if no weight, return from sane range
return Random(0, 501);

View File

@ -2,7 +2,7 @@
#include "../dungeon.h"
#include "../static_data.h"
#include "../context.h"
#include "../settings.h"
#include "../entrance.h"
#include "random.hpp"
#include "../trial.h"
@ -46,7 +46,7 @@ std::string placementtxt;
void GenerateHash() {
auto ctx = Rando::Context::GetInstance();
std::string hash = ctx->GetSettings()->GetHash();
std::string hash = ctx->GetHash();
// adds leading 0s to the hash string if it has less than 10 digits.
while (hash.length() < 10) {
hash = "0" + hash;
@ -139,10 +139,10 @@ static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance)
// Writes the settings (without excluded locations, starting inventory and tricks) to the spoilerLog document.
static void WriteSettings() {
auto ctx = Rando::Context::GetInstance();
std::array<Rando::Option, RSK_MAX> options = ctx->GetSettings()->GetAllOptions();
std::array<Rando::Option, RSK_MAX> options = Rando::Settings::GetInstance()->GetAllOptions();
for (const Rando::Option& option : options) {
if (option.GetName() != ""){
jsonData["settings"][option.GetName()] = option.GetSelectedOptionText();
jsonData["settings"][option.GetName()] = option.GetOptionText(ctx->GetOption(option.GetKey()).Get());
}
}
}
@ -157,9 +157,9 @@ std::string RemoveLineBreaks(std::string s) {
static void WriteExcludedLocations() {
auto ctx = Rando::Context::GetInstance();
for (size_t i = 1; i < ctx->GetSettings()->GetExcludeLocationsOptions().size(); i++) {
for (const auto& location : ctx->GetSettings()->GetExcludeLocationsOptions()[i]) {
if (location->GetContextOptionIndex() == RO_LOCATION_INCLUDE) {
for (size_t i = 1; i < Rando::Settings::GetInstance()->GetExcludeLocationsOptions().size(); i++) {
for (const auto& location : Rando::Settings::GetInstance()->GetExcludeLocationsOptions()[i]) {
if (ctx->GetOption(location->GetKey()).Get() == RO_LOCATION_INCLUDE) {
continue;
}
@ -172,11 +172,11 @@ static void WriteExcludedLocations() {
// Writes the starting inventory to the spoiler log, if there is any.
static void WriteStartingInventory() {
auto ctx = Rando::Context::GetInstance();
const Rando::OptionGroup& optionGroup = ctx->GetSettings()->GetOptionGroup(RSG_STARTING_INVENTORY);
const Rando::OptionGroup& optionGroup = Rando::Settings::GetInstance()->GetOptionGroup(RSG_STARTING_INVENTORY);
for (const Rando::OptionGroup* subGroup : optionGroup.GetSubGroups()) {
if (subGroup->GetContainsType() == Rando::OptionGroupType::DEFAULT) {
for (Rando::Option* option : subGroup->GetOptions()) {
jsonData["settings"][option->GetName()] = option->GetSelectedOptionText();
jsonData["settings"][option->GetName()] = option->GetOptionText(ctx->GetOption(option->GetKey()).Get());
}
}
}
@ -186,8 +186,8 @@ static void WriteStartingInventory() {
static void WriteEnabledTricks() {
auto ctx = Rando::Context::GetInstance();
for (const auto& setting : ctx->GetSettings()->GetOptionGroup(RSG_TRICKS).GetOptions()) {
if (setting->GetContextOptionIndex() != RO_GENERIC_ON) {
for (const auto& setting : Rando::Settings::GetInstance()->GetOptionGroup(RSG_TRICKS).GetOptions()) {
if (ctx->GetOption(setting->GetKey()).IsNot(RO_GENERIC_ON)) {
continue;
}
jsonData["enabledTricks"].push_back(RemoveLineBreaks(setting->GetName()).c_str());
@ -322,8 +322,8 @@ const char* SpoilerLog_Write() {
jsonData["version"] = (char*) gBuildVersion;
jsonData["git_branch"] = (char*) gGitBranch;
jsonData["git_commit"] = (char*) gGitCommitHash;
jsonData["seed"] = ctx->GetSettings()->GetSeedString();
jsonData["finalSeed"] = ctx->GetSettings()->GetSeed();
jsonData["seed"] = ctx->GetSeedString();
jsonData["finalSeed"] = ctx->GetSeed();
// Write Hash
int index = 0;

View File

@ -112,7 +112,7 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_EMPTY_BOTTLE, 1);
// }
// AddItemToInventory(RG_RUTOS_LETTER, StartingRutoBottle.Value<uint8_t>());
AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).GetContextOptionIndex());
AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).Get());
AddItemToInventory(RG_ZELDAS_LULLABY, ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY) ? 1 : 0);
AddItemToInventory(RG_EPONAS_SONG, ctx->GetOption(RSK_STARTING_EPONAS_SONG) ? 1 : 0);
AddItemToInventory(RG_SARIAS_SONG, ctx->GetOption(RSK_STARTING_SARIAS_SONG) ? 1 : 0);
@ -153,21 +153,21 @@ void GenerateStartingInventory() {
// AddItemToInventory(RG_SPIRIT_MEDALLION, StartingSpiritMedallion.Value<uint8_t>());
// AddItemToInventory(RG_SHADOW_MEDALLION, StartingShadowMedallion.Value<uint8_t>());
// AddItemToInventory(RG_LIGHT_MEDALLION, StartingLightMedallion.Value<uint8_t>());
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).GetContextOptionIndex());
AddItemToInventory(RG_GOLD_SKULLTULA_TOKEN, ctx->GetOption(RSK_STARTING_SKULLTULA_TOKEN).Get());
int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() - 2;
int8_t hearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() - 2;
AdditionalHeartContainers = 0;
if (hearts < 0) {
AddItemToInventory(RG_PIECE_OF_HEART, 4);
// Plentiful and minimal have less than 4 standard pieces of heart so also replace the winner heart
if (ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 0 || ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex() == 3) {
if (ctx->GetOption(RSK_ITEM_POOL).Get() == 0 || ctx->GetOption(RSK_ITEM_POOL).Get() == 3) {
AddItemToInventory(RG_TREASURE_GAME_HEART);
}
AdditionalHeartContainers = 1 - hearts;
} else if (hearts > 0) {
// 16 containers in plentiful, 8 in balanced and 0 in the others
uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).GetContextOptionIndex());
uint8_t maxContainers = 8 * std::max(0, 2 - ctx->GetOption(RSK_ITEM_POOL).Get());
if (hearts <= maxContainers) {
AddItemToInventory(RG_HEART_CONTAINER, hearts);

View File

@ -9,7 +9,7 @@ extern PlayState* gPlayState;
#include "src/overlays/actors/ovl_En_Door/z_en_door.h"
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
using SceneDoorParamsPair = std::pair<int, int>;
std::map<SceneDoorParamsPair, RandomizerInf> lookupTable = {

View File

@ -23,7 +23,7 @@ void ShuffleFreestanding_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* sh
Rando::Location* loc = OTRGlobals::Instance->gRandomizer->GetCheckObjectFromActor(item00->actor.id, gPlayState->sceneNum, params);
uint8_t isDungeon = loc->IsDungeon();
uint8_t freestandingSetting =
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).GetContextOptionIndex();
Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_FREESTANDING).Get();
RandomizerCheck randomizerCheck = loc->GetRandomizerCheck();
bool checkObtained = Rando::Context::GetInstance()->GetItemLocation(randomizerCheck)->HasObtained();

View File

@ -28,7 +28,7 @@ extern "C" void ObjTsubo_RandomizerDraw(Actor* thisx, PlayState* play) {
uint8_t ObjTsubo_RandomizerHoldsItem(ObjTsubo* potActor, PlayState* play) {
RandomizerCheck rc = potActor->potIdentity.randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
uint8_t potSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).GetContextOptionIndex();
uint8_t potSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
// Don't pull randomized item if pot isn't randomized or is already checked
if (!IS_RANDO || (potSetting == RO_SHUFFLE_POTS_OVERWORLD && isDungeon) ||
@ -87,7 +87,7 @@ void ShufflePots_OnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va
// Unlock early Ganon's Boss Key doors to allow access to the pots there when pots are shuffled in dungeon
if (id == VB_LOCK_BOSS_DOOR) {
DoorShutter* doorActor = va_arg(args, DoorShutter*);
uint8_t shufflePotSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).GetContextOptionIndex();
uint8_t shufflePotSetting = Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Get();
if (gPlayState->sceneNum == SCENE_GANONS_TOWER && doorActor->dyna.actor.world.pos.y == 800 &&
(shufflePotSetting == RO_SHUFFLE_POTS_DUNGEONS || shufflePotSetting == RO_SHUFFLE_POTS_ALL)) {
*should = false;

View File

@ -28,8 +28,31 @@ Context::Context() {
mDungeons = std::make_shared<Dungeons>();
mLogic = std::make_shared<Logic>();
mTrials = std::make_shared<Trials>();
mSettings = std::make_shared<Settings>();
mFishsanity = std::make_shared<Fishsanity>();
VanillaLogicDefaults = {
// RANDOTODO check what this does
&mOptions[RSK_LINKS_POCKET],
&mOptions[RSK_SHUFFLE_DUNGEON_REWARDS],
&mOptions[RSK_SHUFFLE_SONGS],
&mOptions[RSK_SHOPSANITY],
&mOptions[RSK_SHOPSANITY_COUNT],
&mOptions[RSK_SHOPSANITY_PRICES],
&mOptions[RSK_SHOPSANITY_PRICES_AFFORDABLE],
&mOptions[RSK_FISHSANITY],
&mOptions[RSK_FISHSANITY_POND_COUNT],
&mOptions[RSK_FISHSANITY_AGE_SPLIT],
&mOptions[RSK_SHUFFLE_SCRUBS],
&mOptions[RSK_SHUFFLE_BEEHIVES],
&mOptions[RSK_SHUFFLE_COWS],
&mOptions[RSK_SHUFFLE_POTS],
&mOptions[RSK_SHUFFLE_FREESTANDING],
&mOptions[RSK_SHUFFLE_MERCHANTS],
&mOptions[RSK_SHUFFLE_FROG_SONG_RUPEES],
&mOptions[RSK_SHUFFLE_ADULT_TRADE],
&mOptions[RSK_SHUFFLE_100_GS_REWARD],
&mOptions[RSK_SHUFFLE_FAIRIES],
&mOptions[RSK_GOSSIP_STONE_HINTS],
};
}
RandomizerArea Context::GetAreaFromString(std::string str) {
@ -94,7 +117,7 @@ void Context::PlaceItemInLocation(const RandomizerCheck locKey, const Randomizer
const auto loc = GetItemLocation(locKey);
SPDLOG_DEBUG(StaticData::RetrieveItem(item).GetName().GetEnglish() + " placed at " + StaticData::GetLocation(locKey)->GetName() + "\n");
if (applyEffectImmediately || mSettings->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_GLITCHLESS) || mSettings->GetOption(RSK_LOGIC_RULES).Is(RO_LOGIC_VANILLA)) {
if (applyEffectImmediately || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_GLITCHLESS) || mOptions[RSK_LOGIC_RULES].Is(RO_LOGIC_VANILLA)) {
StaticData::RetrieveItem(item).ApplyEffect();
}
@ -130,22 +153,22 @@ bool Context::IsQuestOfLocationActive(RandomizerCheck rc) {
void Context::GenerateLocationPool() {
allLocations.clear();
if (mSettings->GetOption(RSK_TRIFORCE_HUNT)) {
if (mOptions[RSK_TRIFORCE_HUNT]) {
AddLocation(RC_TRIFORCE_COMPLETED);
}
AddLocations(StaticData::GetOverworldLocations());
if (mSettings->GetOption(RSK_FISHSANITY).IsNot(RO_FISHSANITY_OFF)) {
if (mOptions[RSK_FISHSANITY].IsNot(RO_FISHSANITY_OFF)) {
AddLocations(mFishsanity->GetFishsanityLocations().first);
}
if (mSettings->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_OVERWORLD) ||
mSettings->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
if (mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_OVERWORLD) ||
mOptions[RSK_SHUFFLE_POTS].Is(RO_SHUFFLE_POTS_ALL)) {
AddLocations(StaticData::GetOverworldPotLocations());
}
if (mSettings->GetOption(RSK_GRASSANITY).Is(RO_SHUFFLE_GRASS_OVERWORLD) ||
mSettings->GetOption(RSK_GRASSANITY).Is(RO_SHUFFLE_GRASS_ALL)) {
if (mOptions[RSK_GRASSANITY].Is(RO_SHUFFLE_GRASS_OVERWORLD) ||
mOptions[RSK_GRASSANITY].Is(RO_SHUFFLE_GRASS_ALL)) {
AddLocations(StaticData::GetOverworldGrassLocations());
}
@ -158,7 +181,17 @@ void Context::AddExcludedOptions() {
AddLocations(dungeon->GetEveryLocation(), &everyPossibleLocation);
}
for (const RandomizerCheck rc : everyPossibleLocation) {
GetItemLocation(rc)->AddExcludeOption();
bool alreadyAdded = false;
Location* loc = StaticData::GetLocation(rc);
for (Option* location : Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc->GetArea()))
{
if (location->GetName() == loc->GetExcludedOption()->GetName()) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
Rando::Settings::GetInstance()->GetExcludeOptionsForArea(loc->GetArea()).push_back(loc->GetExcludedOption());
}
}
}
@ -294,7 +327,7 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
nlohmann::json spoilerFileJson;
spoilerFileStream >> spoilerFileJson;
ParseHashIconIndexesJson(spoilerFileJson);
mSettings->ParseJson(spoilerFileJson);
Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
ParseItemLocationsJson(spoilerFileJson);
ParseHintJson(spoilerFileJson);
mEntranceShuffler->ParseJson(spoilerFileJson);
@ -367,10 +400,6 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
CreateStaticHints();
}
std::shared_ptr<Settings> Context::GetSettings() {
return mSettings;
}
std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
return mEntranceShuffler;
}
@ -410,12 +439,28 @@ Sprite* Context::GetSeedTexture(const uint8_t index) {
return &gSeedTextures[index];
}
Option& Context::GetOption(const RandomizerSettingKey key) const {
return mSettings->GetOption(key);
OptionValue& Context::GetOption(const RandomizerSettingKey key) {
return mOptions[key];
}
TrickOption& Context::GetTrickOption(const RandomizerTrick key) const {
return mSettings->GetTrickOption(key);
OptionValue& Context::GetOption(const RandomizerTrick key) {
return mTrickOptions[key];
}
OptionValue& Context::GetOption(const RandomizerCheck key) {
return itemLocationTable[key].GetExcludedOption();
}
OptionValue& Context::GetTrickOption(const RandomizerTrick key) {
return mTrickOptions[key];
}
OptionValue& Context::GetLocationOption(const RandomizerCheck key) {
return itemLocationTable[key].GetExcludedOption();
}
RandoOptionLACSCondition Context::LACSCondition() const {
return mLACSCondition;
}
std::shared_ptr<Kaleido> Context::GetKaleido() {
@ -424,4 +469,28 @@ std::shared_ptr<Kaleido> Context::GetKaleido() {
}
return mKaleido;
}
std::string Context::GetHash() const {
return mHash;
}
void Context::SetHash(std::string hash) {
mHash = std::move(hash);
}
const std::string& Context::GetSeedString() const {
return mSeedString;
}
void Context::SetSeedString(std::string seedString) {
mSeedString = std::move(seedString);
}
uint32_t Context::GetSeed() const {
return mFinalSeed;
}
void Context::SetSeed(const uint32_t seed) {
mFinalSeed = seed;
}
} // namespace Rando

View File

@ -25,7 +25,6 @@
namespace Rando {
class EntranceShuffler;
class Logic;
class Settings;
class Dungeons;
class DungeonInfo;
class TrialInfo;
@ -63,7 +62,24 @@ class Context {
void SetSeedGenerated(bool seedGenerated = true);
bool IsSpoilerLoaded() const;
void SetSpoilerLoaded(bool spoilerLoaded = true);
std::shared_ptr<Settings> GetSettings();
/**
* @brief Reset all RandomizerTrick keys.
*/
void ResetTrickOptions();
/**
* @brief Runs before seed generation to ensure all options are compatible with each
* other and resolve options that have been set to random (such as random trial count,
* or starting age).
*
* @param excludedLocations Set of locations that should be forced to have junk items.
* @param enabledTricks Set of tricks that should be considered logically possible. Tricks
* are things that are possible to do in gameplay but are difficult, not intuitive or that
* require more extensive game knowledge, i.e. opening invisible chests without the Lens of Truth.
*/
void FinalizeSettings(const std::set<RandomizerCheck>& excludedLocations,
const std::set<RandomizerTrick>& enabledTricks);
std::shared_ptr<EntranceShuffler> GetEntranceShuffler();
std::shared_ptr<Dungeons> GetDungeons();
std::shared_ptr<Fishsanity> GetFishsanity();
@ -74,8 +90,19 @@ class Context {
TrialInfo* GetTrial(size_t key) const;
TrialInfo* GetTrial(TrialKey key) const;
static Sprite* GetSeedTexture(uint8_t index);
Option& GetOption(RandomizerSettingKey key) const;
TrickOption& GetTrickOption(RandomizerTrick key) const;
OptionValue& GetOption(RandomizerSettingKey key);
OptionValue& GetOption(RandomizerTrick key);
OptionValue& GetOption(RandomizerCheck key);
OptionValue& GetTrickOption(RandomizerTrick key);
OptionValue& GetLocationOption(RandomizerCheck key);
/**
* @brief Gets the resolved Light Arrow CutScene check condition.
* There is no direct option for this, it is inferred based on the value of a few other options.
*
* @return RandoOptionLACSCondition
*/
RandoOptionLACSCondition LACSCondition() const;
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
void ParseSpoiler(const char* spoilerFileName);
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
@ -87,16 +114,61 @@ class Context {
std::vector<RandomizerCheck> everyPossibleLocation = {};
std::vector<RandomizerGet> possibleIceTrapModels = {};
std::unordered_map<RandomizerCheck, RandomizerGet> iceTrapModels = {};
std::vector<OptionValue*> VanillaLogicDefaults = {};
std::array<uint8_t, 5> hashIconIndexes = {};
bool playthroughBeatable = false;
bool allLocationsReachable = false;
RandomizerArea GetAreaFromString(std::string str);
/**
* @brief Get the hash for the current seed.
*
* @return std::string
*/
std::string GetHash() const;
/**
* @brief Get the Seed String
*
* @return const std::string&
*/
const std::string& GetSeedString() const;
/**
* @brief Set the Seed String
*
* @param seedString
*/
void SetSeedString(std::string seedString);
/**
* @brief Get the Seed
*
* @return const uint32_t
*/
uint32_t GetSeed() const;
/**
* @brief Set the Seed
*
* @param seed
*/
void SetSeed(uint32_t seed);
/**
* @brief Set the Seed Hash for the current seed.
*
* @param hash
*/
void SetHash(std::string hash);
private:
static std::weak_ptr<Context> mContext;
std::array<Hint, RH_MAX> hintTable = {};
std::array<ItemLocation, RC_MAX> itemLocationTable = {};
std::shared_ptr<Settings> mSettings;
std::array<OptionValue, RSK_MAX> mOptions;
std::array<OptionValue, RT_MAX> mTrickOptions;
RandoOptionLACSCondition mLACSCondition = RO_LACS_VANILLA;
std::shared_ptr<EntranceShuffler> mEntranceShuffler;
std::shared_ptr<Dungeons> mDungeons;
std::shared_ptr<Logic> mLogic;
@ -105,5 +177,8 @@ class Context {
std::shared_ptr<Kaleido> mKaleido;
bool mSeedGenerated = false;
bool mSpoilerLoaded = false;
std::string mHash;
std::string mSeedString;
uint32_t mFinalSeed = 0;
};
} // namespace Rando

View File

@ -150,13 +150,13 @@ void DungeonInfo::PlaceVanillaSmallKeys() const {
// Gets the chosen dungeon locations for a playthrough (so either MQ or Vanilla)
std::vector<RandomizerCheck> DungeonInfo::GetDungeonLocations() const {
auto locations = masterQuest ? mqLocations : vanillaLocations;
if (Context::GetInstance()->GetSettings()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
Context::GetInstance()->GetSettings()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
if (Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_DUNGEONS) ||
Context::GetInstance()->GetOption(RSK_SHUFFLE_POTS).Is(RO_SHUFFLE_POTS_ALL)) {
auto potLocations = masterQuest ? mqPots : vanillaPots;
AddElementsToPool(locations, potLocations);
}
if (Context::GetInstance()->GetSettings()->GetOption(RSK_GRASSANITY).Is(RO_SHUFFLE_GRASS_DUNGEONS) ||
Context::GetInstance()->GetSettings()->GetOption(RSK_GRASSANITY).Is(RO_SHUFFLE_GRASS_ALL)) {
if (Context::GetInstance()->GetOption(RSK_GRASSANITY).Is(RO_SHUFFLE_GRASS_DUNGEONS) ||
Context::GetInstance()->GetOption(RSK_GRASSANITY).Is(RO_SHUFFLE_GRASS_ALL)) {
auto grassLocations = masterQuest ? mqGrass : vanillaGrass;
AddElementsToPool(locations, grassLocations);
}

View File

@ -1318,12 +1318,12 @@ int EntranceShuffler::ShuffleAllEntrances() {
(ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES) ? 1 : 0) + (ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES) ? 1 : 0) +
(ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES) ? 1 : 0);
if (totalMixedPools < 2) {
ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).SetContextIndex(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_BOSS_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_OVERWORLD_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_INTERIOR_ENTRANCES).Set(RO_GENERIC_OFF);
ctx->GetOption(RSK_MIX_GROTTO_ENTRANCES).Set(RO_GENERIC_OFF);
}
if (ctx->GetOption(RSK_MIXED_ENTRANCE_POOLS)) {
std::set<EntranceType> poolsToMix = {};

View File

@ -17,7 +17,7 @@ extern PlayState* gPlayState;
#define FSi OTRGlobals::Instance->gRandoContext->GetFishsanity()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
/**
* @brief Parallel list of pond fish checks for both ages

View File

@ -43,7 +43,7 @@ uint8_t EnKusa_RandomizerHoldsItem(EnKusa* grassActor, PlayState* play) {
RandomizerCheck rc = grassActor->grassIdentity.randomizerCheck;
uint8_t isDungeon = Rando::StaticData::GetLocation(rc)->IsDungeon();
uint8_t grassSetting = Rando::Context::GetInstance()->GetOption(RSK_GRASSANITY).GetContextOptionIndex();
uint8_t grassSetting = Rando::Context::GetInstance()->GetOption(RSK_GRASSANITY).Get();
// Don't pull randomized item if grass isn't randomized or is already checked
if (!IS_RANDO || (grassSetting == RO_SHUFFLE_GRASS_OVERWORLD && isDungeon) ||

View File

@ -559,23 +559,23 @@ CustomMessage Hint::GetBridgeReqsText() {
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_STONES_HINT].GetHintMessage();
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex());
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_MEDALLIONS_HINT].GetHintMessage();
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex());
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_REWARDS_HINT].GetHintMessage();
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex());
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_DUNGEONS_HINT].GetHintMessage();
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex());
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS)) {
bridgeMessage = StaticData::hintTextTable[RHT_BRIDGE_TOKENS_HINT].GetHintMessage();
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex());
bridgeMessage.InsertNumber(ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get());
}
else if (ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG)) {
return StaticData::hintTextTable[RHT_BRIDGE_GREG_HINT].GetHintMessage();
@ -613,23 +613,23 @@ CustomMessage Hint::GetGanonBossKeyText() {
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_STONES)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_STONES_HINT].GetHintMessage();
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex());
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_STONE_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_MEDALLIONS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_MEDALLIONS_HINT].GetHintMessage();
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex());
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_REWARDS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_REWARDS_HINT].GetHintMessage();
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex());
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_REWARD_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_DUNGEONS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_DUNGEONS_HINT].GetHintMessage();
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex());
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_LACS_TOKENS)) {
ganonBossKeyMessage = StaticData::hintTextTable[RHT_LACS_TOKENS_HINT].GetHintMessage();
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex());
ganonBossKeyMessage.InsertNumber(ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
}
else if (ctx->GetOption(RSK_GANONS_BOSS_KEY).Is(RO_GANON_BOSS_KEY_TRIFORCE_HUNT)) {
return StaticData::hintTextTable[RHT_GANON_BK_TRIFORCE_HINT].GetHintMessage();

View File

@ -70,7 +70,7 @@ extern void EnMk_Wait(EnMk* enMk, PlayState* play);
extern void func_80ABA778(EnNiwLady* enNiwLady, PlayState* play);
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
bool LocMatchesQuest(Rando::Location loc) {
if (loc.GetQuest() == RCQUEST_BOTH) {
@ -648,7 +648,7 @@ void RandomizerOnDialogMessageHandler() {
MessageContext *msgCtx = &gPlayState->msgCtx;
Actor *actor = msgCtx->talkActor;
auto ctx = Rando::Context::GetInstance();
bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF;
bool revealMerchant = ctx->GetOption(RSK_MERCHANT_TEXT_HINT).Get() != RO_GENERIC_OFF;
bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) ||
ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL);
@ -717,7 +717,7 @@ void RandomizerOnDialogMessageHandler() {
}
break;
case TEXT_SCRUB_RANDOM:
if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).GetContextOptionIndex() != RO_GENERIC_OFF) {
if (ctx->GetOption(RSK_SCRUB_TEXT_HINT).Get() != RO_GENERIC_OFF) {
EnDns* enDns = (EnDns*)actor;
reveal = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)enDns->sohScrubIdentity.randomizerInf);
}

View File

@ -383,7 +383,7 @@ bool Item::IsBottleItem() const {
bool Item::IsMajorItem() const {
const auto ctx = Context::GetInstance();
if (type == ITEMTYPE_TOKEN) {
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS;
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) || ctx->LACSCondition() == RO_LACS_TOKENS;
}
if (type == ITEMTYPE_DROP || type == ITEMTYPE_EVENT || type == ITEMTYPE_SHOP || type == ITEMTYPE_MAP ||

View File

@ -178,34 +178,15 @@ void ItemLocation::SetHidden(const bool hidden_) {
}
bool ItemLocation::IsExcluded() {
return excludedOption.GetContextOptionIndex();
return excludedOption.Is(RO_LOCATION_EXCLUDE);
}
Option* ItemLocation::GetExcludedOption() {
return &excludedOption;
OptionValue& ItemLocation::GetExcludedOption() {
return excludedOption;
}
void ItemLocation::AddExcludeOption() {
if (const std::string name = StaticData::GetLocation(rc)->GetName(); name.length() < 23) {
excludedOption = Option::Bool(name, {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
} else {
const size_t lastSpace = name.rfind(' ', 23);
std::string settingText = name;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = Option::Bool(settingText, {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
}
// RANDOTODO: this without string compares and loops
bool alreadyAdded = false;
const Location* loc = StaticData::GetLocation(rc);
for (Option* location : Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea())) {
if (location->GetName() == excludedOption.GetName()) {
alreadyAdded = true;
}
}
if (!alreadyAdded) {
Context::GetInstance()->GetSettings()->GetExcludeOptionsForArea(loc->GetArea()).push_back(&excludedOption);
}
void ItemLocation::SetExcludedOption(uint8_t val) {
excludedOption.Set(val);
}
bool ItemLocation::IsVisible() const {

View File

@ -3,7 +3,7 @@
#include "randomizerTypes.h"
#include "3drando/text.hpp"
#include "static_data.h"
#include "settings.h"
#include "option.h"
namespace Rando {
class ItemLocation {
@ -46,8 +46,8 @@ class ItemLocation {
void AddHintedBy(RandomizerHint hintKey);
bool IsHidden() const;
bool IsExcluded();
void AddExcludeOption();
Option* GetExcludedOption();
OptionValue& GetExcludedOption();
void SetExcludedOption(uint8_t val);
void SetHidden(bool hidden_);
bool IsVisible() const;
void SetVisible(bool visibleInImGui_);
@ -65,7 +65,7 @@ class ItemLocation {
bool addedToPool = false;
RandomizerGet placedItem = RG_NONE;
RandomizerGet delayedItem = RG_NONE;
Option excludedOption = Option::Bool(StaticData::GetLocation(rc)->GetName(), {"Include", "Exclude"}, OptionCategory::Setting, "", "", WidgetType::Checkbox, RO_LOCATION_INCLUDE);
OptionValue excludedOption = OptionValue(RO_LOCATION_INCLUDE);
uint16_t price = 0;
RandomizerRegion parentRegion = RR_NONE;
std::set<RandomizerArea> areas = {};

View File

@ -2,6 +2,7 @@
#include "static_data.h"
#include <algorithm>
#include <assert.h>
#include "option.h"
RandomizerCheck Rando::Location::GetRandomizerCheck() const {
return rc;
@ -86,6 +87,10 @@ int16_t Rando::Location::GetVanillaPrice() const {
return vanillaPrice;
}
Rando::Option* Rando::Location::GetExcludedOption() {
return &excludedOption;
}
RandomizerCheckArea GetAreaFromScene(uint8_t scene) {
switch (scene) {
case SCENE_LINKS_HOUSE:

View File

@ -10,6 +10,7 @@
#include "z64actor_enum.h"
#include "z64scene.h"
#include "../../util.h"
#include "option.h"
namespace Rando {
class SpoilerCollectionCheck {
@ -59,7 +60,17 @@ class Location {
: rc(rc_), quest(quest_), checkType(checkType_), area(area_), actorId(actorId_),
scene(scene_), actorParams(actorParams_), shortName(std::move(shortName_)),
spoilerName(std::move(spoilerName_)), hintKey(hintKey_), vanillaItem(vanillaItem_),
isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {}
isVanillaCompletion(isVanillaCompletion_), collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {
if (spoilerName.length() < 23) {
excludedOption = LocationOption(rc, spoilerName);
} else {
const size_t lastSpace = spoilerName.rfind(' ', 23);
std::string settingText = spoilerName;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = LocationOption(rc, spoilerName);
}
}
Location(const RandomizerCheck rc_, const RandomizerCheckQuest quest_, const RandomizerCheckType checkType_, const RandomizerCheckArea area_, const ActorID actorId_,
const SceneID scene_, const int32_t actorParams_, std::string shortName_, const RandomizerHintTextKey hintKey_, const RandomizerGet vanillaItem_,
@ -67,7 +78,17 @@ class Location {
const int vanillaPrice_ = 0)
: rc(rc_), quest(quest_), checkType(checkType_), area(area_), actorId(actorId_), scene(scene_), actorParams(actorParams_), shortName(shortName_),
spoilerName(SpoilerNameFromShortName(shortName_, area_)), hintKey(hintKey_), vanillaItem(vanillaItem_), isVanillaCompletion(isVanillaCompletion_),
collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {}
collectionCheck(collectionCheck_), vanillaPrice(vanillaPrice_) {
if (spoilerName.length() < 23) {
excludedOption = LocationOption(rc, spoilerName);
} else {
const size_t lastSpace = spoilerName.rfind(' ', 23);
std::string settingText = spoilerName;
settingText.replace(lastSpace, 1, "\n ");
excludedOption = LocationOption(rc, spoilerName);
}
}
static std::string SpoilerNameFromShortName(std::string shortName, RandomizerCheckArea area) {
if (area < 0 || area >= RCAREA_INVALID) {
@ -96,10 +117,13 @@ class Location {
const HintText& GetHint() const;
RandomizerGet GetVanillaItem() const;
int16_t GetVanillaPrice() const;
Option* GetExcludedOption();
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, ActorID actorId_, SceneID scene_, int32_t actorParams_,
std::string&& shortName_, std::string&& spoilerName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(), bool isVanillaCompletion_ = false, uint16_t vanillaPrice_ = 0);
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_,
ActorID actorId_, SceneID scene_, int32_t actorParams_, std::string&& shortName_,
std::string&& spoilerName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem,
SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
bool isVanillaCompletion_ = false, uint16_t vanillaPrice_ = 0);
static Location Base(RandomizerCheck rc, RandomizerCheckQuest quest_, RandomizerCheckType checkType_, ActorID actorId_, SceneID scene_, int32_t actorParams_,
std::string&& shortName_, RandomizerHintTextKey hintKey, RandomizerGet vanillaItem, SpoilerCollectionCheck collectionCheck = SpoilerCollectionCheck(),
@ -210,5 +234,6 @@ class Location {
SpoilerCollectionCheck collectionCheck;
int16_t vanillaPrice;
bool isHintable = false;
Option excludedOption;
};
} // namespace Rando

View File

@ -267,7 +267,7 @@ void RegionTable_Init() {
}, {
//Locations
LOCATION(RC_LINKS_POCKET, true),
LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).GetContextOptionIndex() + 1;),
LOCATION(RC_TRIFORCE_COMPLETED, logic->GetSaveContext()->ship.quest.data.randomizer.triforcePiecesCollected >= ctx->GetOption(RSK_TRIFORCE_HUNT_PIECES_REQUIRED).Get() + 1;),
LOCATION(RC_SARIA_SONG_HINT, logic->CanUse(RG_SARIAS_SONG)),
}, {
//Exits
@ -409,7 +409,7 @@ void ReplaceAllInString(std::string& s, std::string const& toReplace, std::strin
std::string CleanCheckConditionString(std::string condition) {
ReplaceAllInString(condition, "logic->", "");
ReplaceAllInString(condition, "ctx->", "");
ReplaceAllInString(condition, ".GetContextOptionIndex()", "");
ReplaceAllInString(condition, ".Get()", "");
ReplaceAllInString(condition, "GetSaveContext()->", "");
return condition;
}

View File

@ -75,8 +75,9 @@ void RegionTable_Init_Graveyard() {
areaTable[RR_GRAVEYARD_COMPOSERS_GRAVE] = Region("Graveyard Composers Grave", "Graveyard Composers Grave", {}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource()),
LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile() || logic->CanJumpslash()),
LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_CHEST, logic->HasFireSource()),
LOCATION(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, logic->CanUseProjectile() || logic->CanJumpslash()),
LOCATION(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, {
//Exits
Entrance(RR_THE_GRAVEYARD, []{return true;}),

View File

@ -48,7 +48,7 @@ void RegionTable_Init_Kakariko() {
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 && logic->CanOpenOverworldDoor(RG_KAK_POTION_SHOP_KEY);}),
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());}),

View File

@ -118,9 +118,10 @@ void RegionTable_Init_LostWoods() {
areaTable[RR_LW_SCRUBS_GROTTO] = Region("LW Scrubs Grotto", "LW Scrubs Grotto", {}, NO_DAY_NIGHT_CYCLE, {}, {
//Locations
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_REAR, logic->CanStunDeku()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_FRONT, logic->CanStunDeku()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_BEEHIVE, logic->CanBreakUpperBeehives()),
LOCATION(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, logic->CanUse(RG_SUNS_SONG)),
}, {
//Exits
Entrance(RR_LW_BEYOND_MIDO, []{return true;}),

View File

@ -2170,6 +2170,8 @@ void Rando::StaticData::InitLocationTable() { //
locationTable[RC_DMT_COW_GROTTO_STORMS_FAIRY] = Location::Fairy(RC_DMT_COW_GROTTO_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_DEATH_MOUNTAIN_TRAIL, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, -311), "Cow Grotto Song of Storms Fairy", "Cow Grotto Song of Storms Fairy", RHT_DMT_COW_GROTTO_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_DMT_COW_GROTTO_STORMS_FAIRY));
locationTable[RC_LW_SHORTCUT_STORMS_FAIRY] = Location::Fairy(RC_LW_SHORTCUT_STORMS_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_LOST_WOODS, TWO_ACTOR_PARAMS(0x1000, -795), "Shortcuts Song of Storms Fairy", "Shortcuts Song of Storms Fairy", RHT_LW_SHORTCUT_STORMS_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_SHORTCUT_STORMS_FAIRY));
locationTable[RC_GF_KITCHEN_SUN_FAIRY] = Location::Fairy(RC_GF_KITCHEN_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GERUDO_FORTRESS, SCENE_THIEVES_HIDEOUT, TWO_ACTOR_PARAMS(0x1000, -621), "Kitchen Sun's Song Fairy", "Kitchen Sun's Song Fairy", RHT_GF_KITCHEN_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GF_KITCHEN_SUN_FAIRY));
locationTable[RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY] = Location::Fairy(RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, RCQUEST_BOTH, RCAREA_LOST_WOODS, SCENE_GROTTOS, TWO_ACTOR_PARAMS(0x1000, 741), "Scrub Grotto Sun's Song Fairy", "Scrub Grotto Sun's Song Fairy", RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY));
locationTable[RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY] = Location::Fairy(RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, RCQUEST_BOTH, RCAREA_GRAVEYARD, SCENE_ROYAL_FAMILYS_TOMB, TWO_ACTOR_PARAMS(0x1000, 1476), "Composer's Grave Sun's Song Fairy", "Composer's Grave Sun's Song Fairy", RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY));
locationTable[RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY] = Location::Fairy(RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -1896), "After Boulder Room Sun's Song Fairy", "After Boulder Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY));
locationTable[RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY] = Location::Fairy(RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, RCQUEST_VANILLA,RCAREA_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE, TWO_ACTOR_PARAMS(0x1000, -220), "Four Armos Room Sun's Song Fairy", "Four Armos Room Sun's Song Fairy", RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY, SpoilerCollectionCheck::RandomizerInf(RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY));

View File

@ -1075,7 +1075,7 @@ namespace Rando {
10 for OHKO.
This is the number of shifts to apply, not a real multiplier
*/
uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).GetContextOptionIndex() : 10;
uint8_t Multiplier = (ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Get() < 6) ? ctx->GetOption(RSK_DAMAGE_MULTIPLIER).Get() : 10;
//(Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) is quarter hearts after DD
//>> Multiplier halves on normal and does nothing on half, meaning we're working with half hearts on normal damage
return ((Hearts() << (2 + HasItem(RG_DOUBLE_DEFENSE))) >> Multiplier) +
@ -1205,21 +1205,21 @@ namespace Rando {
bool Logic::CanBuildRainbowBridge(){
return ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_ALWAYS_OPEN) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_VANILLA) && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION) && CanUse(RG_LIGHT_ARROWS)) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).GetContextOptionIndex()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_STONES) && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_STONE_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_MEDALLIONS) && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_MEDALLION_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEON_REWARDS) && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_REWARD_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_DUNGEONS) && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_BRIDGE_OPTIONS).Is(RO_BRIDGE_GREG_REWARD)) >= ctx->GetOption(RSK_RAINBOW_BRIDGE_DUNGEON_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_TOKENS) && GetGSCount() >= ctx->GetOption(RSK_RAINBOW_BRIDGE_TOKEN_COUNT).Get()) ||
(ctx->GetOption(RSK_RAINBOW_BRIDGE).Is(RO_BRIDGE_GREG) && HasItem(RG_GREG_RUPEE));
}
bool Logic::CanTriggerLACS(){
return (ctx->GetSettings()->LACSCondition() == RO_LACS_VANILLA && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION)) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).GetContextOptionIndex()) ||
(ctx->GetSettings()->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).GetContextOptionIndex());
return (ctx->LACSCondition() == RO_LACS_VANILLA && HasItem(RG_SHADOW_MEDALLION) && HasItem(RG_SPIRIT_MEDALLION)) ||
(ctx->LACSCondition() == RO_LACS_STONES && StoneCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_STONE_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_MEDALLIONS && MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_MEDALLION_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_REWARDS && StoneCount() + MedallionCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_REWARD_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_DUNGEONS && DungeonCount() + (HasItem(RG_GREG_RUPEE) && ctx->GetOption(RSK_LACS_OPTIONS).Is(RO_LACS_GREG_REWARD)) >= ctx->GetOption(RSK_LACS_DUNGEON_COUNT).Get()) ||
(ctx->LACSCondition() == RO_LACS_TOKENS && GetGSCount() >= ctx->GetOption(RSK_LACS_TOKEN_COUNT).Get());
}
bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmount) {
@ -1431,6 +1431,18 @@ namespace Rando {
{ RG_GERUDO_MEMBERSHIP_CARD, QUEST_GERUDO_CARD },
};
std::map<uint32_t, uint32_t> BottleRandomizerGetToItemID = {
{ RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED },
{ RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN },
{ RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE },
{ RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY },
{ RG_BOTTLE_WITH_FISH, ITEM_FISH },
{ RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE },
{ RG_BOTTLE_WITH_BUGS, ITEM_BUG },
{ RG_BOTTLE_WITH_POE, ITEM_POE },
{ RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE },
};
uint32_t HookshotLookup[3] = { ITEM_NONE, ITEM_HOOKSHOT, ITEM_LONGSHOT };
uint32_t OcarinaLookup[3] = { ITEM_NONE, ITEM_OCARINA_FAIRY, ITEM_OCARINA_TIME };
@ -1675,7 +1687,11 @@ namespace Rando {
}
slot++;
}
mSaveContext->inventory.items[slot] = item.GetGIEntry()->itemId;
uint16_t itemId = item.GetGIEntry()->itemId;
if (BottleRandomizerGetToItemID.contains(randoGet)) {
itemId = BottleRandomizerGetToItemID[randoGet];
}
mSaveContext->inventory.items[slot] = itemId;
} break;
case RG_RUTOS_LETTER:
SetEventChkInf(EVENTCHKINF_OBTAINED_RUTOS_LETTER, state);
@ -2201,7 +2217,7 @@ namespace Rando {
//Bottle Count
Bottles = 0;
NumBottles = 0;
CanEmptyBigPoes = true;
CanEmptyBigPoes = false;
//Drops and Bottle Contents Access
NutPot = false;
@ -2238,7 +2254,7 @@ namespace Rando {
//CanPlantBean = false;
BigPoeKill = false;
BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).GetContextOptionIndex() + 1;
BaseHearts = ctx->GetOption(RSK_STARTING_HEARTS).Get() + 1;
//Bridge Requirements
@ -2247,7 +2263,7 @@ namespace Rando {
//Other
AtDay = false;
AtNight = false;
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get();
//Events
ShowedMidoSwordAndShield = false;

View File

@ -5,39 +5,53 @@
#include "soh/UIWidgets.hpp"
namespace Rando {
Option Option::Bool(std::string name_, std::vector<std::string> options_, const OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
const bool defaultHidden_, int imFlags_) {
return {false, std::move(name_), std::move(options_), category_, std::move(cvarName_), std::move(description_),
widgetType_, defaultOption_, defaultHidden_, imFlags_};
Option Option::Bool(RandomizerSettingKey key_, std::string name_, std::vector<std::string> options_,
const OptionCategory category_, std::string cvarName_, std::string description_,
WidgetType widgetType_, const uint8_t defaultOption_, const bool defaultHidden_, int imFlags_) {
return {static_cast<size_t>(key_), std::move(name_), std::move(options_), category_,
std::move(cvarName_), std::move(description_), widgetType_, defaultOption_, defaultHidden_, imFlags_};
}
Option Option::Bool(std::string name_, std::string cvarName_, std::string description_, const int imFlags_,
const WidgetType widgetType_, const bool defaultOption_) {
return Option(false, std::move(name_), {"Off", "On"}, OptionCategory::Setting, std::move(cvarName_),
Option Option::Bool(RandomizerSettingKey key_, std::string name_, std::string cvarName_, std::string description_,
const int imFlags_, const WidgetType widgetType_, const bool defaultOption_) {
return Option(key_, std::move(name_), {"Off", "On"}, OptionCategory::Setting, std::move(cvarName_),
std::move(description_), widgetType_, defaultOption_, false, imFlags_);
}
Option Option::U8(std::string name_, std::vector<std::string> options_, const OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
const bool defaultHidden_, int imFlags_) {
return {static_cast<uint8_t>(0), std::move(name_), std::move(options_), category_, std::move(cvarName_),
Option Option::U8(RandomizerSettingKey key_, std::string name_, std::vector<std::string> options_,
const OptionCategory category_, std::string cvarName_, std::string description_,
WidgetType widgetType_, const uint8_t defaultOption_, const bool defaultHidden_, int imFlags_) {
return {static_cast<size_t>(key_), std::move(name_), std::move(options_), category_, std::move(cvarName_),
std::move(description_), widgetType_, defaultOption_, defaultHidden_, imFlags_};
}
Option Option::LogicTrick(std::string name_) {
return Option(false, std::move(name_), { "Disabled", "Enabled" }, OptionCategory::Setting, "",
Option Option::LogicTrick(RandomizerTrick rt_, std::string name_) {
return Option(rt_, std::move(name_), { "Disabled", "Enabled" }, OptionCategory::Setting, "",
"", WidgetType::Checkbox, 0, false, IMFLAG_NONE);
}
Option::operator bool() const {
return contextSelection != 0;
OptionValue::OptionValue(uint8_t val) : mVal(val) {}
uint8_t OptionValue::Get() {
return mVal;
}
void OptionValue::Set(uint8_t val) {
mVal = val;
}
OptionValue::operator bool() const {
return mVal != 0;
}
size_t Option::GetOptionCount() const {
return options.size();
}
const RandomizerSettingKey Option::GetKey() const {
return static_cast<RandomizerSettingKey>(key);
}
const std::string& Option::GetName() const {
return name;
}
@ -50,26 +64,14 @@ uint8_t Option::GetMenuOptionIndex() const {
return menuSelection;
}
uint8_t Option::GetContextOptionIndex() const {
return contextSelection;
}
const std::string& Option::GetSelectedOptionText() const {
return options[contextSelection];
const std::string& Option::GetOptionText(size_t index) const {
return options[index];
}
const std::string& Option::GetCVarName() const {
return cvarName;
}
void Option::SetVariable() {
if (std::holds_alternative<bool>(var)) {
var.emplace<bool>(menuSelection != 0);
} else {
var.emplace<uint8_t>(menuSelection);
}
}
void Option::SaveCVar() const {
if (!cvarName.empty()) {
CVarSetInteger(cvarName.c_str(), GetMenuOptionIndex());
@ -95,10 +97,10 @@ void Option::SetMenuIndex(size_t idx) {
if (menuSelection > options.size() - 1) {
menuSelection = options.size() - 1;
}
SetVariable();
}
void Option::SetContextIndex(size_t idx) {
// TODO: Set to Context's OptionValue array.
contextSelection = idx;
if (contextSelection > options.size() - 1) {
contextSelection = options.size() - 1;
@ -178,6 +180,16 @@ void Option::RemoveFlag(const int imFlag_) {
imFlags &= ~imFlag_;
}
uint8_t Option::GetValueFromText(const std::string text) {
if (optionsTextToVar.contains(text)) {
return optionsTextToVar[text];
} else {
SPDLOG_ERROR("Option {} does not have a var named {}.", name, text);
assert(false);
}
return defaultOption;
}
void Option::SetContextIndexFromText(const std::string text) {
if (optionsTextToVar.contains(text)){
SetContextIndex(optionsTextToVar[text]);
@ -187,21 +199,10 @@ void Option::SetContextIndexFromText(const std::string text) {
}
}
Option::Option(uint8_t var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
Option::Option(size_t key_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_)
: var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_),
defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) {
menuSelection = contextSelection = defaultOption;
hidden = defaultHidden;
PopulateTextToNum();
SetFromCVar();
}
Option::Option(bool var_, std::string name_, std::vector<std::string> options_, const OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, const uint8_t defaultOption_,
const bool defaultHidden_, int imFlags_)
: var(var_), name(std::move(name_)), options(std::move(options_)), category(category_),
: key(key_), name(std::move(name_)), options(std::move(options_)), category(category_),
cvarName(std::move(cvarName_)), description(std::move(description_)), widgetType(widgetType_),
defaultOption(defaultOption_), defaultHidden(defaultHidden_), imFlags(imFlags_) {
menuSelection = contextSelection = defaultOption;
@ -350,13 +351,25 @@ void Option::PopulateTextToNum(){
}
}
TrickOption::TrickOption(const RandomizerCheckQuest quest_, const RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) :
Option(false, name_, {"Disabled", "Enabled"}, OptionCategory::Setting, "",
LocationOption::LocationOption(RandomizerCheck key_, const std::string& name_) :
Option(key_, name_, {"Included", "Excluded"}, OptionCategory::Setting, "", "", WidgetType::Checkbox,
RO_LOCATION_INCLUDE, false, IMFLAG_NONE) {}
const RandomizerCheck LocationOption::GetKey() const {
return static_cast<RandomizerCheck>(key);
}
TrickOption::TrickOption(RandomizerTrick key_, const RandomizerCheckQuest quest_, const RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) :
Option(key_, name_, {"Disabled", "Enabled"}, OptionCategory::Setting, "",
std::move(description_), WidgetType::Checkbox, 0, false, IMFLAG_NONE),
mQuest(quest_), mArea(area_), mTags(std::move(tags_)) {}
TrickOption TrickOption::LogicTrick(RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) {
return {quest_, area_, std::move(tags_), name_, std::move(description_)};
TrickOption TrickOption::LogicTrick(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_) {
return {key_, quest_, area_, std::move(tags_), name_, std::move(description_)};
}
const RandomizerTrick TrickOption::GetKey() const {
return static_cast<RandomizerTrick>(key);
}
RandomizerCheckQuest TrickOption::GetQuest() const {

View File

@ -40,6 +40,59 @@ enum class WidgetType {
Slider, /** Compatible with U8s. If constructed with NumOpts, consider using this. Technically can be used for Bool or non-NumOpts options but it would be a bit weird semantically. */
};
class OptionValue {
public:
OptionValue() = default;
OptionValue(uint8_t value_);
/**
* @brief Returns the value of the OptionValue's mVal
*
* @return uint8_t
*/
uint8_t Get();
/**
* @brief Set the OptionValue's mVal to the provided val.
*
* @param val
*/
void Set(uint8_t val);
/**
* @brief Determines if the value/selected index of this Option matches the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool Is(uint32_t other) const {
return mVal == other;
}
/**
* @brief Determines if the value/selected index of this Option does not match the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool IsNot(uint32_t other) const {
return !Is(other);
}
/**
* @brief Allows the option to be used as a boolean value directly.
*
* @return true
* @return false
*/
explicit operator bool() const;
private:
uint8_t mVal;
};
/**
* @brief A class describing the state of a single option/setting, such as its name,
* options, current value, whether or not it is interactable in the menu, or the CVar,
@ -68,7 +121,8 @@ class Option {
* @param imFlags_ (see ImGuiMenuFlags type) flags that can modify how this option is rendered.
* @return Option
*/
static Option Bool(std::string name_, std::vector<std::string> options_ = { "Off", "On" },
static Option Bool(RandomizerSettingKey key_, std::string name_,
std::vector<std::string> options_ = { "Off", "On" },
OptionCategory category_ = OptionCategory::Setting, std::string cvarName_ = "",
std::string description_ = "", WidgetType widgetType_ = WidgetType::Checkbox,
uint8_t defaultOption_ = 0, bool defaultHidden_ = false, int imFlags_ = IMFLAG_SEPARATOR_BOTTOM);
@ -79,6 +133,7 @@ class Option {
* existing calls to the other overload of this function. The options vector will be { "Off", "On" }
* when using this overload. If you want your option to have different value names, use the other overload.
*
* @param key_ The RandomizerSettingKey of this option.
* @param name_ The name of the option. Appears in the spoiler/patch file.
* @param cvarName_ The name of the CVar this option should correspond with. Set as an empty string to not
* link to any CVar.
@ -90,13 +145,14 @@ class Option {
* @param defaultOption_ The defaulted selected index for this Option.
* @return Option
*/
static Option Bool(std::string name_, std::string cvarName_, std::string description_ = "",
int imFlags_ = IMFLAG_SEPARATOR_BOTTOM, WidgetType widgetType_ = WidgetType::Checkbox,
bool defaultOption_ = false);
static Option Bool(RandomizerSettingKey key_, std::string name_, std::string cvarName_,
std::string description_ = "", int imFlags_ = IMFLAG_SEPARATOR_BOTTOM,
WidgetType widgetType_ = WidgetType::Checkbox, bool defaultOption_ = false);
/**
* @brief Constructs a U8 Option.
*
* @param key_ The RandomizerSettingKey for this option.
* @param name_ The name of this Option. Appears in the spoiler/patch file.
* @param options_ A vector of value names for this Option. The name corresponding to the selected
* index for this option will be printed to the spoiler/patch file.
@ -114,7 +170,7 @@ class Option {
* @param imFlags_ (see ImGuiMenuFlags type) flags that can modify how this option is rendered.
* @return Option
*/
static Option U8(std::string name_, std::vector<std::string> options_,
static Option U8(RandomizerSettingKey key_, std::string name_, std::vector<std::string> options_,
OptionCategory category_ = OptionCategory::Setting, std::string cvarName_ = "",
std::string description_ = "", WidgetType widgetType_ = WidgetType::Combobox,
uint8_t defaultOption_ = 0, bool defaultHidden_ = false, int imFlags_ = IMFLAG_SEPARATOR_BOTTOM);
@ -125,37 +181,7 @@ class Option {
* @param name_ The name of the trick. Appears in the spoiler/patch file.
* @return Option
*/
static Option LogicTrick(std::string name_);
/**
* @brief Determines if the value/selected index of this Option matches the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool Is(uint32_t other) const {
return contextSelection == other;
}
/**
* @brief Determines if the value/selected index of this Option does not match the provided value.
*
* @param other The value to compare.
* @return true
* @return false
*/
bool IsNot(uint32_t other) const {
return !Is(other);
}
/**
* @brief Allows the option to be used as a boolean value directly.
*
* @return true
* @return false
*/
explicit operator bool() const;
static Option LogicTrick(RandomizerTrick rt_, std::string name_);
/**
* @brief Get the size of the options array.
@ -164,6 +190,13 @@ class Option {
*/
size_t GetOptionCount() const;
/**
* @brief Get the Key Option
*
* @return const RandomizerSettingKey
*/
const RandomizerSettingKey GetKey() const;
/**
* @brief Get the name of the Option.
*
@ -173,11 +206,12 @@ class Option {
const std::string& GetDescription() const;
/**
* @brief Get the value name corresponding to the selected index.
*
* @return const std::string&
* @brief Get the text of the Option value of the selected index.
*
* @param index
* @return const std::string&
*/
const std::string& GetSelectedOptionText() const;
const std::string& GetOptionText(size_t index) const;
/**
* @brief Get the CVar name for this Option.
@ -193,18 +227,6 @@ class Option {
*/
uint8_t GetMenuOptionIndex() const;
/**
* @brief Get the rando context index for this Option.
*
* @return uint8_t
*/
uint8_t GetContextOptionIndex() const;
/**
* @brief Sets the variable to the currently selected index for this Option.
*/
void SetVariable();
/**
* @brief Sets the CVar corresponding to the property `cvarName` equal to the value
* of the property `selectedValue`.
@ -306,15 +328,14 @@ class Option {
void SetFlag(int imFlag_);
void RemoveFlag(int imFlag_);
uint8_t GetValueFromText(std::string text);
void SetContextIndexFromText(std::string text);
protected:
Option(uint8_t var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_);
Option(bool var_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
Option(size_t key_, std::string name_, std::vector<std::string> options_, OptionCategory category_,
std::string cvarName_, std::string description_, WidgetType widgetType_, uint8_t defaultOption_,
bool defaultHidden_, int imFlags_);
size_t key;
private:
bool RenderCheckbox();
@ -322,7 +343,6 @@ protected:
bool RenderCombobox();
bool RenderSlider();
void PopulateTextToNum();
std::variant<bool, uint8_t> var;
std::string name;
std::vector<std::string> options;
uint8_t menuSelection = 0;
@ -342,12 +362,20 @@ protected:
std::unordered_map<std::string, uint8_t> optionsTextToVar = {};
};
class LocationOption : public Option {
public:
LocationOption() = default;
LocationOption(RandomizerCheck key_, const std::string& name_);
const RandomizerCheck GetKey() const;
};
class TrickOption : public Option {
public:
TrickOption() = default;
/**
* @brief A convenience function for constructing the Option for a trick.
*
* @param key_ A RandomizerTrick key for this option.
* @param quest_ MQ, Vanilla, or Both.
* @param area_ The area the trick is relevant for.
* @param tags_ The set of RandomizerTrickTags for this trick.
@ -355,7 +383,9 @@ public:
* @param description_ A brief description of the trick.
* @return Option
*/
static TrickOption LogicTrick(RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
static TrickOption LogicTrick(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
const RandomizerTrick GetKey() const;
/**
* @brief Retrieve the quest type this trick is relevant for.
@ -382,7 +412,7 @@ public:
const std::set<Tricks::Tag>& GetTags() const;
private:
TrickOption(RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
TrickOption(RandomizerTrick key_, RandomizerCheckQuest quest_, RandomizerArea area_, std::set<Tricks::Tag> tags_, const std::string& name_, std::string description_);
RandomizerCheckQuest mQuest;
RandomizerArea mArea;
std::set<Tricks::Tag> mTags;

View File

@ -475,7 +475,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
(CUR_UPG_VALUE(UPG_STICKS) < 3 ? CAN_OBTAIN : CANT_OBTAIN_ALREADY_HAVE);
case RG_DEKU_STICK_1:
case RG_BUY_DEKU_STICK_1:
return CUR_UPG_VALUE(UPG_STICKS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).GetContextOptionIndex()
return CUR_UPG_VALUE(UPG_STICKS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_STICK_BAG).Get()
? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE;
case RG_PROGRESSIVE_NUT_UPGRADE:
return infiniteUpgrades != RO_INF_UPGRADES_OFF ?
@ -485,7 +485,7 @@ ItemObtainability Randomizer::GetItemObtainabilityFromRandomizerGet(RandomizerGe
case RG_DEKU_NUTS_10:
case RG_BUY_DEKU_NUTS_5:
case RG_BUY_DEKU_NUTS_10:
return CUR_UPG_VALUE(UPG_NUTS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).GetContextOptionIndex()
return CUR_UPG_VALUE(UPG_NUTS) || !OTRGlobals::Instance->gRandoContext->GetOption(RSK_SHUFFLE_DEKU_NUT_BAG).Get()
? CAN_OBTAIN : CANT_OBTAIN_NEED_UPGRADE;
case RG_PROGRESSIVE_BOMB_BAG:
return infiniteUpgrades != RO_INF_UPGRADES_OFF ?
@ -2249,7 +2249,7 @@ GrassIdentity Randomizer::IdentifyGrass(s32 sceneNum, s32 posX, s32 posZ, s32 re
}
u8 Randomizer::GetRandoSettingValue(RandomizerSettingKey randoSettingKey) {
return Rando::Context::GetInstance()->GetOption(randoSettingKey).GetContextOptionIndex();
return Rando::Context::GetInstance()->GetOption(randoSettingKey).Get();
}
GetItemEntry Randomizer::GetItemFromKnownCheck(RandomizerCheck randomizerCheck, GetItemID ogItemId, bool checkObtainability) {
@ -2283,7 +2283,8 @@ void GenerateRandomizerImgui(std::string seed = "") {
CVarSave();
auto ctx = Rando::Context::GetInstance();
//RANDOTODO proper UI for selecting if a spoiler loaded should be used for settings
ctx->GetSettings()->SetAllFromCVar();
Rando::Settings::GetInstance()->SetAllFromCVar();
Rando::Settings::GetInstance()->SetAllToContext();
// todo: this efficently when we build out cvar array support
std::set<RandomizerCheck> excludedLocations;
@ -4199,10 +4200,10 @@ class ExtendedVanillaTableInvalidItemIdException: public std::exception {
};
void RandomizerSettingsWindow::InitElement() {
mSettings = Rando::Context::GetInstance()->GetSettings();
mSettings = Rando::Settings::GetInstance();
Randomizer::CreateCustomMessages();
seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char));
Rando::Context::GetInstance()->GetSettings()->UpdateOptionProperties();
mSettings->UpdateOptionProperties();
}
// Gameplay stat tracking: Update time the item was acquired

View File

@ -2827,6 +2827,8 @@ typedef enum {
RC_DMT_COW_GROTTO_STORMS_FAIRY,
RC_LW_SHORTCUT_STORMS_FAIRY,
RC_GF_KITCHEN_SUN_FAIRY,
RC_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY,
RC_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY,
RC_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY,
RC_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY,
RC_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY,
@ -5261,6 +5263,8 @@ typedef enum {
RHT_DMT_COW_GROTTO_STORMS_FAIRY,
RHT_LW_SHORTCUT_STORMS_FAIRY,
RHT_GF_KITCHEN_SUN_FAIRY,
RHT_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY,
RHT_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY,
RHT_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY,
RHT_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY,
RHT_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY,

View File

@ -492,7 +492,7 @@ void CheckTrackerLoadGame(int32_t fileNum) {
}
}
if (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_LINKS_POCKET) != RO_LINKS_POCKET_NOTHING && IS_RANDO) {
uint8_t startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
uint8_t startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();
RandomizerCheckArea startingArea;
switch (startingAge) {
case RO_AGE_CHILD:

View File

@ -94,7 +94,7 @@ const EntranceData entranceData[] = {
{ ENTR_SARIAS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Saria's House Entry", "Saria's House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_TWINS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF House of Twins Entry", "House of Twins", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_KNOW_IT_ALL_BROS_HOUSE_0, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Know-It-All House Entry", "Know-It-All House", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_KOKIRI_SHOP_0, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Shop Entry", "KF Shop", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_KOKIRI_SHOP_0, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Shop Entry", "Kokiri Shop", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Storms Grotto Entry", "KF Storms Grotto", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTR_DEKU_TREE_ENTRANCE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, SINGLE_SCENE_INFO(SCENE_KOKIRI_FOREST), "KF Outside Deku Tree", "Deku Tree Entrance", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE, ENTR_LINKS_HOUSE_1, SINGLE_SCENE_INFO(SCENE_LINKS_HOUSE), "Link's House", "KF Link's House Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
@ -102,40 +102,40 @@ const EntranceData entranceData[] = {
{ ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_SARIAS_HOUSE), "Saria's House", "KF Saria's House Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE, ENTR_TWINS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_TWINS_HOUSE), "House of Twins", "KF House of Twins Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0, SINGLE_SCENE_INFO(SCENE_KNOW_IT_ALL_BROS_HOUSE), "Know-It-All House", "KF Know-It-All House Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, ENTR_KOKIRI_SHOP_0, SINGLE_SCENE_INFO(SCENE_KOKIRI_SHOP), "KF Shop", "KF Shop Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ ENTR_KOKIRI_FOREST_OUTSIDE_SHOP, ENTR_KOKIRI_SHOP_0, SINGLE_SCENE_INFO(SCENE_KOKIRI_SHOP), "Kokiri Shop", "KF Shop Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_INTERIOR, ""},
{ ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "KF Storms Grotto", "KF Storms Grotto Entry", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, ENTR_DEKU_TREE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Entrance", "KF Outside Deku Tree", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, ""},
{ ENTR_DEKU_TREE_BOSS_ENTRANCE, ENTR_DEKU_TREE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Boss Door", "Gohma", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_DEKU_TREE_BOSS_DOOR, ENTR_DEKU_TREE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Boss Door", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Blue Warp", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
{ ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma Blue Warp", "Deku Tree Blue Warp", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Lost Woods
{ ENTR_KOKIRI_FOREST_LOWER_EXIT, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge East Exit", "Kokiri Forest Lower Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_HYRULE_FIELD_WOODED_EXIT, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge West Exit", "Hyrule Field Wooded Path", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lw,hf"},
{ ENTR_KOKIRI_FOREST_UPPER_EXIT, ENTR_LOST_WOODS_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods South Exit", "Kokiri Forest Upper Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_GORON_CITY_TUNNEL_SHORTCUT, ENTR_LOST_WOODS_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Tunnel Shortcut", "GC Tunnel Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "lw,gc"},
{ ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Underwater Shortcut", "ZR Underwater Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, ENTR_LOST_WOODS_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Exit", "SFM South Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Shortcuts Grotto Entry", "LW Tunnel Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Grotto Entry", "LW Scrubs Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Meadow Grotto Entry", "Deku Theater", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage", 1},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "LW Tunnel Grotto", "LW Shortcuts Grotto Entry",ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), {{ SCENE_GROTTOS, 0x07 }}, "LW Scrubs Grotto", "LW North Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), {{ SCENE_GROTTOS, 0x0C }}, "Deku Theater", "LW Meadow Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage"},
{ ENTR_KOKIRI_FOREST_LOWER_EXIT, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge East Exit", "Kokiri Forest Lower Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_HYRULE_FIELD_WOODED_EXIT, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge West Exit", "Hyrule Field Wooded Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lw,hf"},
{ ENTR_KOKIRI_FOREST_UPPER_EXIT, ENTR_LOST_WOODS_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods South Exit", "Kokiri Forest Upper Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_GORON_CITY_TUNNEL_SHORTCUT, ENTR_LOST_WOODS_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Tunnel Shortcut", "Goron City Tunnel Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "lw,gc"},
{ ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Underwater Shortcut", "Zora's River Underwater Shortcut", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, ENTR_LOST_WOODS_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods North Exit", "Sacred Forest Meadow South Exit", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Shortcuts Grotto Entry", "LW Tunnel Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW North Grotto Entry", "LW Scrubs Grotto", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "LW Meadow Grotto Entry", "Deku Theater", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage", 1},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "LW Tunnel Grotto", "LW Shortcuts Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,chest"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET), {{ SCENE_GROTTOS, 0x07 }}, "LW Scrubs Grotto", "LW North Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET), {{ SCENE_GROTTOS, 0x0C }}, "Deku Theater", "LW Meadow Grotto Entry", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_GROTTO, "lw,mask,stage"},
// Sacred Forest Meadow
{ ENTR_LOST_WOODS_NORTH_EXIT, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM South Exit", "LW North Exit", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Wolfos Grotto Entry", "SFM Wolfos Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Fairy Grotto Entry", "SFM Fairy Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Storms Grotto Entry", "SFM Storms Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Outside Forest Temple", "Forest Temple Entrance", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), {{ SCENE_GROTTOS, 0x08 }}, "SFM Wolfos Grotto", "SFM Wolfos Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
{ ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "SFM Fairy Grotto", "SFM Fairy Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
{ ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "SFM Storms Grotto", "SFM Storms Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, ENTR_FOREST_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Entrance", "SFM Outside Forest Temple", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON},
{ ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, ENTR_FOREST_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Boss Door", "Phantom Ganon", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_FOREST_TEMPLE_BOSS_DOOR, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Boss Door", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Blue Warp", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
{ ENTR_LOST_WOODS_NORTH_EXIT, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "Sacred Forest Meadow South Exit", "Lost Woods North Exit", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Wolfos Grotto Entry", "SFM Wolfos Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Fairy Grotto Entry", "SFM Fairy Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "SFM Storms Grotto Entry", "SFM Storms Grotto", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_SACRED_FOREST_MEADOW), "Sacred Forest Meadow Outside Forest Temple", "Forest Temple Entrance", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET), {{ SCENE_GROTTOS, 0x08 }}, "SFM Wolfos Grotto", "SFM Wolfos Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
{ ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "SFM Fairy Grotto", "SFM Fairy Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO},
{ ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "SFM Storms Grotto", "SFM Storms Grotto Entry", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, ENTR_FOREST_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Entrance", "Sacred Forest Meadow Outside Forest Temple", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON},
{ ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, ENTR_FOREST_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Boss Door", "Phantom Ganon", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_FOREST_TEMPLE_BOSS_DOOR, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Boss Door", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon Blue Warp", "Forest Temple Blue Warp", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Kakariko Village
{ ENTR_HYRULE_FIELD_STAIRS_EXIT, ENTR_KAKARIKO_VILLAGE_FRONT_GATE, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Front Gate", "Hyrule Field Stairs Exit", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
@ -153,7 +153,7 @@ const EntranceData entranceData[] = {
{ ENTR_POTION_SHOP_KAKARIKO_BACK, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Potion Shop Back Entry", "Kak Potion Shop Back", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Open Grotto Entry", "Kak Open Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET), SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Center Grotto Entry", "Kak Redead Grotto", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kak Outside BotW", "Bottom of the Well Entrance", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw", 1},
{ ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko Outside the Well", "Bottom of the Well Entrance", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw", 1},
{ ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0, SINGLE_SCENE_INFO(SCENE_KAKARIKO_CENTER_GUEST_HOUSE), "Carpenter Boss House", "Kak Boss House Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE, ENTR_HOUSE_OF_SKULLTULA_0, SINGLE_SCENE_INFO(SCENE_HOUSE_OF_SKULLTULA), "House of Skulltula", "Kak Skulltula House Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT, ENTR_IMPAS_HOUSE_FRONT, SINGLE_SCENE_INFO(SCENE_IMPAS_HOUSE), "Impa's House Front", "Kak Impa's House Front Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
@ -166,7 +166,7 @@ const EntranceData entranceData[] = {
{ ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_KAKARIKO), "Kak Potion Shop Back", "Kak Potion Shop Back Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "Kak Open Grotto", "Kak Open Grotto Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET), {{ SCENE_GROTTOS, 0x03 }}, "Kak Redead Grotto", "Kak Center Grotto Entry", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, SINGLE_SCENE_INFO(SCENE_BOTTOM_OF_THE_WELL), "Bottom of the Well Entrance", "Kak Outside BotW", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw"},
{ ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE, SINGLE_SCENE_INFO(SCENE_BOTTOM_OF_THE_WELL), "Bottom of the Well Entrance", "Kakariko Outside the Well", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_DUNGEON, "botw"},
// The Graveyard
{ ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT, ENTR_GRAVEYARD_ENTRANCE, SINGLE_SCENE_INFO(SCENE_GRAVEYARD), "Graveyard Entrance", "Kakariko Southeast Exit", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
@ -184,67 +184,67 @@ const EntranceData entranceData[] = {
{ ENTR_GRAVEYARD_OUTSIDE_TEMPLE, ENTR_SHADOW_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Entrance", "Graveyard Outside Temple", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON},
{ ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, ENTR_SHADOW_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Boss Door", "Bongo-Bongo", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_SHADOW_TEMPLE_BOSS_DOOR, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Boss Door", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Blue Warp", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
{ ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo Blue Warp", "Shadow Temple Blue Warp", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Death Mountain Trail
{ ENTR_GORON_CITY_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Middle Exit", "Goron City Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ ENTR_KAKARIKO_VILLAGE_GUARD_GATE, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Bottom Exit", "Kakariko Guard Gate Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Top Exit", "Death Mountain Crater Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Great Fairy Entry", "DMT Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Rock Circle Grotto Entry", "DMT Storms Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Boulder Grotto Entry", "DMT Cow Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "", 1},
{ ENTR_DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Outside Dodongo's Cavern", "Dodongo's Cavern Entrance", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x00 }}, "DMT Great Fairy Fountain", "DMT Great Fairy Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMT Storms Grotto", "DMT Rock Circle Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), {{ SCENE_GROTTOS, 0x0D }}, "DMT Cow Grotto", "DMT Boulder Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO},
{ ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, ENTR_DODONGOS_CAVERN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Entrance", "DMT Outside Dodongo's Cavern", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"},
{ ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, ENTR_DODONGOS_CAVERN_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Boss Door", "King Dodongo", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ ENTR_DODONGOS_CAVERN_BOSS_DOOR, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_ONE_WAY, "dc,bw", 1},
{ ENTR_GORON_CITY_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Middle Exit", "Goron City Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ ENTR_KAKARIKO_VILLAGE_GUARD_GATE, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Bottom Exit", "Kakariko Guard Gate Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Top Exit", "Death Mountain Crater Upper Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Great Fairy Entry", "DMT Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Rock Circle Grotto Entry", "DMT Storms Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT Boulder Grotto Entry", "DMT Cow Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "", 1},
{ ENTR_DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "Death Mountain Trail Outside Dodongo's Cavern", "Dodongo's Cavern Entrance", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x00 }}, "DMT Great Fairy Fountain", "DMT Great Fairy Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMT Storms Grotto", "DMT Rock Circle Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET), {{ SCENE_GROTTOS, 0x0D }}, "DMT Cow Grotto", "DMT Boulder Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_GROTTO},
{ ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, ENTR_DODONGOS_CAVERN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Entrance", "Death Mountain Trail Outside Dodongo's Cavern", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"},
{ ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, ENTR_DODONGOS_CAVERN_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Boss Door", "King Dodongo", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ ENTR_DODONGOS_CAVERN_BOSS_DOOR, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
{ ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo Blue Warp", "Dodongo's Cavern Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_ONE_WAY, "dc,bw", 1},
// Death Mountain Crater
{ ENTR_GORON_CITY_DARUNIA_ROOM_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Bridge Exit", "Goron City Darunia's Room Backdoor", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Upper Exit", "Death Mountain Trail Top Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Great Fairy Exit", "DMC Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Upper Grotto Exit", "DMC Upper Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Hammer Grotto Exit", "DMC Hammer Scrubs Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Great Fairy Entry", "DMC Great Fairy Fountain", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Upper Grotto Entry", "DMC Upper Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC Hammer Grotto Entry", "DMC Scrubs Grotto", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_FIRE_TEMPLE_ENTRANCE, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "Death Mountain Crater Outside Temple", "Fire Temple Entrance", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x01 }}, "DMC Great Fairy Fountain", "DMC Great Fairy Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMC Upper Grotto", "DMC Upper Grotto Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "DMC Hammer Grotto", "DMC Hammer Grotto Exit", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x01 }}, "DMC Great Fairy Fountain", "DMC Great Fairy Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "DMC Upper Grotto", "DMC Upper Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "DMC Scrubs Grotto", "DMC Hammer Grotto Entry", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, ENTR_FIRE_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Entrance", "Death Mountain Crater Outside Temple", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON},
{ ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, ENTR_FIRE_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Boss Door", "Volvagia", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_FIRE_TEMPLE_BOSS_DOOR, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
{ ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia Blue Warp", "Fire Temple Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Goron City
{ ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT, ENTR_GORON_CITY_UPPER_EXIT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Upper Exit", "Death Mountain Trail Middle Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Darunia's Room Backdoor", "Death Mountain Crater Bridge Exit", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_OVERWORLD, "gc"},
{ ENTR_LOST_WOODS_TUNNEL_SHORTCUT, ENTR_GORON_CITY_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Tunnel Shortcut", "LW Tunnel Shortcut", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "gc,lw"},
{ ENTR_LOST_WOODS_TUNNEL_SHORTCUT, ENTR_GORON_CITY_TUNNEL_SHORTCUT, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City Tunnel Shortcut", "Lost Woods Tunnel Shortcut", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "gc,lw"},
{ ENTR_GORON_SHOP_0, ENTR_GORON_CITY_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Shop Entry", "Goron Shop", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Lava Grotto Entry", "Goron City Grotto", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), SINGLE_SCENE_INFO(SCENE_GORON_CITY), "GC Lava Grotto Entry", "GC Scrubs Grotto", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs", 1},
{ ENTR_GORON_CITY_OUTSIDE_SHOP, ENTR_GORON_SHOP_0, SINGLE_SCENE_INFO(SCENE_GORON_SHOP), "Goron Shop", "GC Shop Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_INTERIOR, "gc"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "Goron City Grotto", "GC Lava Grotto Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "GC Scrubs Grotto", "GC Lava Grotto Entry", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_GROTTO, "gc,scrubs"},
// Zora's River
{ ENTR_HYRULE_FIELD_RIVER_EXIT, ENTR_ZORAS_RIVER_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River West Exit", "Hyrule Field River Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Underwater Shortcut", "LW Underwater Shortcut", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_ZORAS_DOMAIN_ENTRANCE, ENTR_ZORAS_RIVER_WATERFALL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Waterfall Exit", "Zora's Domain Entrance", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Rock Circle Grotto Entry", "ZR Storms Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Boulder Grotto Entry", "ZR Fairy Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Open Grotto Entry", "ZR Open Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "ZR Storms Grotto", "ZR Rock Circle Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZR Fairy Grotto", "ZR Raised Boulder Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "ZR Open Grotto", "ZR Raised Open Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest"},
{ ENTR_HYRULE_FIELD_RIVER_EXIT, ENTR_ZORAS_RIVER_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Lower Exit", "Hyrule Field River Exit", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_LOST_WOODS_UNDERWATER_SHORTCUT, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Underwater Shortcut", "Lost Woods Underwater Shortcut", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_TYPE_OVERWORLD, "lw"},
{ ENTR_ZORAS_DOMAIN_ENTRANCE, ENTR_ZORAS_RIVER_WATERFALL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "Zora's River Waterfall Exit", "Zora's Domain Entrance", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Rock Circle Grotto Entry", "ZR Storms Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Boulder Grotto Entry", "ZR Fairy Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_RIVER), "ZR Raised Open Grotto Entry", "ZR Open Grotto", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest", 1},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "ZR Storms Grotto", "ZR Rock Circle Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZR Fairy Grotto", "ZR Raised Boulder Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET), {{ SCENE_GROTTOS, 0x00 }}, "ZR Open Grotto", "ZR Raised Open Grotto Entry", ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_GROTTO, "chest"},
// Zora's Domain
{ ENTR_ZORAS_RIVER_WATERFALL_EXIT, ENTR_ZORAS_DOMAIN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Entrance", "Zora's River Waterfall Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Underwater Shortcut", "LH Underwater Shortcut", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Behind King Zora", "Zora's Fountain Tunnel Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_ZORA_SHOP_0, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Shop Entry", "Zora Shop", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Island Grotto Entry", "ZD Storms Grotto", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy", 1},
{ ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, ENTR_ZORA_SHOP_0, SINGLE_SCENE_INFO(SCENE_ZORA_SHOP), "Zora Shop", "ZD Shop Entry", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZD Storms Grotto", "ZD Island Grotto Entry", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy"},
{ ENTR_ZORAS_RIVER_WATERFALL_EXIT, ENTR_ZORAS_DOMAIN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Entrance", "Zora's River Waterfall Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Underwater Shortcut", "Lake Hylia Underwater Shortcut", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "Zora's Domain Behind King Zora", "Zora's Fountain Tunnel Exit", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_ZORA_SHOP_0, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Shop Entry", "Zora Shop", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_ZORAS_DOMAIN), "ZD Island Grotto Entry", "ZD Storms Grotto", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy", 1},
{ ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP, ENTR_ZORA_SHOP_0, SINGLE_SCENE_INFO(SCENE_ZORA_SHOP), "Zora Shop", "ZD Shop Entry", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "ZD Storms Grotto", "ZD Island Grotto Entry", ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_GROTTO, "fairy"},
// Zora's Fountain
{ ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT, SINGLE_SCENE_INFO(SCENE_ZORAS_FOUNTAIN), "Zora's Fountain Tunnel Exit", "Zora's Domain Behind King Zora", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD},
@ -255,7 +255,7 @@ const EntranceData entranceData[] = {
{ ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU, ENTR_JABU_JABU_ENTRANCE, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Entrance", "Zora's Fountain Outside Jabu Jabu", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
{ ENTR_JABU_JABU_BOSS_ENTRANCE, ENTR_JABU_JABU_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Boss Door", "Barinade", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_JABU_JABU_BOSS_DOOR, ENTR_JABU_JABU_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Boss Door", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Blue Warp", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
{ ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade Blue Warp", "Jabu Jabu's Belly Blue Warp", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
{ ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN, ENTR_ICE_CAVERN_ENTRANCE, SINGLE_SCENE_INFO(SCENE_ICE_CAVERN), "Ice Cavern Entrance", "Zora's Fountain Outside Ice Cavern", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
// Hyrule Field
@ -263,7 +263,7 @@ const EntranceData entranceData[] = {
{ ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Drawbridge Exit", "Market Entrance South Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_LON_LON_RANCH_ENTRANCE, ENTR_HYRULE_FIELD_CENTER_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Center Exit", "Lon Lon Ranch Entrance", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_OVERWORLD, "hf,llr"},
{ ENTR_KAKARIKO_VILLAGE_FRONT_GATE, ENTR_HYRULE_FIELD_STAIRS_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Stairs Exit", "Kakariko Front Gate", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_KAKARIKO, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_ZORAS_RIVER_WEST_EXIT, ENTR_HYRULE_FIELD_RIVER_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field River Exit", "Zora's River West Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_ZORAS_RIVER_WEST_EXIT, ENTR_HYRULE_FIELD_RIVER_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field River Exit", "Zora's River Lower Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_ZORAS_RIVER, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_LAKE_HYLIA_NORTH_EXIT, ENTR_HYRULE_FIELD_FENCE_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Fence Exit", "Lake Hylia North Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "hf,lh"},
{ ENTR_GERUDO_VALLEY_EAST_EXIT, ENTR_HYRULE_FIELD_ROCKY_PATH, SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "Hyrule Field Rocky Path", "Gerudo Valley East Exit", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_FIELD), "HF Near Market Boulder Grotto Entry", "HF Near Market Boulder Grotto", ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_GROTTO, "chest", 1},
@ -295,39 +295,39 @@ const EntranceData entranceData[] = {
{ ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "LLR Scrubs Grotto", "LLR Grotto Entry", ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_GROUP_LON_LON_RANCH, ENTRANCE_TYPE_GROTTO, "scrubs"},
// Lake Hylia
{ ENTR_HYRULE_FIELD_FENCE_EXIT, ENTR_LAKE_HYLIA_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia North Exit", "Hyrule Field Fenced Exit", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Underwater Shortcut", "ZD Underwater Shortcut", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ ENTR_LAKESIDE_LABORATORY_0, ENTR_LAKE_HYLIA_OUTSIDE_LAB, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Lab Entry", "LH Lab", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
{ ENTR_FISHING_POND_0, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Fishing Pond Entry", "Fishing Pond", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Grave Grotto Entry", "LH Grotto", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia Outside Temple", "Water Temple Entrance", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
{ ENTR_LAKE_HYLIA_OUTSIDE_LAB, ENTR_LAKESIDE_LABORATORY_0, SINGLE_SCENE_INFO(SCENE_LAKESIDE_LABORATORY), "LH Lab", "LH Outside Lab", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
{ ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, ENTR_FISHING_POND_0, SINGLE_SCENE_INFO(SCENE_FISHING_POND), "Fishing Pond", "LH Outside Fishing Pond", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "LH Grotto", "LH Grave Grotto Entry", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "lh,scrubs"},
{ ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, ENTR_WATER_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Entrance", "Lake Hylia Outside Temple", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"},
{ ENTR_WATER_TEMPLE_BOSS_ENTRANCE, ENTR_WATER_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Boss Door", "Morpha", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
{ ENTR_WATER_TEMPLE_BOSS_DOOR, ENTR_WATER_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Boss Door", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
{ ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Blue Warp", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_ONE_WAY, "lh,bw", 1},
{ ENTR_HYRULE_FIELD_FENCE_EXIT, ENTR_LAKE_HYLIA_NORTH_EXIT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia North Exit", "Hyrule Field Fence Exit", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia Underwater Shortcut", "Zora's Domain Underwater Shortcut", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_ZORAS_DOMAIN, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ ENTR_LAKESIDE_LABORATORY_0, ENTR_LAKE_HYLIA_OUTSIDE_LAB, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Lab Entry", "LH Lab", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
{ ENTR_FISHING_POND_0, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Fishing Pond Entry", "Fishing Pond", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "LH Grave Grotto Entry", "LH Grotto", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, SINGLE_SCENE_INFO(SCENE_LAKE_HYLIA), "Lake Hylia Outside Temple", "Water Temple Entrance", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
{ ENTR_LAKE_HYLIA_OUTSIDE_LAB, ENTR_LAKESIDE_LABORATORY_0, SINGLE_SCENE_INFO(SCENE_LAKESIDE_LABORATORY), "LH Lab", "LH Lab Entry", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
{ ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND, ENTR_FISHING_POND_0, SINGLE_SCENE_INFO(SCENE_FISHING_POND), "Fishing Pond", "LH Fishing Pond Entry", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_INTERIOR, "lh"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET), {{ SCENE_GROTTOS, 0x04 }}, "LH Grotto", "LH Grave Grotto Entry", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_GROTTO, "lh,scrubs"},
{ ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, ENTR_WATER_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Entrance", "Lake Hylia Outside Temple", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"},
{ ENTR_WATER_TEMPLE_BOSS_ENTRANCE, ENTR_WATER_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Boss Door", "Morpha", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
{ ENTR_WATER_TEMPLE_BOSS_DOOR, ENTR_WATER_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Boss Door", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
{ ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha Blue Warp", "Water Temple Blue Warp", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_ONE_WAY, "lh,bw", 1},
// Gerudo Area
{ ENTR_HYRULE_FIELD_ROCKY_PATH, ENTR_GERUDO_VALLEY_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "Gerudo Valley East Exit", "Hyrule Field Rocky Path", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_GERUDOS_FORTRESS_EAST_EXIT, ENTR_GERUDO_VALLEY_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "Gerudo Valley West Exit", "Gerudo Fortress East Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ ENTR_LAKE_HYLIA_RIVER_EXIT, -1, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "Gerudo Valley River Exit", "Lake Hylia River Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_OVERWORLD, "lh"},
{ ENTR_CARPENTERS_TENT_0, ENTR_GERUDO_VALLEY_OUTSIDE_TENT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Outside Carpenters' Tent", "Carpenters' Tent", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_CARPENTERS_TENT_0, ENTR_GERUDO_VALLEY_OUTSIDE_TENT, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Carpenters' Tent Entry", "Carpenters' Tent", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Silver Rock Grotto Entry", "GV Octorok Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV Behind Tent Grotto Entry", "GV Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs", 1},
{ ENTR_GERUDO_VALLEY_WEST_EXIT, ENTR_GERUDOS_FORTRESS_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "Gerudo Fortress East Exit", "Gerudo Valley West Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ ENTR_HAUNTED_WASTELAND_EAST_EXIT, ENTR_GERUDOS_FORTRESS_GATE_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "Gerudo Fortress Gate Exit", "Haunted Wasteland", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ ENTR_HAUNTED_WASTELAND_EAST_EXIT, ENTR_GERUDOS_FORTRESS_GATE_EXIT, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "Gerudo Fortress Gate Exit", "Haunted Wasteland East Exit", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "gerudo fortress"},
{ ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "GF Storms Grotto Entry", "GF Storms Grotto", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress", 1},
{ ENTR_GERUDO_TRAINING_GROUND_ENTRANCE, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND, SINGLE_SCENE_INFO(SCENE_GERUDOS_FORTRESS), "GF Outside Training Ground", "Gerudo Training Ground Entrance", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_DUNGEON, "gerudo fortress,gtg", 1},
{ ENTR_GERUDO_VALLEY_OUTSIDE_TENT, ENTR_CARPENTERS_TENT_0, SINGLE_SCENE_INFO(SCENE_CARPENTERS_TENT), "Carpenters' Tent", "GV Outside Carpenters' Tent", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR},
{ ENTR_GERUDO_VALLEY_OUTSIDE_TENT, ENTR_CARPENTERS_TENT_0, SINGLE_SCENE_INFO(SCENE_CARPENTERS_TENT), "Carpenters' Tent", "GV Carpenters' Tent Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET), {{ SCENE_GROTTOS, 0x06 }}, "GV Octorok Grotto", "GV Silver Rock Grotto Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO},
{ ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x0A }}, "GV Storms Grotto", "GV Behind Tent Grotto Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "scrubs"},
{ ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET), {{ SCENE_FAIRYS_FOUNTAIN, 0x00 }}, "GF Storms Grotto", "GF Storms Grotto Entry", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_GROTTO, "gerudo fortress"},
{ ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE, SINGLE_SCENE_INFO(SCENE_GERUDO_TRAINING_GROUND), "Gerudo Training Ground Entrance", "GF Outside Training Ground", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_DUNGEON, "gerudo fortress,gtg"},
// The Wasteland
{ ENTR_GERUDOS_FORTRESS_GATE_EXIT, ENTR_HAUNTED_WASTELAND_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_HAUNTED_WASTELAND), "Haunted Wasteland East Exit", "GF Gate Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hw,gerudo fortress"},
{ ENTR_GERUDOS_FORTRESS_GATE_EXIT, ENTR_HAUNTED_WASTELAND_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_HAUNTED_WASTELAND), "Haunted Wasteland East Exit", "Gerudo Fortress Gate Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_TYPE_OVERWORLD, "hw,gerudo fortress"},
{ ENTR_DESERT_COLOSSUS_EAST_EXIT, ENTR_HAUNTED_WASTELAND_WEST_EXIT, SINGLE_SCENE_INFO(SCENE_HAUNTED_WASTELAND), "Haunted Wasteland West Exit", "Desert Colossus East Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "dc,hw"},
{ ENTR_HAUNTED_WASTELAND_WEST_EXIT, ENTR_DESERT_COLOSSUS_EAST_EXIT, SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Desert Colossus East Exit", "Haunted Wasteland West Exit", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_OVERWORLD, "dc,hw"},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_DESERT_COLOSSUS), "Colossus Great Fairy Entry", "Colossus Great Fairy Fountain", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_INTERIOR, "dc", 1},
@ -338,46 +338,46 @@ const EntranceData entranceData[] = {
{ ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_SPIRIT_TEMPLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple Entrance", "Colossus Outside Temple", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc"},
{ ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE, ENTR_SPIRIT_TEMPLE_BOSS_DOOR, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple Boss Door", "Twinrova", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_SPIRIT_TEMPLE_BOSS_DOOR, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Boss Door", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
{ ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Blue Warp", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
{ ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP, -1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova Blue Warp", "Spirit Temple Blue Warp", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
// Market
{ ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance South Exit", "Hyrule Field Drawbridge Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_MARKET_SOUTH_EXIT, ENTR_MARKET_ENTRANCE_NORTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance North Exit", "Market South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_MARKET_GUARD_HOUSE_0, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance Outside Guard House", "Guard House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe", 1},
{ ENTR_MARKET_ENTRANCE_NORTH_EXIT, ENTR_MARKET_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market South Exit", "Market Entrance North Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_CASTLE_GROUNDS_SOUTH_EXIT, ENTR_MARKET_DAY_CASTLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Castle Exit", "Castle Grounds South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
{ ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, ENTR_MARKET_DAY_TEMPLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Temple Exit", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_SHOOTING_GALLERY_1, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Shooting Gallery Entry", "MK Shooting Gallery", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "child", 1},
{ ENTR_BOMBCHU_BOWLING_ALLEY_0, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bombchu Bowling Entry", "Bombchu Bowling", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_TREASURE_BOX_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Treasure Chest Game Entry", "Treasure Chest Game", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Man-in-Green House Entry", "Man-in-Green's House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_HAPPY_MASK_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Mask Shop Entry", "Mask Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_BAZAAR_1, ENTR_MARKET_DAY_OUTSIDE_BAZAAR, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bazaar Entry", "MK Bazaar", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop", 1},
{ ENTR_POTION_SHOP_MARKET_0, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Potion Shop Entry", "MK Potion Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_BOMBCHU_SHOP_1, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bombchu Shop Entry", "Bombchu Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0, {{ SCENE_MARKET_GUARD_HOUSE }}, "Guard House", "MK Entrance Outside Guard House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe"},
{ ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1, {{ SCENE_SHOOTING_GALLERY, 0x01 }}, "MK Shooting Gallery", "MK Shooting Gallery Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0, SINGLE_SCENE_INFO(SCENE_BOMBCHU_BOWLING_ALLEY), "Bombchu Bowling", "MK Bombchu Bowling Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, ENTR_TREASURE_BOX_SHOP_0, SINGLE_SCENE_INFO(SCENE_TREASURE_BOX_SHOP), "Treasure Chest Game", "MK Treasure Chest Game Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, SINGLE_SCENE_INFO(SCENE_BACK_ALLEY_HOUSE), "Man-in-Green's House", "MK Man-in-Green House Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0, SINGLE_SCENE_INFO(SCENE_HAPPY_MASK_SHOP), "Mask Shop", "MK Mask Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_BAZAAR, ENTR_BAZAAR_1, {{ SCENE_BAZAAR, 0x01 }}, "MK Bazaar", "MK Bazaar Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop"},
{ ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_MARKET), "MK Potion Shop", "MK Potion Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1, SINGLE_SCENE_INFO(SCENE_BOMBCHU_SHOP), "Bombchu Shop", "MK Bombchu Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_TEMPLE_EXIT, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "MK Temple Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "tot"},
{ ENTR_TEMPLE_OF_TIME_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "Temple of Time Entrance", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot", 1},
{ ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, ENTR_TEMPLE_OF_TIME_ENTRANCE, SINGLE_SCENE_INFO(SCENE_TEMPLE_OF_TIME), "Temple of Time Entrance", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot"},
{ ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance South Exit", "Hyrule Field Drawbridge Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
{ ENTR_MARKET_SOUTH_EXIT, ENTR_MARKET_ENTRANCE_NORTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance North Exit", "Market South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_MARKET_GUARD_HOUSE_0, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "MK Entrance Guard House Entry", "Guard House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe", 1},
{ ENTR_MARKET_ENTRANCE_NORTH_EXIT, ENTR_MARKET_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market South Exit", "Market Entrance North Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_CASTLE_GROUNDS_SOUTH_EXIT, ENTR_MARKET_DAY_CASTLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Castle Exit", "Castle Grounds South Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
{ ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, ENTR_MARKET_DAY_TEMPLE_EXIT, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "Market Temple Exit", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD},
{ ENTR_SHOOTING_GALLERY_1, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Shooting Gallery Entry", "MK Shooting Gallery", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "child", 1},
{ ENTR_BOMBCHU_BOWLING_ALLEY_0, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bombchu Bowling Entry", "Bombchu Bowling", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_TREASURE_BOX_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Treasure Chest Game Entry", "Treasure Chest Game", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Man-in-Green House Entry", "Man-in-Green's House", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_HAPPY_MASK_SHOP_0, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Mask Shop Entry", "Mask Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_BAZAAR_1, ENTR_MARKET_DAY_OUTSIDE_BAZAAR, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bazaar Entry", "MK Bazaar", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop", 1},
{ ENTR_POTION_SHOP_MARKET_0, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Potion Shop Entry", "MK Potion Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_BOMBCHU_SHOP_1, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, {SCENE_NO_SPAWN(SCENE_MARKET_DAY), SCENE_NO_SPAWN(SCENE_MARKET_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_RUINS), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_DAY), SCENE_NO_SPAWN(SCENE_BACK_ALLEY_NIGHT)}, "MK Bombchu Shop Entry", "Bombchu Shop", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0, {{ SCENE_MARKET_GUARD_HOUSE }}, "Guard House", "MK Entrance Guard House Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "pots,poe"},
{ ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1, {{ SCENE_SHOOTING_GALLERY, 0x01 }}, "MK Shooting Gallery", "MK Shooting Gallery Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0, SINGLE_SCENE_INFO(SCENE_BOMBCHU_BOWLING_ALLEY), "Bombchu Bowling", "MK Bombchu Bowling Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP, ENTR_TREASURE_BOX_SHOP_0, SINGLE_SCENE_INFO(SCENE_TREASURE_BOX_SHOP), "Treasure Chest Game", "MK Treasure Chest Game Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE, SINGLE_SCENE_INFO(SCENE_BACK_ALLEY_HOUSE), "Man-in-Green's House", "MK Man-in-Green House Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0, SINGLE_SCENE_INFO(SCENE_HAPPY_MASK_SHOP), "Mask Shop", "MK Mask Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_OUTSIDE_BAZAAR, ENTR_BAZAAR_1, {{ SCENE_BAZAAR, 0x01 }}, "MK Bazaar", "MK Bazaar Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "shop"},
{ ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0, SINGLE_SCENE_INFO(SCENE_POTION_SHOP_MARKET), "MK Potion Shop", "MK Potion Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1, SINGLE_SCENE_INFO(SCENE_BOMBCHU_SHOP), "Bombchu Shop", "MK Bombchu Shop Entry", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR},
{ ENTR_MARKET_DAY_TEMPLE_EXIT, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "Market Temple Exit", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "tot"},
{ ENTR_TEMPLE_OF_TIME_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, {SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_DAY), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_NIGHT), SCENE_NO_SPAWN(SCENE_TEMPLE_OF_TIME_EXTERIOR_RUINS)}, "Outside Temple of Time", "Temple of Time Entrance", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot", 1},
{ ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE, ENTR_TEMPLE_OF_TIME_ENTRANCE, SINGLE_SCENE_INFO(SCENE_TEMPLE_OF_TIME), "Temple of Time Entrance", "Outside Temple of Time", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_INTERIOR, "tot"},
// Hyrule Castle
{ ENTR_MARKET_DAY_CASTLE_EXIT, ENTR_CASTLE_GROUNDS_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_HYRULE_CASTLE), SCENE_NO_SPAWN(SCENE_OUTSIDE_GANONS_CASTLE)}, "Castle Grounds South Exit", "Market Castle Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Boulder Crawlspace", "HC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Storms Grotto Entry", "HC Storms Grotto", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable", 1},
{ ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x01 }}, "HC Great Fairy Fountain", "HC Boulder Crawlspace", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x09 }}, "HC Storms Grotto", "HC Storms Grotto Entry", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable"},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, ENTR_POTION_SHOP_KAKARIKO_1, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Behind Pillar", "OGC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle", 1},
{ ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Rainbow Bridge Exit", "Ganon's Castle", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc", 1},
{ ENTR_POTION_SHOP_KAKARIKO_1, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x02 }}, "OGC Great Fairy Fountain", "OGC Behind Pillar", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle"},
{ ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Entrance", "OGC Rainbow Bridge Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"}
{ ENTR_MARKET_DAY_CASTLE_EXIT, ENTR_CASTLE_GROUNDS_SOUTH_EXIT, {SCENE_NO_SPAWN(SCENE_HYRULE_CASTLE), SCENE_NO_SPAWN(SCENE_OUTSIDE_GANONS_CASTLE)}, "Castle Grounds South Exit", "Market Castle Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_MARKET, ENTRANCE_TYPE_OVERWORLD, "outside ganon's castle"},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Boulder Crawlspace", "HC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "", 1},
{ ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), SINGLE_SCENE_INFO(SCENE_HYRULE_CASTLE), "HC Storms Grotto Entry", "HC Storms Grotto", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable", 1},
{ ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_SPELLS, 0x01 }}, "HC Great Fairy Fountain", "HC Boulder Crawlspace", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR},
{ ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET), ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET), {{ SCENE_GROTTOS, 0x09 }}, "HC Storms Grotto", "HC Storms Grotto Entry", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_GROTTO, "bombable"},
{ ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, ENTR_POTION_SHOP_KAKARIKO_1, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Behind Pillar", "OGC Great Fairy Fountain", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle", 1},
{ ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Rainbow Bridge Exit", "Inside Ganon's Castle Entrance", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc", 1},
{ ENTR_POTION_SHOP_KAKARIKO_1, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x02 }}, "OGC Great Fairy Fountain", "OGC Behind Pillar", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle"},
{ ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Entrance", "OGC Rainbow Bridge Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"}
};
// Check if Link is in the area and return that scene/entrance for tracking
@ -442,6 +442,21 @@ const EntranceData* GetEntranceData(s16 index) {
return nullptr;
}
// Used for verifying the names on both sides of entrance pairs match. Keeping for ease of use for further name changes later
// TODO: Figure out how to remove the need for duplicate entrance names so this is no longer necessary
void CheckEntranceNames() {
SPDLOG_ERROR("Checking entrance names:");
for (size_t i = 0; i < ARRAY_COUNT(entranceData); i++) {
auto entrance = &entranceData[i];
auto reverse = GetEntranceData(entrance->reverseIndex);
if (entrance != nullptr && reverse != nullptr) {
if (entrance->source != reverse->destination) {
SPDLOG_ERROR("{}({}) -> {}({})", entrance->source, entrance->index, reverse->destination, reverse->reverseIndex);
}
}
}
}
void SortEntranceListByType(EntranceOverride* entranceList, u8 byDest) {
EntranceOverride tempList[ENTRANCE_OVERRIDES_MAX_COUNT] = { 0 };

View File

@ -1253,6 +1253,8 @@ typedef enum {
RAND_INF_HF_FENCE_GROTTO_STORMS_FAIRY,
RAND_INF_LW_SHORTCUT_STORMS_FAIRY,
RAND_INF_GF_KITCHEN_SUN_FAIRY,
RAND_INF_LW_DEKU_SCRUB_GROTTO_SUN_FAIRY,
RAND_INF_GRAVEYARD_ROYAL_FAMILYS_TOMB_SUN_FAIRY,
RAND_INF_SPIRIT_TEMPLE_BOULDER_ROOM_SUN_FAIRY,
RAND_INF_SPIRIT_TEMPLE_ARMOS_ROOM_SUN_FAIRY,
RAND_INF_SHADOW_TEMPLE_BEAMOS_STORM_FAIRY,

View File

@ -272,7 +272,7 @@ extern "C" void Randomizer_InitSaveFile() {
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO);
}
int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).GetContextOptionIndex();
int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();
switch (startingAge) {
case RO_AGE_ADULT: // Adult
gSaveContext.linkAge = LINK_AGE_ADULT;

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,6 @@
#pragma once
#include "context.h"
#include "option.h"
#include "randomizerTypes.h"
#include "3drando/spoiler_log.hpp"
@ -49,11 +50,6 @@ class Settings {
*/
TrickOption& GetTrickOption(RandomizerTrick key);
/**
* @brief Reset all RandomizerTrick keys.
*/
void ResetTrickOptions();
/**
* @brief Returns a reference to the entire array of options.
*
@ -77,56 +73,6 @@ class Settings {
*/
const std::vector<std::vector<Option*>>& GetExcludeLocationsOptions() const;
/**
* @brief Gets the resolved Light Arrow CutScene check condition.
* There is no direct option for this, it is inferred based on the value of a few other options.
*
* @return RandoOptionLACSCondition
*/
RandoOptionLACSCondition LACSCondition() const;
/**
* @brief Get the hash for the current seed.
*
* @return std::string
*/
std::string GetHash() const;
/**
* @brief Get the Seed String
*
* @return const std::string&
*/
const std::string& GetSeedString() const;
/**
* @brief Set the Seed String
*
* @param seedString
*/
void SetSeedString(std::string seedString);
/**
* @brief Get the Seed
*
* @return const uint32_t
*/
uint32_t GetSeed() const;
/**
* @brief Set the Seed
*
* @param seed
*/
void SetSeed(uint32_t seed);
/**
* @brief Set the Seed Hash for the current seed.
*
* @param hash
*/
void SetHash(std::string hash);
/**
* @brief Get the list of `OptionGroup`s.
*
@ -160,42 +106,43 @@ class Settings {
*/
void UpdateOptionProperties();
/**
* @brief Runs before seed generation to ensure all options are compatible with each
* other and resolve options that have been set to random (such as random trial count,
* or starting age).
*
* @param excludedLocations Set of locations that should be forced to have junk items.
* @param enabledTricks Set of tricks that should be considered logically possible. Tricks
* are things that are possible to do in gameplay but are difficult, not intuitive or that
* require more extensive game knowledge, i.e. opening invisible chests without the Lens of Truth.
*/
void FinalizeSettings(const std::set<RandomizerCheck>& excludedLocations, const std::set<RandomizerTrick>& enabledTricks);
/**
* @brief Parse Options from a JSON file.
*
* @param spoilerFileJson
*/
void ParseJson(nlohmann::json spoilerFileJson);
std::vector<Option*> VanillaLogicDefaults = {};
std::map<RandomizerArea, std::vector<RandomizerTrick>> mTricksByArea = {};
void ReloadOptions();
/**
* @brief Assigns a Rando::Context instance to this settings instance
* with which to later instantiate and access OptionValues.
*
* @param ctx
*/
void AssignContext(std::shared_ptr<Context> ctx);
void ClearContext();
/**
* @brief Sets all the currently selected MenuIndexes to the currently assigned Rando::Context.
*/
void SetAllToContext();
static std::shared_ptr<Settings> GetInstance();
private:
/**
* @brief Create the list of description strings for `Option`s.
*/
void CreateOptionDescriptions();
static std::shared_ptr<Settings> mInstance;
std::shared_ptr<Context> mContext = nullptr;
std::array<Option, RSK_MAX> mOptions = {};
std::array<std::string, RSK_MAX> mOptionDescriptions = {};
std::array<OptionGroup, RSG_MAX> mOptionGroups = {};
std::array<TrickOption, RT_MAX> mTrickOptions = {};
std::vector<std::vector<Option*>> mExcludeLocationsOptionsAreas = {};
RandoOptionLACSCondition mLACSCondition = RO_LACS_VANILLA;
std::string mHash;
std::string mSeedString;
uint32_t mFinalSeed = 0;
std::unordered_map<std::string, RandomizerTrick> mTrickNameToEnum;
};
} // namespace Rando

View File

@ -44,7 +44,7 @@ extern void EnGo2_CurledUp(EnGo2* enGo2, PlayState* play);
extern void EnRu2_SetEncounterSwitchFlag(EnRu2* enRu2, PlayState* play);
}
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).GetContextOptionIndex()
#define RAND_GET_OPTION(option) Rando::Context::GetInstance()->GetOption(option).Get()
void EnMa1_EndTeachSong(EnMa1* enMa1, PlayState* play) {
if (Message_GetState(&gPlayState->msgCtx) == TEXT_STATE_CLOSING) {

View File

@ -391,9 +391,10 @@ OTRGlobals::OTRGlobals() {
gSaveStateMgr = std::make_shared<SaveStateMgr>();
gRandoContext->InitStaticData();
gRandoContext = Rando::Context::CreateInstance();
Rando::Settings::GetInstance()->AssignContext(gRandoContext);
Rando::StaticData::InitItemTable();//RANDOTODO make this not rely on context's logic so it can be initialised in InitStaticData
gRandoContext->AddExcludedOptions();
gRandoContext->GetSettings()->CreateOptions();
Rando::Settings::GetInstance()->CreateOptions();
gRandomizer = std::make_shared<Randomizer>();
hasMasterQuest = hasOriginal = false;
@ -1930,7 +1931,7 @@ extern "C" u32 SpoilerFileExists(const char* spoilerFileName) {
}
extern "C" u8 Randomizer_GetSettingValue(RandomizerSettingKey randoSettingKey) {
return OTRGlobals::Instance->gRandoContext->GetOption(randoSettingKey).GetContextOptionIndex();
return OTRGlobals::Instance->gRandoContext->GetOption(randoSettingKey).Get();
}
extern "C" RandomizerCheck Randomizer_GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams) {
@ -2439,9 +2440,8 @@ void SoH_ProcessDroppedFiles(std::string filePath) {
}
}
auto randoCtx = Rando::Context::GetInstance();
randoCtx->GetSettings()->UpdateOptionProperties();
randoCtx->GetSettings()->SetAllFromCVar();
Rando::Settings::GetInstance()->UpdateOptionProperties();
Rando::Settings::GetInstance()->SetAllFromCVar();
auto gui = Ship::Context::GetInstance()->GetWindow()->GetGui();
gui->GetGuiWindow("Console")->Hide();

View File

@ -28,7 +28,7 @@ struct ExtensionEntry {
};
extern std::unordered_map<std::string, ExtensionEntry> ExtensionCache;
#include "Enhancements/randomizer/context.h"
#include "Enhancements/randomizer/settings.h"
const std::string customMessageTableID = "BaseGameOverrides";
const std::string appShortName = "soh";

View File

@ -180,7 +180,7 @@ void SaveManager::LoadRandomizerVersion1() {
int key, value;
SaveManager::Instance->LoadData("sk" + std::to_string(i), key);
SaveManager::Instance->LoadData("sv" + std::to_string(i), value);
randoContext->GetOption(RandomizerSettingKey(key)).SetContextIndex(value);
randoContext->GetOption(RandomizerSettingKey(key)).Set(value);
}
for (int i = 0; i < 50; i++) {
@ -277,16 +277,16 @@ void SaveManager::LoadRandomizerVersion2() {
std::string inputSeed;
SaveManager::Instance->LoadData("inputSeed", inputSeed);
randoContext->GetSettings()->SetSeedString(inputSeed);
randoContext->SetSeedString(inputSeed);
uint32_t finalSeed;
SaveManager::Instance->LoadData("finalSeed", finalSeed);
randoContext->GetSettings()->SetSeed(finalSeed);
randoContext->SetSeed(finalSeed);
SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) {
int value = 0;
SaveManager::Instance->LoadData("", value);
randoContext->GetOption(RandomizerSettingKey(i)).SetContextIndex(value);
randoContext->GetOption(RandomizerSettingKey(i)).Set(value);
});
SaveManager::Instance->LoadArray("hintLocations", RH_ZR_OPEN_GROTTO_GOSSIP_STONE + 1, [&](size_t i) {
@ -426,16 +426,16 @@ void SaveManager::LoadRandomizerVersion3() {
std::string inputSeed;
SaveManager::Instance->LoadData("inputSeed", inputSeed);
randoContext->GetSettings()->SetSeedString(inputSeed);
randoContext->SetSeedString(inputSeed);
uint32_t finalSeed;
SaveManager::Instance->LoadData("finalSeed", finalSeed);
randoContext->GetSettings()->SetSeed(finalSeed);
randoContext->SetSeed(finalSeed);
SaveManager::Instance->LoadArray("randoSettings", RSK_MAX, [&](size_t i) {
int value = 0;
SaveManager::Instance->LoadData("", value);
randoContext->GetOption(RandomizerSettingKey(i)).SetContextIndex(value);
randoContext->GetOption(RandomizerSettingKey(i)).Set(value);
});
SaveManager::Instance->LoadArray("hintLocations", RH_MAX, [&](size_t i) {
@ -464,7 +464,7 @@ void SaveManager::LoadRandomizerVersion3() {
});
randoContext->GetTrials()->SkipAll();
SaveManager::Instance->LoadArray("requiredTrials", randoContext->GetOption(RSK_TRIAL_COUNT).GetContextOptionIndex() + 1, [&](size_t i) {
SaveManager::Instance->LoadArray("requiredTrials", randoContext->GetOption(RSK_TRIAL_COUNT).Get() + 1, [&](size_t i) {
size_t trialId;
SaveManager::Instance->LoadData("", trialId);
randoContext->GetTrial(trialId)->SetAsRequired();
@ -508,12 +508,12 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
SaveManager::Instance->SaveData("", randoContext->hashIconIndexes[i]);
});
SaveManager::Instance->SaveData("inputSeed", randoContext->GetSettings()->GetSeedString());
SaveManager::Instance->SaveData("inputSeed", randoContext->GetSeedString());
SaveManager::Instance->SaveData("finalSeed", randoContext->GetSettings()->GetSeed());
SaveManager::Instance->SaveData("finalSeed", randoContext->GetSeed());
SaveManager::Instance->SaveArray("randoSettings", RSK_MAX, [&](size_t i) {
SaveManager::Instance->SaveData("", randoContext->GetOption((RandomizerSettingKey(i))).GetContextOptionIndex());
SaveManager::Instance->SaveData("", randoContext->GetOption((RandomizerSettingKey(i))).Get());
});
SaveManager::Instance->SaveArray("hintLocations", RH_MAX, [&](size_t i) {
@ -662,8 +662,6 @@ void SaveManager::Init() {
OTRGlobals::Instance->gRandoContext->ClearItemLocations();
}
}
auto ctx = Rando::Context::GetInstance();
ctx->GetSettings()->CreateOptions();
}
void SaveManager::InitMeta(int fileNum) {
@ -2846,14 +2844,11 @@ extern "C" void Save_SaveGlobal(void) {
extern "C" void Save_LoadFile(void) {
// Handle vanilla context reset
OTRGlobals::Instance->gRandoContext->GetLogic()->SetContext(nullptr);
Rando::Settings::GetInstance()->ClearContext();
OTRGlobals::Instance->gRandoContext.reset();
OTRGlobals::Instance->gRandoContext = Rando::Context::CreateInstance();
OTRGlobals::Instance->gRandoContext->GetLogic()->SetSaveContext(&gSaveContext);
if (SaveManager::Instance->fileMetaInfo[gSaveContext.fileNum].randoSave) {
OTRGlobals::Instance->gRandoContext->AddExcludedOptions();
OTRGlobals::Instance->gRandoContext->GetSettings()->CreateOptions();
}
Rando::Settings::GetInstance()->AssignContext(OTRGlobals::Instance->gRandoContext);
SaveManager::Instance->LoadFile(gSaveContext.fileNum);
}

View File

@ -7254,19 +7254,9 @@ void func_8083E4C4(PlayState* play, Player* this, GetItemEntry* giEntry) {
s32 Player_ActionHandler_2(Player* this, PlayState* play) {
Actor* interactedActor;
if(gSaveContext.ship.pendingIceTrapCount) {
gSaveContext.ship.pendingIceTrapCount--;
GameInteractor_ExecuteOnItemReceiveHooks(ItemTable_RetrieveEntry(MOD_RANDOMIZER, RG_ICE_TRAP));
if (CVarGetInteger(CVAR_ENHANCEMENT("ExtraTraps.Enabled"), 0)) {
return 1;
}
this->stateFlags1 &= ~(PLAYER_STATE1_GETTING_ITEM | PLAYER_STATE1_CARRYING_ACTOR);
this->actor.colChkInfo.damage = 0;
func_80837C0C(play, this, 3, 0.0f, 0.0f, 0, 20);
if (GameInteractor_Should(VB_SHORT_CIRCUIT_GIVE_ITEM_PROCESS, false)) {
this->getItemId = GI_NONE;
this->getItemEntry = (GetItemEntry) GET_ITEM_NONE;
// Gameplay stats: Increment Ice Trap count
gSaveContext.ship.stats.count[COUNT_ICE_TRAPS]++;
this->getItemEntry = (GetItemEntry)GET_ITEM_NONE;
return 1;
}

View File

@ -3710,6 +3710,7 @@ void FileChoose_Init(GameState* thisx) {
this->questType[0] = MIN_QUEST;
this->questType[1] = MIN_QUEST;
this->questType[2] = MIN_QUEST;
fileSelectSpoilerFileLoaded = false;
CVarSetInteger(CVAR_GENERAL("OnFileSelectNameEntry"), 0);
SREG(30) = 1;