mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-08-22 14:23:44 -07:00
Merge branch 'develop-blair' into jabu-mouth-qol
This commit is contained in:
commit
1f93a2f596
57 changed files with 1112 additions and 576 deletions
|
@ -2,6 +2,7 @@ cmake_minimum_required(VERSION 3.26.0 FATAL_ERROR)
|
|||
|
||||
set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
|
||||
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||
set(CMAKE_C_STANDARD 17 CACHE STRING "The C standard to use")
|
||||
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version")
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ set(CMAKE_SYSTEM_VERSION 10.0 CACHE STRING "" FORCE)
|
|||
|
||||
project(soh LANGUAGES C CXX)
|
||||
set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||
set(CMAKE_C_STANDARD 17 CACHE STRING "The C standard to use")
|
||||
|
||||
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
|
||||
enable_language(OBJCXX)
|
||||
|
|
|
@ -15,7 +15,7 @@ extern "C"
|
|||
#include <soh/Enhancements/randomizer/randomizer_inf.h>
|
||||
|
||||
#if defined(INCLUDE_GAME_PRINTF) && defined(_DEBUG)
|
||||
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, __VA_ARGS__)
|
||||
#define osSyncPrintf(fmt, ...) lusprintf(__FILE__, __LINE__, 0, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define osSyncPrintf(fmt, ...) osSyncPrintfUnused(fmt, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
|
|
@ -265,6 +265,9 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
|
|||
}
|
||||
}
|
||||
|
||||
auto playingFromMenu = CVarGetInteger(CVAR_AUDIO("Playing"), 0);
|
||||
auto currentBGM = func_800FA0B4(SEQ_PLAYER_BGM_MAIN);
|
||||
|
||||
// Longest text in Audio Editor
|
||||
ImVec2 columnSize = ImGui::CalcTextSize("Navi - Look/Hey/Watchout (Target Enemy)");
|
||||
ImGui::BeginTable(tabId.c_str(), 3, ImGuiTableFlags_SizingFixedFit);
|
||||
|
@ -291,10 +294,13 @@ void Draw_SfxTab(const std::string& tabId, SeqType type, const std::string& tabN
|
|||
const std::string lockedButton = ICON_FA_LOCK + hiddenKey;
|
||||
const std::string unlockedButton = ICON_FA_UNLOCK + hiddenKey;
|
||||
const int currentValue = CVarGetInteger(cvarKey.c_str(), defaultValue);
|
||||
const bool isCurrentlyPlaying = currentValue == playingFromMenu || seqData.sequenceId == currentBGM;
|
||||
|
||||
ImGui::TableNextRow();
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::Text("%s", seqData.label.c_str());
|
||||
ImGui::TextColored(
|
||||
UIWidgets::ColorValues.at(isCurrentlyPlaying ? UIWidgets::Colors::Yellow : UIWidgets::Colors::White), "%s",
|
||||
seqData.label.c_str());
|
||||
ImGui::TableNextColumn();
|
||||
ImGui::PushItemWidth(-FLT_MIN);
|
||||
const int initialValue = map.contains(currentValue) ? currentValue : defaultValue;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include "soh/Enhancements/cosmetics/CosmeticsEditor.h"
|
||||
#include "soh/Enhancements/audio/AudioEditor.h"
|
||||
#include "soh/Enhancements/randomizer/logic.h"
|
||||
|
||||
#define Path _Path
|
||||
#define PATH_HACK
|
||||
|
@ -1450,6 +1451,55 @@ static bool SfxHandler(std::shared_ptr<Ship::Console> Console, const std::vector
|
|||
return 0;
|
||||
}
|
||||
|
||||
static bool AvailableChecksProcessUndiscoveredExitsHandler(std::shared_ptr<Ship::Console> Console,
|
||||
const std::vector<std::string>& args, std::string* output) {
|
||||
const auto& logic = Rando::Context::GetInstance()->GetLogic();
|
||||
bool enabled = false;
|
||||
|
||||
if (args.size() == 1) {
|
||||
enabled = !logic->ACProcessUndiscoveredExits;
|
||||
} else {
|
||||
try {
|
||||
enabled = std::stoi(args[1]);
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
ERROR_MESSAGE("[SOH] Enable should be 0 or 1");
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
logic->ACProcessUndiscoveredExits = enabled;
|
||||
INFO_MESSAGE("[SOH] Available Checks - Process Undiscovered Exits %s",
|
||||
logic->ACProcessUndiscoveredExits ? "enabled" : "disabled");
|
||||
|
||||
if (GameInteractor::IsSaveLoaded(true)) {
|
||||
CheckTracker::RecalculateAvailableChecks();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool AvailableChecksRecalculateHandler(std::shared_ptr<Ship::Console> Console,
|
||||
const std::vector<std::string>& args, std::string* output) {
|
||||
RandomizerRegion startingRegion = RR_ROOT;
|
||||
|
||||
if (args.size() > 1) {
|
||||
try {
|
||||
startingRegion = static_cast<RandomizerRegion>(std::stoi(args[1]));
|
||||
} catch (std::invalid_argument const& ex) {
|
||||
ERROR_MESSAGE("[SOH] Region should be a number");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (startingRegion <= RR_NONE || startingRegion >= RR_MAX) {
|
||||
ERROR_MESSAGE("[SOH] Region should be between 1 and %d", RR_MAX - 1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
CheckTracker::RecalculateAvailableChecks(startingRegion);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DebugConsole_Init(void) {
|
||||
// Console
|
||||
CMD_REGISTER("file_select", { FileSelectHandler, "Returns to the file select." });
|
||||
|
@ -1708,5 +1758,15 @@ void DebugConsole_Init(void) {
|
|||
{ "group_name", Ship::ArgumentType::TEXT, true },
|
||||
} });
|
||||
|
||||
CMD_REGISTER("acpue", { AvailableChecksProcessUndiscoveredExitsHandler,
|
||||
"Available Checks - Process Undiscovered Exits",
|
||||
{ { "enable", Ship::ArgumentType::NUMBER, true } } });
|
||||
|
||||
CMD_REGISTER("acr", { AvailableChecksRecalculateHandler,
|
||||
"Available Checks - Recalculate",
|
||||
{
|
||||
{ "starting_region", Ship::ArgumentType::NUMBER, true },
|
||||
} });
|
||||
|
||||
Ship::Context::GetInstance()->GetWindow()->GetGui()->SaveConsoleVariablesNextFrame();
|
||||
}
|
||||
|
|
|
@ -11,8 +11,13 @@
|
|||
|
||||
extern "C" {
|
||||
#include <z64.h>
|
||||
#include "src/overlays/actors/ovl_En_Rr/z_en_rr.h"
|
||||
}
|
||||
|
||||
#define CVAR_ENEMY_RANDOMIZER_NAME CVAR_ENHANCEMENT("RandomizedEnemies")
|
||||
#define CVAR_ENEMY_RANDOMIZER_DEFAULT ENEMY_RANDOMIZER_OFF
|
||||
#define CVAR_ENEMY_RANDOMIZER_VALUE CVarGetInteger(CVAR_ENEMY_RANDOMIZER_NAME, CVAR_ENEMY_RANDOMIZER_DEFAULT)
|
||||
|
||||
const char* enemyCVarList[] = {
|
||||
CVAR_ENHANCEMENT("RandomizedEnemyList.Armos"), CVAR_ENHANCEMENT("RandomizedEnemyList.Arwing"),
|
||||
CVAR_ENHANCEMENT("RandomizedEnemyList.BabyDodongo"), CVAR_ENHANCEMENT("RandomizedEnemyList.Bari"),
|
||||
|
@ -270,15 +275,7 @@ extern "C" uint8_t GetRandomizedEnemy(PlayState* play, int16_t* actorId, f32* po
|
|||
// Get randomized enemy ID and parameter.
|
||||
uint32_t seed =
|
||||
play->sceneNum + *actorId + (int)*posX + (int)*posY + (int)*posZ + *rotX + *rotY + *rotZ + *params;
|
||||
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed);
|
||||
|
||||
int8_t timesRandomized = 1;
|
||||
|
||||
// While randomized enemy isn't allowed in certain situations, randomize again.
|
||||
while (!IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, randomEnemy)) {
|
||||
randomEnemy = GetRandomizedEnemyEntry(seed + timesRandomized);
|
||||
timesRandomized++;
|
||||
}
|
||||
EnemyEntry randomEnemy = GetRandomizedEnemyEntry(seed, play);
|
||||
|
||||
*actorId = randomEnemy.id;
|
||||
*params = randomEnemy.params;
|
||||
|
@ -334,19 +331,28 @@ void GetSelectedEnemies() {
|
|||
}
|
||||
}
|
||||
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed) {
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play) {
|
||||
std::vector<EnemyEntry> filteredEnemyList = {};
|
||||
if (selectedEnemyList.size() == 0) {
|
||||
GetSelectedEnemies();
|
||||
}
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("RandomizedEnemies"), ENEMY_RANDOMIZER_OFF) == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
|
||||
for (EnemyEntry enemy : selectedEnemyList) {
|
||||
if (IsEnemyAllowedToSpawn(play->sceneNum, play->roomCtx.curRoom.num, enemy)) {
|
||||
filteredEnemyList.push_back(enemy);
|
||||
}
|
||||
}
|
||||
if (filteredEnemyList.size() == 0) {
|
||||
filteredEnemyList = selectedEnemyList;
|
||||
}
|
||||
if (CVAR_ENEMY_RANDOMIZER_VALUE == ENEMY_RANDOMIZER_RANDOM_SEEDED) {
|
||||
uint32_t finalSeed =
|
||||
seed + (IS_RANDO ? Rando::Context::GetInstance()->GetSeed() : gSaveContext.ship.stats.fileCreatedAt);
|
||||
Random_Init(finalSeed);
|
||||
uint32_t randomNumber = Random(0, selectedEnemyList.size());
|
||||
return selectedEnemyList[randomNumber];
|
||||
uint32_t randomNumber = Random(0, filteredEnemyList.size());
|
||||
return filteredEnemyList[randomNumber];
|
||||
} else {
|
||||
uint32_t randomSelectedEnemy = Random(0, selectedEnemyList.size());
|
||||
return selectedEnemyList[randomSelectedEnemy];
|
||||
uint32_t randomSelectedEnemy = Random(0, filteredEnemyList.size());
|
||||
return filteredEnemyList[randomSelectedEnemy];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -532,3 +538,45 @@ bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy) {
|
|||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterEnemyRandomizer() {
|
||||
// prevent dark link from triggering a voidout
|
||||
COND_VB_SHOULD(VB_TRIGGER_VOIDOUT, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||
Actor* actor = va_arg(args, Actor*);
|
||||
|
||||
if (actor->category != ACTORCAT_PLAYER) {
|
||||
*should = false;
|
||||
Actor_Kill(actor);
|
||||
}
|
||||
});
|
||||
|
||||
// prevent dark link dealing fall damage to the player
|
||||
COND_VB_SHOULD(VB_RECIEVE_FALL_DAMAGE, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||
Actor* actor = va_arg(args, Actor*);
|
||||
|
||||
if (actor->category != ACTORCAT_PLAYER) {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
|
||||
// prevent dark link from interfering with HESS/recoil/etc when at more than 100 away from him
|
||||
COND_VB_SHOULD(VB_TORCH2_HANDLE_CLANKING, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||
Actor* darkLink = va_arg(args, Actor*);
|
||||
|
||||
if (darkLink->xzDistToPlayer > 100.0f) {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
|
||||
// prevent dark link from being grabbed by like likes and therefore grabbing the player
|
||||
COND_VB_SHOULD(VB_LIKE_LIKE_GRAB_PLAYER, CVAR_ENEMY_RANDOMIZER_VALUE != CVAR_ENEMY_RANDOMIZER_DEFAULT, {
|
||||
EnRr* likeLike = va_arg(args, EnRr*);
|
||||
|
||||
if (!(likeLike->collider1.base.oc != NULL && likeLike->collider1.base.oc->category == ACTORCAT_PLAYER) &&
|
||||
!(likeLike->collider2.base.oc != NULL && likeLike->collider2.base.oc->category == ACTORCAT_PLAYER)) {
|
||||
*should = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static RegisterShipInitFunc initFunc(RegisterEnemyRandomizer, { CVAR_ENEMY_RANDOMIZER_NAME });
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <libultraship/bridge.h>
|
||||
#include "item-tables/ItemTableTypes.h"
|
||||
|
||||
typedef struct EnemyEntry {
|
||||
int16_t id;
|
||||
|
@ -11,7 +12,7 @@ typedef struct EnemyEntry {
|
|||
|
||||
bool IsEnemyFoundToRandomize(int16_t sceneNum, int8_t roomNum, int16_t actorId, int16_t params, float posX);
|
||||
bool IsEnemyAllowedToSpawn(int16_t sceneNum, int8_t roomNum, EnemyEntry enemy);
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed);
|
||||
EnemyEntry GetRandomizedEnemyEntry(uint32_t seed, PlayState* play);
|
||||
|
||||
extern const char* enemyCVarList[];
|
||||
extern const char* enemyNameList[];
|
||||
|
|
|
@ -474,6 +474,14 @@ typedef enum {
|
|||
// - `*BgHeavyBlock`
|
||||
VB_FREEZE_LINK_FOR_BLOCK_THROW,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - None
|
||||
VB_FREEZE_LINK_FOR_FOREST_PILLARS,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
|
@ -1358,6 +1366,14 @@ typedef enum {
|
|||
// - `*BgTreemouth`
|
||||
VB_PLAY_DEKU_TREE_INTRO_CS,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*DemoKekkai`
|
||||
VB_PLAY_DISPEL_BARRIER_CS,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
|
@ -1422,6 +1438,15 @@ typedef enum {
|
|||
// - None
|
||||
VB_PLAY_FIRE_ARROW_CS,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnHeishi2`
|
||||
// - `bool` (clearCamera - true if the code clears a sub-camera, false otherwise)
|
||||
VB_PLAY_GATE_OPENING_OR_CLOSING_CS,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
|
@ -1986,6 +2011,38 @@ typedef enum {
|
|||
// #### `args`
|
||||
// - `*EnWonderTalk2`
|
||||
VB_WONDER_TALK,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*Actor`
|
||||
VB_TRIGGER_VOIDOUT,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*Actor`
|
||||
VB_TORCH2_HANDLE_CLANKING,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*Actor`
|
||||
VB_RECIEVE_FALL_DAMAGE,
|
||||
|
||||
// #### `result`
|
||||
// ```c
|
||||
// true
|
||||
// ```
|
||||
// #### `args`
|
||||
// - `*EnRr`
|
||||
VB_LIKE_LIKE_GRAB_PLAYER,
|
||||
} GIVanillaBehavior;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -99,6 +99,13 @@ void SwitchAge() {
|
|||
gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK_FAST;
|
||||
gPlayState->linkAgeOnLoad ^= 1;
|
||||
|
||||
// Discover adult/child spawns
|
||||
if (gPlayState->linkAgeOnLoad == LINK_AGE_ADULT) {
|
||||
Entrance_SetEntranceDiscovered(ENTR_HYRULE_FIELD_10, false);
|
||||
} else {
|
||||
Entrance_SetEntranceDiscovered(ENTR_LINKS_HOUSE_CHILD_SPAWN, false);
|
||||
}
|
||||
|
||||
static HOOK_ID hookId = 0;
|
||||
hookId = REGISTER_VB_SHOULD(VB_INFLICT_VOID_DAMAGE, {
|
||||
*should = false;
|
||||
|
|
|
@ -209,6 +209,13 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
|
|||
bool stopOnBeatable = false, bool addToPlaythrough = false) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (auto& exit : region->exits) {
|
||||
int16_t entranceIndex = exit.GetIndex();
|
||||
if (!logic->ACProcessUndiscoveredExits && logic->CalculatingAvailableChecks &&
|
||||
ctx->GetOption(RSK_SHUFFLE_ENTRANCES).Get() && exit.IsShuffled() && entranceIndex != -1 &&
|
||||
!Entrance_GetIsEntranceDiscovered(entranceIndex)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Region* exitRegion = exit.GetConnectedRegion();
|
||||
// Update Time of Day Access for the exit
|
||||
if (UpdateToDAccess(&exit, exitRegion)) {
|
||||
|
@ -421,18 +428,13 @@ bool AddCheckToLogic(LocationAccess& locPair, GetAccessibleLocationsStruct& gals
|
|||
Rando::ItemLocation* location = ctx->GetItemLocation(loc);
|
||||
RandomizerGet locItem = location->GetPlacedRandomizerGet();
|
||||
|
||||
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, gals.calculatingAvailableChecks)) {
|
||||
if (gals.calculatingAvailableChecks) {
|
||||
gals.accessibleLocations.push_back(loc);
|
||||
StopPerformanceTimer(PT_LOCATION_LOGIC);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!location->IsAddedToPool() && locPair.ConditionsMet(parentRegion, logic->CalculatingAvailableChecks)) {
|
||||
location->AddToPool();
|
||||
|
||||
if (locItem == RG_NONE) {
|
||||
if (locItem == RG_NONE || logic->CalculatingAvailableChecks) {
|
||||
gals.accessibleLocations.push_back(loc); // Empty location, consider for placement
|
||||
} else {
|
||||
}
|
||||
if (locItem != RG_NONE) {
|
||||
// If ignore has a value, we want to check if the item location should be considered or not
|
||||
// This is necessary due to the below preprocessing for playthrough generation
|
||||
if (ignore != RG_NONE) {
|
||||
|
@ -528,11 +530,32 @@ void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, Randomize
|
|||
// Return any of the targetLocations that are accessible in logic
|
||||
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& targetLocations,
|
||||
RandomizerGet ignore /* = RG_NONE*/,
|
||||
bool calculatingAvailableChecks /* = false */) {
|
||||
bool calculatingAvailableChecks /* = false */,
|
||||
RandomizerRegion startingRegion /* = RR_ROOT */) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
GetAccessibleLocationsStruct gals(0);
|
||||
gals.calculatingAvailableChecks = calculatingAvailableChecks;
|
||||
ResetLogic(ctx, gals, !calculatingAvailableChecks);
|
||||
if (startingRegion != RR_ROOT) {
|
||||
gals.regionPool.insert(gals.regionPool.begin(), startingRegion);
|
||||
|
||||
const auto& region = RegionTable(startingRegion);
|
||||
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
|
||||
region->childDay = true;
|
||||
} else {
|
||||
region->adultDay = true;
|
||||
}
|
||||
if (region->timePass) {
|
||||
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD)) {
|
||||
region->childNight = true;
|
||||
} else {
|
||||
region->adultNight = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (calculatingAvailableChecks) {
|
||||
logic->Reset(false);
|
||||
logic->CalculatingAvailableChecks = true;
|
||||
}
|
||||
do {
|
||||
gals.InitLoop();
|
||||
for (size_t i = 0; i < gals.regionPool.size(); i++) {
|
||||
|
|
|
@ -34,8 +34,6 @@ struct GetAccessibleLocationsStruct {
|
|||
std::vector<RandomizerCheck> itemSphere;
|
||||
std::list<Rando::Entrance*> entranceSphere;
|
||||
|
||||
bool calculatingAvailableChecks = false;
|
||||
|
||||
GetAccessibleLocationsStruct(int _maxGsCount){
|
||||
regionPool = {RR_ROOT};
|
||||
gsCount = 0;
|
||||
|
@ -58,13 +56,14 @@ struct GetAccessibleLocationsStruct {
|
|||
void ClearProgress();
|
||||
void VanillaFill();
|
||||
int Fill();
|
||||
void SetAreas();
|
||||
|
||||
std::vector<RandomizerCheck> GetEmptyLocations(std::vector<RandomizerCheck> allowedLocations);
|
||||
|
||||
void ProcessRegion(Region* region, GetAccessibleLocationsStruct& gals, RandomizerGet ignore = RG_NONE,
|
||||
bool stopOnBeatable = false, bool addToPlaythrough = false);
|
||||
|
||||
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& allowedLocations, RandomizerGet ignore=RG_NONE, bool calculatingAvailableChecks=false);
|
||||
std::vector<RandomizerCheck> ReachabilitySearch(const std::vector<RandomizerCheck>& allowedLocations, RandomizerGet ignore=RG_NONE, bool calculatingAvailableChecks=false, RandomizerRegion startingRegion=RR_ROOT);
|
||||
|
||||
void GeneratePlaythrough();
|
||||
|
||||
|
|
|
@ -2412,13 +2412,13 @@ void StaticData::HintTable_Init() {
|
|||
|
||||
hintTextTable[RHT_ISOLATED_PLACE] = HintText(CustomMessage("an Isolated Place"));
|
||||
|
||||
hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage(" It's ordinary.",
|
||||
/*german*/ "&Sieht aus wie immer.",
|
||||
/*french*/ "&Elle vous semble %rordinaire%w."));
|
||||
hintTextTable[RHT_DUNGEON_ORDINARY] = HintText(CustomMessage("&It's %gordinary%w.",
|
||||
/*german*/ "&Sieht aus %gwie immer%w.",
|
||||
/*french*/ "&Elle vous semble %gordinaire%w."));
|
||||
|
||||
hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage(" It's masterful!",
|
||||
/*german*/ "&Man kann darauf die Worte&%r\"Master Quest\"%w entziffern...",
|
||||
/*french*/ "&Étrange... les mots %r\"Master&Quest\"%w sont gravés dessus."));
|
||||
hintTextTable[RHT_DUNGEON_MASTERFUL] = HintText(CustomMessage("&It's %rmasterful%w!",
|
||||
/*german*/ "&Man kann darauf die Worte %r\"Master_Quest\"%w entziffern...",
|
||||
/*french*/ "&Étrange... les mots %r\"Master_Quest\"%w sont gravés dessus."));
|
||||
|
||||
// clang-format on
|
||||
}
|
||||
|
|
|
@ -362,7 +362,7 @@ void Rando::StaticData::RegisterCrateLocations() {
|
|||
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1518), "Near Impas House Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_1));
|
||||
locationTable[RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-389, 1470), "Near Impas House Adult Crate 2", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_IMPAS_HOUSE_ADULT_CRATE_2));
|
||||
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_1, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-433, -401), "Near Bazaar Adult Crate 1", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_1));
|
||||
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-489, -424), "Near Bazaar Adult Crate 2`", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_2));
|
||||
locationTable[RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2] = Location::Crate(RC_KAK_NEAR_BAZAAR_ADULT_CRATE_2, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-489, -424), "Near Bazaar Adult Crate 2", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_BAZAAR_ADULT_CRATE_2));
|
||||
locationTable[RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE] = Location::Crate(RC_KAK_BEHIND_GS_HOUSE_ADULT_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(-724, 871), "Behind GS House Adult Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_BEHIND_GS_HOUSE_ADULT_CRATE));
|
||||
locationTable[RC_KAK_NEAR_GY_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_GY_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1732, 1366), "Near Graveyard Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_GY_CHILD_CRATE));
|
||||
locationTable[RC_KAK_NEAR_WINDMILL_CHILD_CRATE] = Location::Crate(RC_KAK_NEAR_WINDMILL_CHILD_CRATE, RCQUEST_BOTH, RCAREA_KAKARIKO_VILLAGE, SCENE_KAKARIKO_VILLAGE, TWO_ACTOR_PARAMS(1170, 601), "Near Windmill Child Crate", RHT_CRATE_KAKARIKO_VILLAGE, RG_GREEN_RUPEE, SpoilerCollectionCheck::RandomizerInf(RAND_INF_KAK_NEAR_WINDMILL_CHILD_CRATE));
|
||||
|
|
|
@ -400,8 +400,9 @@ void Context::ParseSpoiler(const char* spoilerFileName) {
|
|||
ParseHashIconIndexesJson(spoilerFileJson);
|
||||
Rando::Settings::GetInstance()->ParseJson(spoilerFileJson);
|
||||
ParseItemLocationsJson(spoilerFileJson);
|
||||
ParseHintJson(spoilerFileJson);
|
||||
ParseTricksJson(spoilerFileJson);
|
||||
mEntranceShuffler->ParseJson(spoilerFileJson);
|
||||
ParseHintJson(spoilerFileJson);
|
||||
mDungeons->ParseJson(spoilerFileJson);
|
||||
mTrials->ParseJson(spoilerFileJson);
|
||||
mSpoilerLoaded = true;
|
||||
|
@ -469,6 +470,17 @@ void Context::ParseHintJson(nlohmann::json spoilerFileJson) {
|
|||
CreateStaticHints();
|
||||
}
|
||||
|
||||
void Context::ParseTricksJson(nlohmann::json spoilerFileJson) {
|
||||
nlohmann::json enabledTricksJson = spoilerFileJson["enabledTricks"];
|
||||
const auto& settings = Rando::Settings::GetInstance();
|
||||
for (auto it : enabledTricksJson) {
|
||||
int rt = settings->GetRandomizerTrickByName(it);
|
||||
if (rt != -1) {
|
||||
mTrickOptions[rt].Set(RO_GENERIC_ON);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::shared_ptr<EntranceShuffler> Context::GetEntranceShuffler() {
|
||||
return mEntranceShuffler;
|
||||
}
|
||||
|
@ -524,6 +536,10 @@ RandoOptionLACSCondition Context::LACSCondition() const {
|
|||
return mLACSCondition;
|
||||
}
|
||||
|
||||
void Context::LACSCondition(RandoOptionLACSCondition lacsCondition) {
|
||||
mLACSCondition = lacsCondition;
|
||||
}
|
||||
|
||||
std::shared_ptr<Kaleido> Context::GetKaleido() {
|
||||
if (mKaleido == nullptr) {
|
||||
mKaleido = std::make_shared<Kaleido>();
|
||||
|
|
|
@ -104,12 +104,22 @@ class Context {
|
|||
* @return RandoOptionLACSCondition
|
||||
*/
|
||||
RandoOptionLACSCondition LACSCondition() const;
|
||||
|
||||
/**
|
||||
* @brief Sets 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.
|
||||
*
|
||||
* @param lacsCondition
|
||||
*/
|
||||
void LACSCondition(RandoOptionLACSCondition lacsCondition);
|
||||
|
||||
GetItemEntry GetFinalGIEntry(RandomizerCheck rc, bool checkObtainability = true, GetItemID ogItemId = GI_NONE);
|
||||
void ParseSpoiler(const char* spoilerFileName);
|
||||
void ParseHashIconIndexesJson(nlohmann::json spoilerFileJson);
|
||||
void ParseItemLocationsJson(nlohmann::json spoilerFileJson);
|
||||
void WriteHintJson(nlohmann::ordered_json& spoilerFileJson);
|
||||
void ParseHintJson(nlohmann::json spoilerFileJson);
|
||||
void ParseTricksJson(nlohmann::json spoilerFileJson);
|
||||
std::map<RandomizerCheck, ItemOverride> overrides = {};
|
||||
std::vector<std::vector<RandomizerCheck>> playthroughLocations = {};
|
||||
std::vector<RandomizerCheck> everyPossibleLocation = {};
|
||||
|
|
|
@ -250,7 +250,319 @@ std::string EntranceNameByRegions(RandomizerRegion parentRegion, RandomizerRegio
|
|||
return RegionTable(parentRegion)->regionName + " -> " + RegionTable(connectedRegion)->regionName;
|
||||
}
|
||||
|
||||
void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
||||
std::unordered_map<int16_t, Entrance*> entranceMap;
|
||||
|
||||
void SetAllEntrancesData() {
|
||||
std::vector<EntranceInfoPair> entranceShuffleTable = {
|
||||
// clang-format off
|
||||
// Type Parent Region Connected Region Index
|
||||
{ { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, ENTR_DEKU_TREE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE } },
|
||||
{ { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, ENTR_DODONGOS_CAVERN_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN } },
|
||||
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, ENTR_JABU_JABU_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } },
|
||||
{ { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, ENTR_SHADOW_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } },
|
||||
{ { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } },
|
||||
{ { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } },
|
||||
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE },
|
||||
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } },
|
||||
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, ENTR_TWINS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, ENTR_KOKIRI_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP } },
|
||||
{ { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, ENTR_LAKESIDE_LABORATORY_0 },
|
||||
{ EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_LAB } },
|
||||
{ { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_POND, ENTR_FISHING_POND_0 },
|
||||
{ EntranceType::Interior, RR_LH_FISHING_POND, RR_LH_FISHING_ISLAND, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND } },
|
||||
{ { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, ENTR_CARPENTERS_TENT_0 },
|
||||
{ EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_OUTSIDE_TENT } },
|
||||
{ { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, ENTR_TREASURE_BOX_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP } },
|
||||
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1 },
|
||||
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP } },
|
||||
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE },
|
||||
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, ENTR_HOUSE_OF_SKULLTULA_0 },
|
||||
{ EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, ENTR_IMPAS_HOUSE_FRONT },
|
||||
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT } },
|
||||
{ { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK },
|
||||
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK } },
|
||||
{ { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, ENTR_POTION_SHOP_GRANNY_0 },
|
||||
{ EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY } },
|
||||
{ { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, ENTR_GRAVEKEEPERS_HUT_0 },
|
||||
{ EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT } },
|
||||
{ { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, ENTR_GORON_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, ENTR_GORON_CITY_OUTSIDE_SHOP } },
|
||||
{ { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, ENTR_ZORA_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP } },
|
||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE },
|
||||
{ EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, ENTR_STABLE_0 },
|
||||
{ EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_STABLES } },
|
||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, ENTR_LON_LON_BUILDINGS_TOWER },
|
||||
{ EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TOWER } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, ENTR_BAZAAR_1 },
|
||||
{ EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BAZAAR } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1 },
|
||||
{ EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, ENTR_BAZAAR_0 },
|
||||
{ EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0 },
|
||||
{ EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY } },
|
||||
{ { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS },
|
||||
{ EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC },
|
||||
{ EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD },
|
||||
// 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy
|
||||
// fountain exits (normally they both use 0x340)
|
||||
{ EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_POTION_SHOP_KAKARIKO_1 } },
|
||||
{ { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC },
|
||||
{ EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT },
|
||||
{ EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF },
|
||||
{ EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY } },
|
||||
|
||||
{ { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 },
|
||||
{ EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } },
|
||||
{ { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_ENTRANCE },
|
||||
{ EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL },
|
||||
{ EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL } },
|
||||
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT },
|
||||
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT } },
|
||||
{ { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK },
|
||||
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK } },
|
||||
|
||||
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
|
||||
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
||||
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
|
||||
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
||||
{ { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN_ISLAND, RR_ZD_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN_ISLAND, ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET) } },
|
||||
|
||||
// Graves have their own specified entrance indices
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0 },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, ENTR_REDEAD_GRAVE_0 },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, ENTR_ROYAL_FAMILYS_TOMB_0 },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT } },
|
||||
|
||||
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_LOWER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_UPPER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, ENTR_GORON_CITY_TUNNEL_SHORTCUT },
|
||||
{ EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_TUNNEL_SHORTCUT } },
|
||||
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZORAS_RIVER, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT },
|
||||
{ EntranceType::Overworld, RR_ZORAS_RIVER, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT } },
|
||||
{ { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, ENTR_LOST_WOODS_NORTH_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_WOODED_EXIT },
|
||||
{ EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_FENCE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, ENTR_GERUDO_VALLEY_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ROCKY_PATH } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT },
|
||||
{ EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_FRONT_GATE },
|
||||
{ EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_STAIRS_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, ENTR_ZORAS_RIVER_WEST_EXIT },
|
||||
{ EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_RIVER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_ENTRANCE },
|
||||
{ EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_CENTER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_LAKE_HYLIA, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT },
|
||||
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT } },
|
||||
{ { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_WEST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, ENTR_HAUNTED_WASTELAND_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, ENTR_GERUDOS_FORTRESS_GATE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, ENTR_HAUNTED_WASTELAND_WEST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NORTH_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, ENTR_MARKET_DAY_CASTLE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT },
|
||||
{ EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_DAY_TEMPLE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ENTRANCE },
|
||||
{ EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT },
|
||||
{ EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, ENTR_KAKARIKO_VILLAGE_GUARD_GATE } },
|
||||
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, ENTR_GORON_CITY_UPPER_EXIT },
|
||||
{ EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT },
|
||||
{ EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT },
|
||||
{ EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_ENTRANCE },
|
||||
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, ENTR_ZORAS_RIVER_WATERFALL_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT },
|
||||
{ EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT } },
|
||||
|
||||
{ { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_RIVER_EXIT },
|
||||
NO_RETURN_ENTRANCE },
|
||||
|
||||
{ { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_OWL_DROP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, ENTR_KAKARIKO_VILLAGE_OWL_DROP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
|
||||
{ { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_CHILD_SPAWN },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, ENTR_HYRULE_FIELD_10 },
|
||||
NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between
|
||||
// Adult Spawn and prelude of light (normally they both use 0x5F4)
|
||||
{ { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
|
||||
{ { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, ENTR_DEKU_TREE_BOSS_ENTRANCE },
|
||||
{ EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT, ENTR_DEKU_TREE_BOSS_DOOR } },
|
||||
{ { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE },
|
||||
{ EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT, ENTR_DODONGOS_CAVERN_BOSS_DOOR } },
|
||||
{ { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, ENTR_JABU_JABU_BOSS_ENTRANCE },
|
||||
{ EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT, ENTR_JABU_JABU_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, ENTR_FOREST_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, ENTR_FIRE_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, ENTR_WATER_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, ENTR_WATER_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, ENTR_SPIRIT_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, ENTR_SHADOW_TEMPLE_BOSS_DOOR } },
|
||||
|
||||
{ { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (auto& entrancePair : entranceShuffleTable) {
|
||||
|
||||
|
@ -262,6 +574,7 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
|||
forwardEntrance->SetIndex(forwardEntry.index);
|
||||
forwardEntrance->SetType(forwardEntry.type);
|
||||
forwardEntrance->SetAsPrimary();
|
||||
entranceMap[forwardEntry.index] = forwardEntrance;
|
||||
|
||||
// When decouple entrances is on, mark the forward entrance
|
||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
|
@ -273,6 +586,7 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
|||
returnEntrance->SetIndex(returnEntry.index);
|
||||
returnEntrance->SetType(returnEntry.type);
|
||||
forwardEntrance->BindTwoWay(returnEntrance);
|
||||
entranceMap[returnEntry.index] = returnEntrance;
|
||||
|
||||
// Mark reverse entrance as decoupled
|
||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
|
@ -857,316 +1171,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
|||
mTotalRandomizableEntrances = 0;
|
||||
mCurNumRandomizedEntrances = 0;
|
||||
|
||||
std::vector<EntranceInfoPair> entranceShuffleTable = {
|
||||
// clang-format off
|
||||
// Type Parent Region Connected Region Index
|
||||
{ { EntranceType::Dungeon, RR_KF_OUTSIDE_DEKU_TREE, RR_DEKU_TREE_ENTRYWAY, ENTR_DEKU_TREE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE } },
|
||||
{ { EntranceType::Dungeon, RR_DEATH_MOUNTAIN_TRAIL, RR_DODONGOS_CAVERN_ENTRYWAY, ENTR_DODONGOS_CAVERN_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN } },
|
||||
{ { EntranceType::Dungeon, RR_ZORAS_FOUNTAIN, RR_JABU_JABUS_BELLY_ENTRYWAY, ENTR_JABU_JABU_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU } },
|
||||
{ { EntranceType::Dungeon, RR_SACRED_FOREST_MEADOW, RR_FOREST_TEMPLE_ENTRYWAY, ENTR_FOREST_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_DMC_CENTRAL_LOCAL, RR_FIRE_TEMPLE_ENTRYWAY, ENTR_FIRE_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_FIRE_TEMPLE_ENTRYWAY, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_LAKE_HYLIA, RR_WATER_TEMPLE_ENTRYWAY, ENTR_WATER_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_WATER_TEMPLE_ENTRYWAY, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_DESERT_COLOSSUS, RR_SPIRIT_TEMPLE_ENTRYWAY, ENTR_SPIRIT_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_GRAVEYARD_WARP_PAD_REGION, RR_SHADOW_TEMPLE_ENTRYWAY, ENTR_SHADOW_TEMPLE_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::Dungeon, RR_KAK_WELL, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, ENTR_BOTTOM_OF_THE_WELL_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_BOTTOM_OF_THE_WELL_ENTRYWAY, RR_KAK_WELL, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BOTTOM_OF_THE_WELL } },
|
||||
{ { EntranceType::Dungeon, RR_ZF_LEDGE, RR_ICE_CAVERN_ENTRYWAY, ENTR_ICE_CAVERN_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_ICE_CAVERN_ENTRYWAY, RR_ZF_LEDGE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_ICE_CAVERN } },
|
||||
{ { EntranceType::Dungeon, RR_GERUDO_FORTRESS, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, ENTR_GERUDO_TRAINING_GROUND_ENTRANCE },
|
||||
{ EntranceType::Dungeon, RR_GERUDO_TRAINING_GROUND_ENTRYWAY, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_OUTSIDE_GERUDO_TRAINING_GROUND } },
|
||||
{ { EntranceType::GanonDungeon, RR_GANONS_CASTLE_LEDGE, RR_GANONS_CASTLE_ENTRYWAY, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE },
|
||||
{ EntranceType::GanonDungeon, RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT } },
|
||||
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_MIDOS_HOUSE, ENTR_MIDOS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_MIDOS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_MIDOS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_SARIAS_HOUSE, ENTR_SARIAS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_SARIAS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SARIAS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_HOUSE_OF_TWINS, ENTR_TWINS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_HOUSE_OF_TWINS, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_TWINS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KNOW_IT_ALL_HOUSE, ENTR_KNOW_IT_ALL_BROS_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KF_KNOW_IT_ALL_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_KNOW_IT_ALL_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KOKIRI_FOREST, RR_KF_KOKIRI_SHOP, ENTR_KOKIRI_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_KF_KOKIRI_SHOP, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_SHOP } },
|
||||
{ { EntranceType::Interior, RR_LAKE_HYLIA, RR_LH_LAB, ENTR_LAKESIDE_LABORATORY_0 },
|
||||
{ EntranceType::Interior, RR_LH_LAB, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_OUTSIDE_LAB } },
|
||||
{ { EntranceType::Interior, RR_LH_FISHING_ISLAND, RR_LH_FISHING_POND, ENTR_FISHING_POND_0 },
|
||||
{ EntranceType::Interior, RR_LH_FISHING_POND, RR_LH_FISHING_ISLAND, ENTR_LAKE_HYLIA_OUTSIDE_FISHING_POND } },
|
||||
{ { EntranceType::Interior, RR_GV_FORTRESS_SIDE, RR_GV_CARPENTER_TENT, ENTR_CARPENTERS_TENT_0 },
|
||||
{ EntranceType::Interior, RR_GV_CARPENTER_TENT, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_OUTSIDE_TENT } },
|
||||
{ { EntranceType::Interior, RR_MARKET_ENTRANCE, RR_MARKET_GUARD_HOUSE, ENTR_MARKET_GUARD_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_GUARD_HOUSE, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_OUTSIDE_GUARD_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_MASK_SHOP, ENTR_HAPPY_MASK_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_MASK_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_HAPPY_MASK_SHOP } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BOMBCHU_BOWLING, ENTR_BOMBCHU_BOWLING_ALLEY_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_BOMBCHU_BOWLING, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BOMBCHU_BOWLING } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_POTION_SHOP, ENTR_POTION_SHOP_MARKET_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_POTION_SHOP, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_POTION_SHOP } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_TREASURE_CHEST_GAME, ENTR_TREASURE_BOX_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_MARKET_TREASURE_CHEST_GAME, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_TREASURE_BOX_SHOP } },
|
||||
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_BOMBCHU_SHOP, ENTR_BOMBCHU_SHOP_1 },
|
||||
{ EntranceType::Interior, RR_MARKET_BOMBCHU_SHOP, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_BOMBCHU_SHOP } },
|
||||
{ { EntranceType::Interior, RR_MARKET_BACK_ALLEY, RR_MARKET_MAN_IN_GREEN_HOUSE, ENTR_BACK_ALLEY_MAN_IN_GREEN_HOUSE },
|
||||
{ EntranceType::Interior, RR_MARKET_MAN_IN_GREEN_HOUSE, RR_MARKET_BACK_ALLEY, ENTR_BACK_ALLEY_DAY_OUTSIDE_MAN_IN_GREEN_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_CARPENTER_BOSS_HOUSE, ENTR_KAKARIKO_CENTER_GUEST_HOUSE_0 },
|
||||
{ EntranceType::Interior, RR_KAK_CARPENTER_BOSS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_CENTER_GUEST_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_HOUSE_OF_SKULLTULA, ENTR_HOUSE_OF_SKULLTULA_0 },
|
||||
{ EntranceType::Interior, RR_KAK_HOUSE_OF_SKULLTULA, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SKULKLTULA_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_IMPAS_HOUSE, ENTR_IMPAS_HOUSE_FRONT },
|
||||
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_FRONT } },
|
||||
{ { EntranceType::Interior, RR_KAK_IMPAS_LEDGE, RR_KAK_IMPAS_HOUSE_BACK, ENTR_IMPAS_HOUSE_BACK },
|
||||
{ EntranceType::Interior, RR_KAK_IMPAS_HOUSE_BACK, RR_KAK_IMPAS_LEDGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_IMPAS_HOUSE_BACK } },
|
||||
{ { EntranceType::Interior, RR_KAK_BACKYARD, RR_KAK_ODD_POTION_BUILDING, ENTR_POTION_SHOP_GRANNY_0 },
|
||||
{ EntranceType::Interior, RR_KAK_ODD_POTION_BUILDING, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOP_GRANNY } },
|
||||
{ { EntranceType::Interior, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_HOUSE, ENTR_GRAVEKEEPERS_HUT_0 },
|
||||
{ EntranceType::Interior, RR_GRAVEYARD_DAMPES_HOUSE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_OUTSIDE_DAMPES_HUT } },
|
||||
{ { EntranceType::Interior, RR_GORON_CITY, RR_GC_SHOP, ENTR_GORON_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_GC_SHOP, RR_GORON_CITY, ENTR_GORON_CITY_OUTSIDE_SHOP } },
|
||||
{ { EntranceType::Interior, RR_ZORAS_DOMAIN, RR_ZD_SHOP, ENTR_ZORA_SHOP_0 },
|
||||
{ EntranceType::Interior, RR_ZD_SHOP, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_OUTSIDE_SHOP } },
|
||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TALONS_HOUSE, ENTR_LON_LON_BUILDINGS_TALONS_HOUSE },
|
||||
{ EntranceType::Interior, RR_LLR_TALONS_HOUSE, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TALONS_HOUSE } },
|
||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_STABLES, ENTR_STABLE_0 },
|
||||
{ EntranceType::Interior, RR_LLR_STABLES, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_STABLES } },
|
||||
{ { EntranceType::Interior, RR_LON_LON_RANCH, RR_LLR_TOWER, ENTR_LON_LON_BUILDINGS_TOWER },
|
||||
{ EntranceType::Interior, RR_LLR_TOWER, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_OUTSIDE_TOWER } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_BAZAAR, ENTR_BAZAAR_1 },
|
||||
{ EntranceType::Interior, RR_MARKET_BAZAAR, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_BAZAAR } },
|
||||
{ { EntranceType::Interior, RR_THE_MARKET, RR_MARKET_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_1 },
|
||||
{ EntranceType::Interior, RR_MARKET_SHOOTING_GALLERY, RR_THE_MARKET, ENTR_MARKET_DAY_OUTSIDE_SHOOTING_GALLERY } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_BAZAAR, ENTR_BAZAAR_0 },
|
||||
{ EntranceType::Interior, RR_KAK_BAZAAR, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_BAZAAR } },
|
||||
{ { EntranceType::Interior, RR_KAKARIKO_VILLAGE, RR_KAK_SHOOTING_GALLERY, ENTR_SHOOTING_GALLERY_0 },
|
||||
{ EntranceType::Interior, RR_KAK_SHOOTING_GALLERY, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_SHOOTING_GALLERY } },
|
||||
{ { EntranceType::Interior, RR_DESERT_COLOSSUS, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_NAYRUS_COLOSSUS },
|
||||
{ EntranceType::Interior, RR_COLOSSUS_GREAT_FAIRY_FOUNTAIN, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_HYRULE_CASTLE_GROUNDS, RR_HC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_DINS_HC },
|
||||
{ EntranceType::Interior, RR_HC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_GANONS_CASTLE_GROUNDS, RR_OGC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD },
|
||||
// 0x3E8 is an unused entrance index repruposed to differentiate between the HC and OGC fairy
|
||||
// fountain exits (normally they both use 0x340)
|
||||
{ EntranceType::Interior, RR_OGC_GREAT_FAIRY_FOUNTAIN, RR_CASTLE_GROUNDS, ENTR_POTION_SHOP_KAKARIKO_1 } },
|
||||
{ { EntranceType::Interior, RR_DMC_LOWER_NEARBY, RR_DMC_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMC },
|
||||
{ EntranceType::Interior, RR_DMC_GREAT_FAIRY_FOUNTAIN, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_DMT },
|
||||
{ EntranceType::Interior, RR_DMT_GREAT_FAIRY_FOUNTAIN, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_GREAT_FAIRY_EXIT } },
|
||||
{ { EntranceType::Interior, RR_ZORAS_FOUNTAIN, RR_ZF_GREAT_FAIRY_FOUNTAIN, ENTR_GREAT_FAIRYS_FOUNTAIN_SPELLS_FARORES_ZF },
|
||||
{ EntranceType::Interior, RR_ZF_GREAT_FAIRY_FOUNTAIN, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_OUTSIDE_GREAT_FAIRY } },
|
||||
|
||||
{ { EntranceType::SpecialInterior, RR_KOKIRI_FOREST, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_1 },
|
||||
{ EntranceType::SpecialInterior, RR_KF_LINKS_HOUSE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_OUTSIDE_LINKS_HOUSE } },
|
||||
{ { EntranceType::SpecialInterior, RR_TOT_ENTRANCE, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_ENTRANCE },
|
||||
{ EntranceType::SpecialInterior, RR_TEMPLE_OF_TIME, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_OUTSIDE_TEMPLE } },
|
||||
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_WINDMILL, ENTR_WINDMILL_AND_DAMPES_GRAVE_WINDMILL },
|
||||
{ EntranceType::SpecialInterior, RR_KAK_WINDMILL, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_WINDMILL } },
|
||||
{ { EntranceType::SpecialInterior, RR_KAKARIKO_VILLAGE, RR_KAK_POTION_SHOP_FRONT, ENTR_POTION_SHOP_KAKARIKO_FRONT },
|
||||
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_FRONT, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_FRONT } },
|
||||
{ { EntranceType::SpecialInterior, RR_KAK_BACKYARD, RR_KAK_POTION_SHOP_BACK, ENTR_POTION_SHOP_KAKARIKO_BACK },
|
||||
{ EntranceType::SpecialInterior, RR_KAK_POTION_SHOP_BACK, RR_KAK_BACKYARD, ENTR_KAKARIKO_VILLAGE_OUTSIDE_POTION_SHOP_BACK } },
|
||||
|
||||
// Grotto Loads use an entrance index of 0x0700 + their grotto id. The id is used as index for the
|
||||
// grottoLoadTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
||||
// Grotto Returns use an entrance index of 0x0800 + their grotto id. The id is used as index for the
|
||||
// grottoReturnTable in soh/soh/Enhancements/randomizer/randomizer_grotto.c
|
||||
{ { EntranceType::GrottoGrave, RR_DESERT_COLOSSUS, RR_COLOSSUS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_COLOSSUS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_COLOSSUS_GROTTO, RR_DESERT_COLOSSUS, ENTRANCE_GROTTO_EXIT(GROTTO_COLOSSUS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LAKE_HYLIA, RR_LH_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LH_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LH_GROTTO, RR_LAKE_HYLIA, ENTRANCE_GROTTO_EXIT(GROTTO_LH_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZR_STORMS_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_FAIRY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZR_FAIRY_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_FAIRY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_RIVER, RR_ZR_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZR_OPEN_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZR_OPEN_GROTTO, RR_ZORAS_RIVER, ENTRANCE_GROTTO_EXIT(GROTTO_ZR_OPEN_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DMC_LOWER_NEARBY, RR_DMC_HAMMER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_HAMMER_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMC_HAMMER_GROTTO, RR_DMC_LOWER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_HAMMER_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DMC_UPPER_NEARBY, RR_DMC_UPPER_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMC_UPPER_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMC_UPPER_GROTTO, RR_DMC_UPPER_LOCAL, ENTRANCE_GROTTO_EXIT(GROTTO_DMC_UPPER_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GC_GROTTO_PLATFORM, RR_GC_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GORON_CITY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GC_GROTTO, RR_GC_GROTTO_PLATFORM, ENTRANCE_GROTTO_EXIT(GROTTO_GORON_CITY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_TRAIL, RR_DMT_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMT_STORMS_GROTTO, RR_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMT_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_DMT_COW_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DMT_COW_GROTTO, RR_DEATH_MOUNTAIN_SUMMIT, ENTRANCE_GROTTO_EXIT(GROTTO_DMT_COW_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_KAK_BACKYARD, RR_KAK_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_OPEN_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_KAK_OPEN_GROTTO, RR_KAK_BACKYARD, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_OPEN_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_KAKARIKO_VILLAGE, RR_KAK_REDEAD_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KAK_REDEAD_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_KAK_REDEAD_GROTTO, RR_KAKARIKO_VILLAGE, ENTRANCE_GROTTO_EXIT(GROTTO_KAK_REDEAD_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_CASTLE_GROUNDS, RR_HC_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HC_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HC_STORMS_GROTTO, RR_CASTLE_GROUNDS, ENTRANCE_GROTTO_EXIT(GROTTO_HC_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_TEKTITE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_TEKTITE_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_TEKTITE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_TEKTITE_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_KAK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_KAK_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_NEAR_KAK_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_KAK_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_FAIRY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_FAIRY_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_FAIRY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_NEAR_MARKET_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_NEAR_MARKET_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_NEAR_MARKET_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_NEAR_MARKET_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_COW_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_COW_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_COW_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_COW_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_INSIDE_FENCE_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_INSIDE_FENCE_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_INSIDE_FENCE_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_INSIDE_FENCE_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_OPEN_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_OPEN_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_OPEN_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_OPEN_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_HYRULE_FIELD, RR_HF_SOUTHEAST_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_HF_SOUTHEAST_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_HF_SOUTHEAST_GROTTO, RR_HYRULE_FIELD, ENTRANCE_GROTTO_EXIT(GROTTO_HF_SOUTHEAST_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LON_LON_RANCH, RR_LLR_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LLR_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LLR_GROTTO, RR_LON_LON_RANCH, ENTRANCE_GROTTO_EXIT(GROTTO_LLR_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_SFM_ENTRYWAY, RR_SFM_WOLFOS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_WOLFOS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_SFM_WOLFOS_GROTTO, RR_SFM_ENTRYWAY, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_WOLFOS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_SFM_STORMS_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_SACRED_FOREST_MEADOW, RR_SFM_FAIRY_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_SFM_FAIRY_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_SFM_FAIRY_GROTTO, RR_SACRED_FOREST_MEADOW, ENTRANCE_GROTTO_EXIT(GROTTO_SFM_FAIRY_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_LW_SCRUBS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_SCRUBS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LW_SCRUBS_GROTTO, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_SCRUBS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_LOST_WOODS, RR_LW_NEAR_SHORTCUTS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_LW_NEAR_SHORTCUTS_GROTTO, RR_THE_LOST_WOODS, ENTRANCE_GROTTO_EXIT(GROTTO_LW_NEAR_SHORTCUTS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_KOKIRI_FOREST, RR_KF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_KF_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_KF_STORMS_GROTTO, RR_KOKIRI_FOREST, ENTRANCE_GROTTO_EXIT(GROTTO_KF_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_ZORAS_DOMAIN_ISLAND, RR_ZD_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_ZD_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_ZD_STORMS_GROTTO, RR_ZORAS_DOMAIN_ISLAND, ENTRANCE_GROTTO_EXIT(GROTTO_ZD_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GERUDO_FORTRESS, RR_GF_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GF_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GF_STORMS_GROTTO, RR_GERUDO_FORTRESS, ENTRANCE_GROTTO_EXIT(GROTTO_GF_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GV_FORTRESS_SIDE, RR_GV_STORMS_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_STORMS_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GV_STORMS_GROTTO, RR_GV_FORTRESS_SIDE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_STORMS_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_GV_GROTTO_LEDGE, RR_GV_OCTOROK_GROTTO, ENTRANCE_GROTTO_LOAD(GROTTO_GV_OCTOROK_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_GV_OCTOROK_GROTTO, RR_GV_GROTTO_LEDGE, ENTRANCE_GROTTO_EXIT(GROTTO_GV_OCTOROK_OFFSET) } },
|
||||
{ { EntranceType::GrottoGrave, RR_LW_BEYOND_MIDO, RR_DEKU_THEATER, ENTRANCE_GROTTO_LOAD(GROTTO_LW_DEKU_THEATRE_OFFSET) },
|
||||
{ EntranceType::GrottoGrave, RR_DEKU_THEATER, RR_LW_BEYOND_MIDO, ENTRANCE_GROTTO_EXIT(GROTTO_LW_DEKU_THEATRE_OFFSET) } },
|
||||
|
||||
// Graves have their own specified entrance indices
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_SHIELD_GRAVE, ENTR_GRAVE_WITH_FAIRYS_FOUNTAIN_0 },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_SHIELD_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_SHIELD_GRAVE_EXIT } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_HEART_PIECE_GRAVE, ENTR_REDEAD_GRAVE_0 },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_HEART_PIECE_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_HEART_PIECE_GRAVE_EXIT } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_COMPOSERS_GRAVE, ENTR_ROYAL_FAMILYS_TOMB_0 },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_COMPOSERS_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ROYAL_TOMB_EXIT } },
|
||||
{ { EntranceType::GrottoGrave, RR_THE_GRAVEYARD, RR_GRAVEYARD_DAMPES_GRAVE, ENTR_WINDMILL_AND_DAMPES_GRAVE_GRAVE },
|
||||
{ EntranceType::GrottoGrave, RR_GRAVEYARD_DAMPES_GRAVE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_DAMPES_GRAVE_EXIT } },
|
||||
|
||||
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_LW_BRIDGE_FROM_FOREST, ENTR_LOST_WOODS_BRIDGE_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_LW_BRIDGE, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_LOWER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_KOKIRI_FOREST, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_LW_FOREST_EXIT, RR_KOKIRI_FOREST, ENTR_KOKIRI_FOREST_UPPER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_GC_WOODS_WARP, ENTR_GORON_CITY_TUNNEL_SHORTCUT },
|
||||
{ EntranceType::Overworld, RR_GC_WOODS_WARP, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_TUNNEL_SHORTCUT } },
|
||||
{ { EntranceType::Overworld, RR_THE_LOST_WOODS, RR_ZORAS_RIVER, ENTR_ZORAS_RIVER_UNDERWATER_SHORTCUT },
|
||||
{ EntranceType::Overworld, RR_ZORAS_RIVER, RR_THE_LOST_WOODS, ENTR_LOST_WOODS_UNDERWATER_SHORTCUT } },
|
||||
{ { EntranceType::Overworld, RR_LW_BEYOND_MIDO, RR_SFM_ENTRYWAY, ENTR_SACRED_FOREST_MEADOW_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_SFM_ENTRYWAY, RR_LW_BEYOND_MIDO, ENTR_LOST_WOODS_NORTH_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_LW_BRIDGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_WOODED_EXIT },
|
||||
{ EntranceType::Overworld, RR_HYRULE_FIELD, RR_LW_BRIDGE, ENTR_LOST_WOODS_BRIDGE_WEST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_NORTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_LAKE_HYLIA, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_FENCE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_GERUDO_VALLEY, ENTR_GERUDO_VALLEY_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_GERUDO_VALLEY, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ROCKY_PATH } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NEAR_GUARD_EXIT },
|
||||
{ EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_ON_BRIDGE_SPAWN } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_FRONT_GATE },
|
||||
{ EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_STAIRS_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_ZR_FRONT, ENTR_ZORAS_RIVER_WEST_EXIT },
|
||||
{ EntranceType::Overworld, RR_ZR_FRONT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_RIVER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_HYRULE_FIELD, RR_LON_LON_RANCH, ENTR_LON_LON_RANCH_ENTRANCE },
|
||||
{ EntranceType::Overworld, RR_LON_LON_RANCH, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_CENTER_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_LAKE_HYLIA, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_UNDERWATER_SHORTCUT },
|
||||
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_UNDERWATER_SHORTCUT } },
|
||||
{ { EntranceType::Overworld, RR_GV_FORTRESS_SIDE, RR_GERUDO_FORTRESS, ENTR_GERUDOS_FORTRESS_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_GERUDO_FORTRESS, RR_GV_FORTRESS_SIDE, ENTR_GERUDO_VALLEY_WEST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_GF_OUTSIDE_GATE, RR_WASTELAND_NEAR_FORTRESS, ENTR_HAUNTED_WASTELAND_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_WASTELAND_NEAR_FORTRESS, RR_GF_OUTSIDE_GATE, ENTR_GERUDOS_FORTRESS_GATE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_WASTELAND_NEAR_COLOSSUS, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_EAST_EXIT },
|
||||
{ EntranceType::Overworld, RR_DESERT_COLOSSUS, RR_WASTELAND_NEAR_COLOSSUS, ENTR_HAUNTED_WASTELAND_WEST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_MARKET_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_THE_MARKET, RR_MARKET_ENTRANCE, ENTR_MARKET_ENTRANCE_NORTH_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_THE_MARKET, RR_CASTLE_GROUNDS, ENTR_CASTLE_GROUNDS_SOUTH_EXIT },
|
||||
{ EntranceType::Overworld, RR_CASTLE_GROUNDS, RR_THE_MARKET, ENTR_MARKET_DAY_CASTLE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_THE_MARKET, RR_TOT_ENTRANCE, ENTR_TEMPLE_OF_TIME_EXTERIOR_DAY_GOSSIP_STONE_EXIT },
|
||||
{ EntranceType::Overworld, RR_TOT_ENTRANCE, RR_THE_MARKET, ENTR_MARKET_DAY_TEMPLE_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_KAKARIKO_VILLAGE, RR_THE_GRAVEYARD, ENTR_GRAVEYARD_ENTRANCE },
|
||||
{ EntranceType::Overworld, RR_THE_GRAVEYARD, RR_KAKARIKO_VILLAGE, ENTR_KAKARIKO_VILLAGE_SOUTHEAST_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_KAK_BEHIND_GATE, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_BOTTOM_EXIT },
|
||||
{ EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_KAK_BEHIND_GATE, ENTR_KAKARIKO_VILLAGE_GUARD_GATE } },
|
||||
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_TRAIL, RR_GORON_CITY, ENTR_GORON_CITY_UPPER_EXIT },
|
||||
{ EntranceType::Overworld, RR_GORON_CITY, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_GC_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_GC_DARUNIAS_CHAMBER, RR_DMC_LOWER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_GC_EXIT },
|
||||
{ EntranceType::Overworld, RR_DMC_LOWER_NEARBY, RR_GC_DARUNIAS_CHAMBER, ENTR_GORON_CITY_DARUNIA_ROOM_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_DEATH_MOUNTAIN_SUMMIT, RR_DMC_UPPER_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_UPPER_EXIT },
|
||||
{ EntranceType::Overworld, RR_DMC_UPPER_NEARBY, RR_DEATH_MOUNTAIN_SUMMIT, ENTR_DEATH_MOUNTAIN_TRAIL_SUMMIT_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_ZR_BEHIND_WATERFALL, RR_ZORAS_DOMAIN, ENTR_ZORAS_DOMAIN_ENTRANCE },
|
||||
{ EntranceType::Overworld, RR_ZORAS_DOMAIN, RR_ZR_BEHIND_WATERFALL, ENTR_ZORAS_RIVER_WATERFALL_EXIT } },
|
||||
{ { EntranceType::Overworld, RR_ZD_BEHIND_KING_ZORA, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_TUNNEL_EXIT },
|
||||
{ EntranceType::Overworld, RR_ZORAS_FOUNTAIN, RR_ZD_BEHIND_KING_ZORA, ENTR_ZORAS_DOMAIN_KING_ZORA_EXIT } },
|
||||
|
||||
{ { EntranceType::Overworld, RR_GV_LOWER_STREAM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_RIVER_EXIT },
|
||||
NO_RETURN_ENTRANCE },
|
||||
|
||||
{ { EntranceType::OwlDrop, RR_LH_OWL_FLIGHT, RR_HYRULE_FIELD, ENTR_HYRULE_FIELD_OWL_DROP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::OwlDrop, RR_DMT_OWL_FLIGHT, RR_KAK_IMPAS_ROOFTOP, ENTR_KAKARIKO_VILLAGE_OWL_DROP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
|
||||
{ { EntranceType::Spawn, RR_CHILD_SPAWN, RR_KF_LINKS_HOUSE, ENTR_LINKS_HOUSE_CHILD_SPAWN },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::Spawn, RR_ADULT_SPAWN, RR_TEMPLE_OF_TIME, ENTR_HYRULE_FIELD_10 },
|
||||
NO_RETURN_ENTRANCE }, // 0x282 is an unused entrance index repurposed to differentiate between
|
||||
// Adult Spawn and prelude of light (normally they both use 0x5F4)
|
||||
{ { EntranceType::WarpSong, RR_MINUET_OF_FOREST_WARP, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_BOLERO_OF_FIRE_WARP, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_SERENADE_OF_WATER_WARP, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_REQUIEM_OF_SPIRIT_WARP, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_NOCTURNE_OF_SHADOW_WARP, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::WarpSong, RR_PRELUDE_OF_LIGHT_WARP, RR_TEMPLE_OF_TIME, ENTR_TEMPLE_OF_TIME_WARP_PAD },
|
||||
NO_RETURN_ENTRANCE },
|
||||
|
||||
{ { EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ENTRYWAY, RR_DEKU_TREE_BOSS_ROOM, ENTR_DEKU_TREE_BOSS_ENTRANCE },
|
||||
{ EntranceType::ChildBoss, RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY, ENTR_DEKU_TREE_BOSS_DOOR } },
|
||||
{ { EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, RR_DODONGOS_CAVERN_BOSS_ROOM, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE },
|
||||
{ EntranceType::ChildBoss, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, ENTR_DODONGOS_CAVERN_BOSS_DOOR } },
|
||||
{ { EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, RR_JABU_JABUS_BELLY_BOSS_ROOM, ENTR_JABU_JABU_BOSS_ENTRANCE },
|
||||
{ EntranceType::ChildBoss, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, ENTR_JABU_JABU_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, RR_FOREST_TEMPLE_BOSS_ROOM, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY, ENTR_FOREST_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, RR_FIRE_TEMPLE_BOSS_ROOM, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_FIRE_TEMPLE_BOSS_ROOM, RR_FIRE_TEMPLE_BOSS_ENTRYWAY, ENTR_FIRE_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ENTRYWAY, RR_WATER_TEMPLE_BOSS_ROOM, ENTR_WATER_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_WATER_TEMPLE_BOSS_ROOM, RR_WATER_TEMPLE_BOSS_ENTRYWAY, ENTR_WATER_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, RR_SPIRIT_TEMPLE_BOSS_ROOM, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, ENTR_SPIRIT_TEMPLE_BOSS_DOOR } },
|
||||
{ { EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, RR_SHADOW_TEMPLE_BOSS_ROOM, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE },
|
||||
{ EntranceType::AdultBoss, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, ENTR_SHADOW_TEMPLE_BOSS_DOOR } },
|
||||
|
||||
{ { EntranceType::BlueWarp, RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL, ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN, ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_WATER_TEMPLE_BOSS_ROOM, RR_LAKE_HYLIA, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
|
||||
{ "Bolero", { { RR_DMC_CENTRAL_LOCAL }, { EntranceType::OwlDrop, EntranceType::WarpSong } } },
|
||||
{ "Nocturne",
|
||||
|
@ -1178,7 +1182,7 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
|||
};
|
||||
|
||||
mEntranceShuffleFailure = false;
|
||||
SetAllEntrancesData(entranceShuffleTable);
|
||||
SetAllEntrancesData();
|
||||
|
||||
EntrancePools oneWayEntrancePools = {};
|
||||
EntrancePools entrancePools = {};
|
||||
|
@ -1488,11 +1492,11 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
|||
if (true /* ctx->GetOption(RSK_SHUFFLE_BLUEWARP_ENTRANCES).Is(RO_BLUEWARP_ENTRANCE_SHUFFLE_DUNGEON) */) {
|
||||
// If a boss room is inside a boss door, make the blue warp go outside the dungeon's entrance
|
||||
std::map<std::string, Entrance*> bossExits = {
|
||||
{ EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY),
|
||||
{ EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT),
|
||||
GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_ENTRYWAY, RR_KF_OUTSIDE_DEKU_TREE)) },
|
||||
{ EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY),
|
||||
{ EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT),
|
||||
GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_ENTRYWAY, RR_DEATH_MOUNTAIN_TRAIL)) },
|
||||
{ EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY),
|
||||
{ EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT),
|
||||
GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_ENTRYWAY, RR_ZORAS_FOUNTAIN)) },
|
||||
{ EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY),
|
||||
GetEntrance(EntranceNameByRegions(RR_FOREST_TEMPLE_ENTRYWAY, RR_SACRED_FOREST_MEADOW)) },
|
||||
|
@ -1530,11 +1534,11 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
|||
// Pair <BlueWarp exit, BossRoom reverse exit>
|
||||
std::vector<EntrancePair> bossRoomExitPairs = {
|
||||
{ GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_KF_OUTSIDE_DEKU_TREE)),
|
||||
GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_ENTRYWAY)) },
|
||||
GetEntrance(EntranceNameByRegions(RR_DEKU_TREE_BOSS_ROOM, RR_DEKU_TREE_BOSS_EXIT)) },
|
||||
{ GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DEATH_MOUNTAIN_TRAIL)),
|
||||
GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_ENTRYWAY)) },
|
||||
GetEntrance(EntranceNameByRegions(RR_DODONGOS_CAVERN_BOSS_ROOM, RR_DODONGOS_CAVERN_BOSS_EXIT)) },
|
||||
{ GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_ZORAS_FOUNTAIN)),
|
||||
GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY)) },
|
||||
GetEntrance(EntranceNameByRegions(RR_JABU_JABUS_BELLY_BOSS_ROOM, RR_JABU_JABUS_BELLY_BOSS_EXIT)) },
|
||||
{ GetEntrance(EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_SACRED_FOREST_MEADOW)),
|
||||
GetEntrance(EntranceNameByRegions(RR_FOREST_TEMPLE_BOSS_ROOM, RR_FOREST_TEMPLE_BOSS_ENTRYWAY)) },
|
||||
{ GetEntrance(EntranceNameByRegions(RR_FIRE_TEMPLE_BOSS_ROOM, RR_DMC_CENTRAL_LOCAL)),
|
||||
|
@ -1662,6 +1666,30 @@ void EntranceShuffler::ParseJson(nlohmann::json spoilerFileJson) {
|
|||
}
|
||||
}
|
||||
} catch (const std::exception& e) { throw e; }
|
||||
// We may need to reset more things here or elsewhere in spoiler loading
|
||||
RegionTable_Init();
|
||||
ApplyEntranceOverrides();
|
||||
SetAreas();
|
||||
}
|
||||
|
||||
void EntranceShuffler::ApplyEntranceOverrides() {
|
||||
SetAllEntrancesData();
|
||||
|
||||
for (size_t i = 0; i < entranceOverrides.size(); i++) {
|
||||
EntranceOverride entranceOverride = entranceOverrides[i];
|
||||
|
||||
if (entranceOverride.index == 0 && entranceOverride.destination == 0 && entranceOverride.override == 0 &&
|
||||
entranceOverride.overrideDestination == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Entrance* entrance = entranceMap[entranceOverride.index];
|
||||
Entrance* overrideEntrance = entranceMap[entranceOverride.override];
|
||||
|
||||
entrance->Disconnect();
|
||||
entrance->Connect(overrideEntrance->GetOriginalConnectedRegionKey());
|
||||
entrance->SetAsShuffled();
|
||||
}
|
||||
}
|
||||
} // namespace Rando
|
||||
|
||||
|
|
|
@ -128,6 +128,7 @@ class EntranceShuffler {
|
|||
void CreateEntranceOverrides();
|
||||
void UnshuffleAllEntrances();
|
||||
void ParseJson(nlohmann::json spoilerFileJson);
|
||||
void ApplyEntranceOverrides();
|
||||
|
||||
private:
|
||||
std::vector<Entrance*> AssumeEntrancePool(std::vector<Entrance*>& entrancePool);
|
||||
|
|
|
@ -46,14 +46,20 @@ Item::~Item() = default;
|
|||
|
||||
void Item::ApplyEffect() const {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true);
|
||||
ctx->GetLogic()->SetInLogic(logicVal, true);
|
||||
auto logic = ctx->GetLogic();
|
||||
if (!logic->CalculatingAvailableChecks) {
|
||||
logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), true);
|
||||
}
|
||||
logic->SetInLogic(logicVal, true);
|
||||
}
|
||||
|
||||
void Item::UndoEffect() const {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
ctx->GetLogic()->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false);
|
||||
ctx->GetLogic()->SetInLogic(logicVal, false);
|
||||
auto logic = ctx->GetLogic();
|
||||
if (!logic->CalculatingAvailableChecks) {
|
||||
logic->ApplyItemEffect(StaticData::RetrieveItem(randomizerGet), false);
|
||||
}
|
||||
logic->SetInLogic(logicVal, false);
|
||||
}
|
||||
|
||||
const Text& Item::GetName() const {
|
||||
|
|
|
@ -10,9 +10,10 @@
|
|||
#include "soh/Enhancements/debugger/performanceTimer.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <soh/OTRGlobals.h>
|
||||
|
||||
#include "3drando/shops.hpp"
|
||||
extern "C" {
|
||||
extern SaveContext gSaveContext;
|
||||
extern PlayState* gPlayState;
|
||||
}
|
||||
|
||||
|
@ -45,17 +46,71 @@ bool LocationAccess::ConditionsMet(Region* parentRegion, bool calculatingAvailab
|
|||
conditionsMet = true;
|
||||
}
|
||||
|
||||
return conditionsMet &&
|
||||
(calculatingAvailableChecks || CanBuy()); // TODO: run CanBuy when price is known due to settings
|
||||
return conditionsMet && CanBuy(calculatingAvailableChecks);
|
||||
}
|
||||
|
||||
bool LocationAccess::CanBuy() const {
|
||||
return CanBuyAnother(location);
|
||||
static uint16_t GetMinimumPrice(const Rando::Location* loc) {
|
||||
extern PriceSettingsStruct shopsanityPrices;
|
||||
extern PriceSettingsStruct scrubPrices;
|
||||
extern PriceSettingsStruct merchantPrices;
|
||||
PriceSettingsStruct priceSettings = loc->GetRCType() == RCTYPE_SHOP ? shopsanityPrices
|
||||
: loc->GetRCType() == RCTYPE_SCRUB ? scrubPrices
|
||||
: merchantPrices;
|
||||
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
switch (ctx->GetOption(priceSettings.main).Get()) {
|
||||
case RO_PRICE_VANILLA:
|
||||
return loc->GetVanillaPrice();
|
||||
case RO_PRICE_CHEAP_BALANCED:
|
||||
return 0;
|
||||
case RO_PRICE_BALANCED:
|
||||
return 0;
|
||||
case RO_PRICE_FIXED:
|
||||
return ctx->GetOption(priceSettings.fixedPrice).Get() * 5;
|
||||
case RO_PRICE_RANGE: {
|
||||
uint16_t range1 = ctx->GetOption(priceSettings.range1).Get() * 5;
|
||||
uint16_t range2 = ctx->GetOption(priceSettings.range1).Get() * 5;
|
||||
return range1 < range2 ? range1 : range2;
|
||||
}
|
||||
case RO_PRICE_SET_BY_WALLET: {
|
||||
if (ctx->GetOption(priceSettings.noWallet).Get()) {
|
||||
return 0;
|
||||
} else if (ctx->GetOption(priceSettings.childWallet).Get()) {
|
||||
return 1;
|
||||
} else if (ctx->GetOption(priceSettings.adultWallet).Get()) {
|
||||
return 100;
|
||||
} else if (ctx->GetOption(priceSettings.giantWallet).Get()) {
|
||||
return 201;
|
||||
} else {
|
||||
return 501;
|
||||
}
|
||||
}
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool LocationAccess::CanBuy(bool calculatingAvailableChecks) const {
|
||||
const auto& loc = Rando::StaticData::GetLocation(location);
|
||||
const auto& itemLoc = OTRGlobals::Instance->gRandoContext->GetItemLocation(location);
|
||||
|
||||
if (loc->GetRCType() == RCTYPE_SHOP || loc->GetRCType() == RCTYPE_SCRUB || loc->GetRCType() == RCTYPE_MERCHANT) {
|
||||
// Checks should only be identified while playing
|
||||
if (calculatingAvailableChecks && itemLoc->GetCheckStatus() != RCSHOW_IDENTIFIED) {
|
||||
return CanBuyAnother(GetMinimumPrice(loc));
|
||||
} else {
|
||||
return CanBuyAnother(itemLoc->GetPrice());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CanBuyAnother(RandomizerCheck rc) {
|
||||
uint16_t price = ctx->GetItemLocation(rc)->GetPrice();
|
||||
return CanBuyAnother(ctx->GetItemLocation(rc)->GetPrice());
|
||||
}
|
||||
|
||||
bool CanBuyAnother(uint16_t price) {
|
||||
if (price > 500) {
|
||||
return logic->HasItem(RG_TYCOON_WALLET);
|
||||
} else if (price > 200) {
|
||||
|
@ -275,7 +330,7 @@ bool BeanPlanted(const RandomizerRegion region) {
|
|||
if (gPlayState != nullptr && gPlayState->sceneNum == sceneID) {
|
||||
swch = gPlayState->actorCtx.flags.swch;
|
||||
} else if (sceneID != SCENE_ID_MAX) {
|
||||
swch = gSaveContext.sceneFlags[sceneID].swch;
|
||||
swch = Rando::Context::GetInstance()->GetLogic()->GetSaveContext()->sceneFlags[sceneID].swch;
|
||||
} else {
|
||||
swch = 0;
|
||||
}
|
||||
|
|
|
@ -100,9 +100,10 @@ class LocationAccess {
|
|||
std::string condition_str;
|
||||
|
||||
// Makes sure shop locations are buyable
|
||||
bool CanBuy() const;
|
||||
bool CanBuy(bool calculatingAvailableChecks) const;
|
||||
};
|
||||
|
||||
bool CanBuyAnother(uint16_t price);
|
||||
bool CanBuyAnother(RandomizerCheck rc);
|
||||
|
||||
namespace Rando {
|
||||
|
@ -136,7 +137,6 @@ class Region {
|
|||
bool adultDay = false;
|
||||
bool adultNight = false;
|
||||
bool addedToPool = false;
|
||||
;
|
||||
|
||||
void ApplyTimePass();
|
||||
|
||||
|
|
|
@ -25,7 +25,6 @@ void RegionTable_Init_BottomOfTheWell() {
|
|||
}, {
|
||||
//Locations
|
||||
LOCATION(RC_BOTTOM_OF_THE_WELL_FRONT_CENTER_BOMBABLE_CHEST, logic->HasExplosives()),
|
||||
LOCATION(RC_BOTTOM_OF_THE_WELL_FREESTANDING_KEY, (logic->HasItem(RG_BRONZE_SCALE) || logic->LoweredWaterInsideBotw) && logic->CanUse(RG_STICKS) || logic->CanUse(RG_DINS_FIRE)),
|
||||
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_FRONT_CHEST, logic->LoweredWaterInsideBotw),
|
||||
LOCATION(RC_BOTTOM_OF_THE_WELL_UNDERWATER_LEFT_CHEST, logic->LoweredWaterInsideBotw),
|
||||
LOCATION(RC_BOTTOM_OF_THE_WELL_NEAR_ENTRANCE_POT_1, logic->CanBreakPots()),
|
||||
|
|
|
@ -436,11 +436,16 @@ void RegionTable_Init_DekuTree() {
|
|||
#pragma endregion
|
||||
|
||||
// Boss Room
|
||||
// RANDOTODO make it so entrance randomiser can properly handle more than 1 access to that entrance
|
||||
areaTable[RR_DEKU_TREE_BOSS_ENTRYWAY] = Region("Deku Tree Boss Entryway", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_DEKU_TREE_BOSS_ROOM, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_DEKU_TREE_BOSS_EXIT] = Region("Deku Tree Boss Exit", "Deku Tree", {RA_DEKU_TREE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_DEKU_TREE_OUTSIDE_BOSS_ROOM, []{return ctx->GetDungeon(DEKU_TREE)->IsVanilla();}),
|
||||
Entrance(RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM, []{return ctx->GetDungeon(DEKU_TREE)->IsMQ();}),
|
||||
Entrance(RR_DEKU_TREE_BOSS_ROOM, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_DEKU_TREE_BOSS_ROOM] = Region("Deku Tree Boss Room", "Deku Tree", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
@ -460,7 +465,7 @@ void RegionTable_Init_DekuTree() {
|
|||
LOCATION(RC_DEKU_TREE_QUEEN_GOHMA_GRASS_8, logic->CanCutShrubs()),
|
||||
}, {
|
||||
// Exits
|
||||
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, []{return true;}),
|
||||
Entrance(RR_DEKU_TREE_BOSS_EXIT, []{return true;}),
|
||||
Entrance(RR_KF_OUTSIDE_DEKU_TREE, []{return logic->DekuTreeClear;}, false),
|
||||
});
|
||||
|
||||
|
|
|
@ -268,6 +268,7 @@ void RegionTable_Init_DodongosCavern() {
|
|||
LOCATION(RC_DODONGOS_CAVERN_MQ_DEKU_SCRUB_LOBBY_FRONT, logic->CanStunDeku()),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BEGINNING, []{return true;}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_GOSSIP_STONE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->CanBreakMudWalls() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_MOUTH_SIDE_BRIDGE, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_STAIRS_LOWER, []{return Here(RR_DODONGOS_CAVERN_MQ_LOBBY, []{return logic->BlastOrSmash() || logic->HasItem(RG_GORONS_BRACELET);});}),
|
||||
|
@ -386,7 +387,7 @@ void RegionTable_Init_DodongosCavern() {
|
|||
Entrance(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanUse(RG_STICKS) && logic->HasItem(RG_GORONS_BRACELET);}), //Implies access to RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM from here
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM] = Region("Dodongos Cavern MQ Torch Puzzle Lower", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
areaTable[RR_DODONGOS_CAVERN_MQ_BIG_BLOCK_ROOM] = Region("Dodongos Cavern MQ Big Block Room", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_DODONGOS_CAVERN_MQ_BIG_BLOCK_POT_1, logic->CanBreakPots()),
|
||||
LOCATION(RC_DODONGOS_CAVERN_MQ_BIG_BLOCK_POT_2, logic->CanBreakPots()),
|
||||
|
@ -426,7 +427,7 @@ void RegionTable_Init_DodongosCavern() {
|
|||
Entrance(RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM, []{return Here(RR_DODONGOS_CAVERN_MQ_UPPER_LIZALFOS, []{return logic->CanKillEnemy(RE_LIZALFOS);});}),
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM] = Region("Dodongos Cavern MQ Before Upper Lizalfos", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
areaTable[RR_DODONGOS_CAVERN_MQ_TWO_FIRES_ROOM] = Region("Dodongos Cavern MQ Two Fires Room", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_1, logic->CanBreakPots()),
|
||||
LOCATION(RC_DODONGOS_CAVERN_MQ_TWO_FLAMES_POT_2, logic->CanBreakPots()),
|
||||
|
@ -558,11 +559,16 @@ void RegionTable_Init_DodongosCavern() {
|
|||
#pragma endregion
|
||||
|
||||
// Boss Room
|
||||
// RANDOTODO make it so entrance randomiser can properly handle more than 1 access to that entrance
|
||||
areaTable[RR_DODONGOS_CAVERN_BOSS_ENTRYWAY] = Region("Dodongos Cavern Boss Entryway", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_BOSS_EXIT] = Region("Dodongos Cavern Boss Exit", "Dodongos Cavern", {RA_DODONGOS_CAVERN}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_AREA, []{return ctx->GetDungeon(DODONGOS_CAVERN)->IsVanilla();}),
|
||||
Entrance(RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH, []{return ctx->GetDungeon(DODONGOS_CAVERN)->IsMQ();}),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_ROOM, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_DODONGOS_CAVERN_BOSS_ROOM] = Region("Dodongos Cavern Boss Room", "Dodongos Cavern", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
@ -575,7 +581,7 @@ void RegionTable_Init_DodongosCavern() {
|
|||
LOCATION(RC_KING_DODONGO, logic->DodongosCavernClear),
|
||||
}, {
|
||||
// Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, []{return true;}),
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_EXIT, []{return true;}),
|
||||
Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return logic->DodongosCavernClear;}, false),
|
||||
});
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ void RegionTable_Init_FireTemple() {
|
|||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_ENTRYWAY, []{return true;}),
|
||||
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return logic->FireTimer() >= 24;}),
|
||||
Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsKeysanity);}),
|
||||
Entrance(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return Here(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->CanUse(RG_MEGATON_HAMMER);}) && (logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked);}),
|
||||
Entrance(RR_FIRE_TEMPLE_LOOP_EXIT, []{return true;}),
|
||||
Entrance(RR_FIRE_TEMPLE_BIG_LAVA_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 2) && logic->FireTimer() >= 24;}),
|
||||
});
|
||||
|
@ -38,12 +38,12 @@ void RegionTable_Init_FireTemple() {
|
|||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return true;}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY) && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return logic->CanUse(RG_MEGATON_HAMMER);}))) || logic->CanUse(RG_HOVER_BOOTS));}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || Here(RR_FIRE_TEMPLE_FIRE_MAZE_UPPER, []{return logic->CanUse(RG_MEGATON_HAMMER);}) || logic->CanUse(RG_HOVER_BOOTS));}),
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_LOOP_ENEMIES] = Region("Fire Temple Loop Enemies", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsKeysanity;}),
|
||||
Entrance(RR_FIRE_TEMPLE_FIRST_ROOM, []{return logic->SmallKeys(RR_FIRE_TEMPLE, 8) || !logic->IsFireLoopLocked;}),
|
||||
Entrance(RR_FIRE_TEMPLE_LOOP_TILES, []{return Here(RR_FIRE_TEMPLE_LOOP_ENEMIES, []{return logic->CanKillEnemy(RE_TORCH_SLUG) && logic->CanKillEnemy(RE_FIRE_KEESE);});}),
|
||||
});
|
||||
|
||||
|
@ -445,7 +445,7 @@ void RegionTable_Init_FireTemple() {
|
|||
Entrance(RR_FIRE_TEMPLE_MQ_FIRST_ROOM_UPPER, []{return true;}),
|
||||
//Child cannot make it to the north side torches without a hook without specifically bunny hood speed + hover boots
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM_NORTH, []{return logic->FireTimer() > 32 && (logic->CanUse(RG_HOOKSHOT) || (logic->IsAdult && logic->CanUse(RG_HOVER_BOOTS)));}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY) && logic->FireTimer() >= 15 && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->IsAdult && logic->HitFireTemplePlatform) || (logic->HitFireTemplePlatform && logic->CanUse(RG_HOVER_BOOTS)));}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, []{return logic->FireTimer() >= 15 && ((logic->IsAdult && (ctx->GetTrickOption(RT_FIRE_BOSS_DOOR_JUMP) || logic->CanUse(RG_HOVER_BOOTS))) || (logic->IsAdult && logic->HitFireTemplePlatform) || (logic->HitFireTemplePlatform && logic->CanUse(RG_HOVER_BOOTS)));}),
|
||||
});
|
||||
|
||||
//This room assumes tunic logic is handled on entry.
|
||||
|
@ -701,7 +701,7 @@ void RegionTable_Init_FireTemple() {
|
|||
Entrance(RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER] = Region("Fire Temple MQ North Fire Maze", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
areaTable[RR_FIRE_TEMPLE_MQ_UPPER_FLARE_DANCER] = Region("Fire Temple MQ Upper Flare Dancer", "Fire Temple", {RA_FIRE_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_FIRE_TEMPLE_MQ_FREESTANDING_KEY, logic->CanKillEnemy(RE_FLARE_DANCER)),
|
||||
}, {
|
||||
|
@ -740,7 +740,7 @@ void RegionTable_Init_FireTemple() {
|
|||
// Exits
|
||||
Entrance(RR_FIRE_TEMPLE_NEAR_BOSS_ROOM, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsVanilla() && false;}),
|
||||
Entrance(RR_FIRE_TEMPLE_MQ_NEAR_BOSS_ROOM, []{return ctx->GetDungeon(FIRE_TEMPLE)->IsMQ() && false;}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, []{return true;}),
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ROOM, []{return logic->HasItem(RG_FIRE_TEMPLE_BOSS_KEY);}),
|
||||
});
|
||||
|
||||
areaTable[RR_FIRE_TEMPLE_BOSS_ROOM] = Region("Fire Temple Boss Room", "Fire Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
|
|
@ -298,7 +298,7 @@ void RegionTable_Init_ForestTemple() {
|
|||
}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_LOBBY, []{return true;}),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FOREST_TEMPLE_BOSS_KEY);}),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||
});
|
||||
|
||||
#pragma endregion
|
||||
|
@ -481,7 +481,7 @@ void RegionTable_Init_ForestTemple() {
|
|||
Entrance(RR_FOREST_TEMPLE_MQ_FALLING_ROOM, []{return logic->CanUse(RG_SONG_OF_TIME);}),
|
||||
});
|
||||
|
||||
areaTable[RR_FOREST_TEMPLE_MQ_JOELLE_ROOM] = Region("Forest Temple MQ Joelle room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||
areaTable[RR_FOREST_TEMPLE_MQ_JOELLE_ROOM] = Region("Forest Temple MQ Joelle Room", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&logic->ForestTempleJoelle, []{return logic->CanUse(RG_FAIRY_BOW);}),
|
||||
}, {
|
||||
|
@ -593,7 +593,7 @@ void RegionTable_Init_ForestTemple() {
|
|||
areaTable[RR_FOREST_TEMPLE_MQ_BOSS_REGION] = Region("Forest Temple MQ Boss Region", "Forest Temple", {RA_FOREST_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_BASEMENT, []{return logic->ForestOpenBossCorridor;}),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_FOREST_TEMPLE_BOSS_KEY);}),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||
});
|
||||
|
||||
#pragma endregion
|
||||
|
@ -603,7 +603,7 @@ void RegionTable_Init_ForestTemple() {
|
|||
// Exits
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_REGION, []{return ctx->GetDungeon(FOREST_TEMPLE)->IsVanilla() && false;}),
|
||||
Entrance(RR_FOREST_TEMPLE_MQ_BOSS_REGION, []{return ctx->GetDungeon(FOREST_TEMPLE)->IsMQ() && false;}),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ROOM, []{return true;}),
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ROOM, []{return logic->HasItem(RG_FOREST_TEMPLE_BOSS_KEY);}),
|
||||
});
|
||||
|
||||
areaTable[RR_FOREST_TEMPLE_BOSS_ROOM] = Region("Forest Temple Boss Room", "Forest Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
|
|
@ -29,12 +29,7 @@ void RegionTable_Init_GanonsCastle() {
|
|||
Entrance(RR_GANONS_CASTLE_SHADOW_TRIAL, []{return true;}),
|
||||
Entrance(RR_GANONS_CASTLE_SPIRIT_TRIAL, []{return true;}),
|
||||
Entrance(RR_GANONS_CASTLE_LIGHT_TRIAL, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);}),
|
||||
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
|
||||
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
|
||||
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
|
||||
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
|
||||
(logic->SpiritTrialClear || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) &&
|
||||
(logic->LightTrialClear || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}),
|
||||
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return true;}),
|
||||
Entrance(RR_GANONS_CASTLE_DEKU_SCRUBS, []{return ctx->GetTrickOption(RT_LENS_GANON) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||
});
|
||||
|
||||
|
@ -162,13 +157,7 @@ void RegionTable_Init_GanonsCastle() {
|
|||
Entrance(RR_GANONS_CASTLE_MQ_SHADOW_TRIAL_STARTING_LEDGE, []{return true;}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_SPIRIT_TRIAL_CHAIRS_ROOM, []{return true;}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_LIGHT_TRIAL_DINOLFOS_ROOM, []{return Here(RR_GANONS_CASTLE_MQ_MAIN, []{return logic->CanUse(RG_GOLDEN_GAUNTLETS);});}),
|
||||
//RANDOTODO could we just set these events automatically based on the setting?
|
||||
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
|
||||
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
|
||||
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
|
||||
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
|
||||
(logic->SpiritTrialClear || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) &&
|
||||
(logic->LightTrialClear || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}),
|
||||
Entrance(RR_GANONS_TOWER_ENTRYWAY, []{return true;}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_DEKU_SCRUBS, []{return ctx->GetTrickOption(RT_LENS_GANON_MQ) || logic->CanUse(RG_LENS_OF_TRUTH);}),
|
||||
});
|
||||
|
||||
|
@ -436,7 +425,13 @@ void RegionTable_Init_GanonsCastle() {
|
|||
//Exits
|
||||
Entrance(RR_GANONS_CASTLE_LOBBY, []{return ctx->GetDungeon(GANONS_CASTLE)->IsVanilla();}),
|
||||
Entrance(RR_GANONS_CASTLE_MQ_MAIN, []{return ctx->GetDungeon(GANONS_CASTLE)->IsMQ();}),
|
||||
Entrance(RR_GANONS_TOWER_FLOOR_1, []{return true;}),
|
||||
//RANDOTODO could we just set these events automatically based on the setting?
|
||||
Entrance(RR_GANONS_TOWER_FLOOR_1, []{return (logic->ForestTrialClear || ctx->GetTrial(TK_FOREST_TRIAL)->IsSkipped()) &&
|
||||
(logic->FireTrialClear || ctx->GetTrial(TK_FIRE_TRIAL)->IsSkipped()) &&
|
||||
(logic->WaterTrialClear || ctx->GetTrial(TK_WATER_TRIAL)->IsSkipped()) &&
|
||||
(logic->ShadowTrialClear || ctx->GetTrial(TK_SHADOW_TRIAL)->IsSkipped()) &&
|
||||
(logic->SpiritTrialClear || ctx->GetTrial(TK_SPIRIT_TRIAL)->IsSkipped()) &&
|
||||
(logic->LightTrialClear || ctx->GetTrial(TK_LIGHT_TRIAL)->IsSkipped());}),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_TOWER_FLOOR_1] = Region("Ganon's Tower Floor 1", "Ganons Castle", {RA_GANONS_CASTLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
|
|
|
@ -149,7 +149,7 @@ void RegionTable_Init_GerudoTrainingGround() {
|
|||
Entrance(RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER, []{return logic->SmallKeys(RR_GERUDO_TRAINING_GROUND, 3);}),
|
||||
});
|
||||
|
||||
areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER] = Region("Gerudo Training Ground MQ Center", "Gerudo Training Ground", {RA_GERUDO_TRAINING_GROUND}, NO_DAY_NIGHT_CYCLE, {
|
||||
areaTable[RR_GERUDO_TRAINING_GROUND_MQ_MAZE_CENTER] = Region("Gerudo Training Ground MQ Maze Center", "Gerudo Training Ground", {RA_GERUDO_TRAINING_GROUND}, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&logic->MQGTGMazeSwitch, []{return logic->CanUse(RG_MEGATON_HAMMER);}),
|
||||
},
|
||||
|
|
|
@ -84,7 +84,7 @@ void RegionTable_Init_IceCavern() {
|
|||
//Exits
|
||||
//the switch for the glass blocking the entrance is linked to the switch that controls the glass around the skulltulla in RR_ICE_CAVERN_MQ_SCARECROW_ROOM
|
||||
//if you clear the ice, you can hit it with a pot from here.
|
||||
Entrance(RR_ICE_CAVERN_BEGINNING, []{return logic->BlueFire();}),
|
||||
Entrance(RR_ICE_CAVERN_MQ_BEGINNING, []{return logic->BlueFire();}),
|
||||
Entrance(RR_ICE_CAVERN_MQ_MAP_ROOM, []{return Here(RR_ICE_CAVERN_MQ_BEGINNING, []{return logic->CanKillEnemy(RE_WHITE_WOLFOS) && logic->CanKillEnemy(RE_FREEZARD);});}),
|
||||
Entrance(RR_ICE_CAVERN_MQ_COMPASS_ROOM, []{return logic->IsAdult && logic->BlueFire();}),
|
||||
Entrance(RR_ICE_CAVERN_MQ_SCARECROW_ROOM, []{return logic->BlueFire();}),
|
||||
|
|
|
@ -351,10 +351,14 @@ void RegionTable_Init_JabuJabusBelly() {
|
|||
|
||||
// Boss Room
|
||||
areaTable[RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY] = Region("Jabu Jabus Belly Boss Entryway", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_JABU_JABUS_BELLY_BOSS_EXIT] = Region("Jabu Jabus Belly Boss Exit", "Jabu Jabus Belly", {RA_JABU_JABUS_BELLY}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_NEAR_BOSS_ROOM, []{return ctx->GetDungeon(JABU_JABUS_BELLY)->IsVanilla();}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_EAST_ROOM, []{return ctx->GetDungeon(JABU_JABUS_BELLY)->IsMQ();}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_ROOM, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_JABU_JABUS_BELLY_BOSS_ROOM] = Region("Jabu Jabus Belly Boss Room", "Jabu Jabus Belly", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
@ -372,7 +376,7 @@ void RegionTable_Init_JabuJabusBelly() {
|
|||
LOCATION(RC_BARINADE, logic->JabuJabusBellyClear),
|
||||
}, {
|
||||
// Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, []{return false;}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_EXIT, []{return false;}),
|
||||
Entrance(RR_ZORAS_FOUNTAIN, []{return logic->JabuJabusBellyClear;}, false),
|
||||
});
|
||||
|
||||
|
|
|
@ -112,7 +112,7 @@ void RegionTable_Init_ShadowTemple() {
|
|||
LOCATION(RC_SHADOW_TEMPLE_AFTER_SHIP_LOWER_HEART, (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DISTANT_SCARECROW) || (ctx->GetTrickOption(RT_SHADOW_STATUE) && logic->CanUse(RG_BOMBCHU_5))) && logic->CanUse(RG_SONG_OF_TIME) || (logic->CanUse(RG_DISTANT_SCARECROW) && logic->CanUse(RG_HOVER_BOOTS))),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, []{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DISTANT_SCARECROW) || (ctx->GetTrickOption(RT_SHADOW_STATUE) && logic->CanUse(RG_BOMBCHU_5))) && logic->SmallKeys(RR_SHADOW_TEMPLE, 5) && logic->CanUse(RG_HOVER_BOOTS) && logic->HasItem(RG_SHADOW_TEMPLE_BOSS_KEY);})
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, []{return (logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_DISTANT_SCARECROW) || (ctx->GetTrickOption(RT_SHADOW_STATUE) && logic->CanUse(RG_BOMBCHU_5))) && logic->SmallKeys(RR_SHADOW_TEMPLE, 5) && logic->CanUse(RG_HOVER_BOOTS);})
|
||||
});
|
||||
|
||||
#pragma endregion
|
||||
|
@ -370,7 +370,7 @@ void RegionTable_Init_ShadowTemple() {
|
|||
}, {
|
||||
//Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_ACROSS_CHASM, []{return logic->CanUse(RG_HOVER_BOOTS) && (ctx->GetTrickOption(RT_LENS_SHADOW_MQ) || logic->CanUse(RG_LENS_OF_TRUTH));}),
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SHADOW_TEMPLE_BOSS_KEY);}),
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||
});
|
||||
|
||||
//Assumes lens is checked on entry
|
||||
|
@ -403,7 +403,7 @@ void RegionTable_Init_ShadowTemple() {
|
|||
// Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_BEYOND_BOAT, []{return ctx->GetDungeon(SHADOW_TEMPLE)->IsVanilla() && false;}),
|
||||
Entrance(RR_SHADOW_TEMPLE_MQ_BEYOND_BOAT, []{return ctx->GetDungeon(SHADOW_TEMPLE)->IsMQ() && false;}),
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ROOM, []{return true;}),
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ROOM, []{return logic->HasItem(RG_SHADOW_TEMPLE_BOSS_KEY);}),
|
||||
});
|
||||
|
||||
areaTable[RR_SHADOW_TEMPLE_BOSS_ROOM] = Region("Shadow Temple Boss Room", "Shadow Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
|
|
@ -145,7 +145,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
areaTable[RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD] = Region("Spirit Temple Inside Statue Head", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_CENTRAL_CHAMBER, []{return true;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||
});
|
||||
|
||||
#pragma endregion
|
||||
|
@ -194,13 +194,13 @@ void RegionTable_Init_SpiritTemple() {
|
|||
});
|
||||
|
||||
// Room to store the 2 pots in to handle glitch logic going backwards around the loop later
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH] = Region("Spirit Temple MQ Gibdo Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_1F_GIBDO_ROOM_NORTH] = Region("Spirit Temple MQ 1F Gibdo Room North", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_GIBDO_POT_1, logic->CanBreakPots()),
|
||||
LOCATION(RC_SPIRIT_TEMPLE_MQ_CHILD_GIBDO_POT_2, logic->CanBreakPots()),
|
||||
}, {});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM] = Region("Spirit Temple Turntable Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM] = Region("Spirit Temple MQ Turntable Room", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
//For non-fairy pot items, you can also get them with rang without killing the stalfos
|
||||
EventAccess(&logic->FairyPot, []{return Here(RR_SPIRIT_TEMPLE_MQ_TURNTABLE_ROOM, []{return logic->CanKillEnemy(RE_STALFOS);});}),
|
||||
|
@ -315,7 +315,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
Entrance(RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
|
||||
});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE] = Region("Spirit Temple MQ East Iron Knuckle", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
areaTable[RR_SPIRIT_TEMPLE_MQ_WEST_IRON_KNUCKLE] = Region("Spirit Temple MQ West Iron Knuckle", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_SUN_BLOCK_ROOM, []{return logic->SmallKeys(RR_SPIRIT_TEMPLE, 7);}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_SILVER_GAUNTLETS_HAND, []{return logic->CanKillEnemy(RE_IRON_KNUCKLE);}),
|
||||
|
@ -541,7 +541,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
areaTable[RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD] = Region("Spirit Temple MQ Inside Statue Head", "Spirit Temple", {RA_SPIRIT_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
// Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_LOBBY, []{return true;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||
});
|
||||
|
||||
#pragma endregion
|
||||
|
@ -551,7 +551,7 @@ void RegionTable_Init_SpiritTemple() {
|
|||
// Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_INSIDE_STATUE_HEAD, []{return ctx->GetDungeon(SPIRIT_TEMPLE)->IsVanilla() && false;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_MQ_INSIDE_STATUE_HEAD, []{return ctx->GetDungeon(SPIRIT_TEMPLE)->IsMQ() && false;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, []{return true;}),
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, []{return logic->HasItem(RG_SPIRIT_TEMPLE_BOSS_KEY);}),
|
||||
});
|
||||
|
||||
areaTable[RR_SPIRIT_TEMPLE_BOSS_ROOM] = Region("Spirit Temple Boss Room", "Spirit Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
|
|
@ -277,7 +277,7 @@ void RegionTable_Init_WaterTemple() {
|
|||
}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_LOBBY, []{return true;}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_WATER_TEMPLE_BOSS_KEY);}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||
});
|
||||
|
||||
#pragma endregion
|
||||
|
@ -362,10 +362,10 @@ void RegionTable_Init_WaterTemple() {
|
|||
Entrance(RR_WATER_TEMPLE_MQ_BOSS_DOOR, []{return logic->CanUse(RG_LONGSHOT) || logic->CanUse(RG_ICE_ARROWS) || logic->CanUse(RG_NAYRUS_LOVE);}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_MQ_BOSS_DOOR] = Region("Water Temple MQ Main", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
areaTable[RR_WATER_TEMPLE_MQ_BOSS_DOOR] = Region("Water Temple MQ Boss Door", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_MQ_3F_NORTH_LEDGE, []{return logic->CanUse(RG_ICE_ARROWS) || logic->TakeDamage();}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, []{return logic->HasItem(RG_WATER_TEMPLE_BOSS_KEY);}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_MQ_EAST_TOWER] = Region("Water Temple MQ East Tower", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
@ -507,7 +507,7 @@ void RegionTable_Init_WaterTemple() {
|
|||
Entrance(RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_3F, []{return logic->CanUse(RG_LONGSHOT);}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_3F] = Region("Water Temple MQ Behind Blue Switch 2F", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
areaTable[RR_WATER_TEMPLE_MQ_BEHIND_BLUE_SWITCH_3F] = Region("Water Temple MQ Behind Blue Switch 3F", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_WATER_TEMPLE_MQ_GS_BEFORE_UPPER_WATER_SWITCH, logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA)),
|
||||
}, {
|
||||
|
@ -552,7 +552,7 @@ void RegionTable_Init_WaterTemple() {
|
|||
}, {});
|
||||
|
||||
//This room exists to hold the wonderitems that drop from the emblems here. Specifically this assumes you are standing on the final ledge
|
||||
areaTable[RR_WATER_TEMPLE_MQ_WATERFALL] = Region("Water Temple Waterfall", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
areaTable[RR_WATER_TEMPLE_MQ_WATERFALL] = Region("Water Temple MQ Waterfall", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_WATER_TEMPLE_MQ_3F_CENTRAL, []{return logic->SmallKeys(RR_WATER_TEMPLE, 1) && logic->CanUse(RG_LONGSHOT);}),
|
||||
Entrance(RR_WATER_TEMPLE_MQ_STALFOS_PIT, []{return true;}),
|
||||
|
@ -658,7 +658,7 @@ void RegionTable_Init_WaterTemple() {
|
|||
|
||||
areaTable[RR_WATER_TEMPLE_MQ_DRAGON_ROOM_ALCOVE] = Region("Water Temple MQ Dragon Room Alcove", "Water Temple", {RA_WATER_TEMPLE}, NO_DAY_NIGHT_CYCLE, {
|
||||
//Events
|
||||
EventAccess(&logic->MQWaterDragonTorches, []{return true;}),
|
||||
EventAccess(&logic->MQWaterDragonTorches, []{return logic->HasFireSource();}),
|
||||
},
|
||||
{
|
||||
//Locations
|
||||
|
@ -843,7 +843,7 @@ void RegionTable_Init_WaterTemple() {
|
|||
// Exits
|
||||
Entrance(RR_WATER_TEMPLE_PRE_BOSS_ROOM, []{return ctx->GetDungeon(WATER_TEMPLE)->IsVanilla() && false;}),
|
||||
Entrance(RR_WATER_TEMPLE_MQ_BOSS_DOOR, []{return ctx->GetDungeon(WATER_TEMPLE)->IsMQ() && false;}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ROOM, []{return true;}),
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ROOM, []{return logic->HasItem(RG_WATER_TEMPLE_BOSS_KEY);}),
|
||||
});
|
||||
|
||||
areaTable[RR_WATER_TEMPLE_BOSS_ROOM] = Region("Water Temple Boss Room", "Water Temple", {}, NO_DAY_NIGHT_CYCLE, {
|
||||
|
|
|
@ -265,7 +265,7 @@ void RegionTable_Init_Kakariko() {
|
|||
Entrance(RR_DEATH_MOUNTAIN_TRAIL, []{return true;}),
|
||||
});
|
||||
|
||||
areaTable[RR_KAK_WELL] = Region("Kak Behind Gate", "Kakariko Village", {RA_KAKARIKO_VILLAGE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
areaTable[RR_KAK_WELL] = Region("Kak Well", "Kakariko Village", {RA_KAKARIKO_VILLAGE}, NO_DAY_NIGHT_CYCLE, {}, {}, {
|
||||
//Exits
|
||||
Entrance(RR_KAKARIKO_VILLAGE, []{return logic->IsAdult || logic->HasItem(RG_BRONZE_SCALE) || logic->DrainWell;}),
|
||||
Entrance(RR_BOTTOM_OF_THE_WELL_ENTRYWAY, []{return logic->IsChild || (logic->DrainWell && ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES).IsNot(RO_DUNGEON_ENTRANCE_SHUFFLE_OFF));}),
|
||||
|
|
|
@ -105,7 +105,7 @@ void RegionTable_Init_LakeHylia() {
|
|||
|
||||
areaTable[RR_LH_LAB] = Region("LH Lab", "LH Lab", {}, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
//Locations
|
||||
LOCATION(RC_LH_LAB_DIVE, logic->HasItem(RG_GOLDEN_SCALE) || (ctx->GetTrickOption(RT_LH_LAB_DIVING) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT))),
|
||||
LOCATION(RC_LH_LAB_DIVE, logic->HasItem(RG_GOLDEN_SCALE) || (ctx->GetTrickOption(RT_LH_LAB_DIVING) && logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->HasItem(RG_BRONZE_SCALE))),
|
||||
LOCATION(RC_LH_TRADE_FROG, logic->IsAdult && logic->CanUse(RG_EYEBALL_FROG)),
|
||||
LOCATION(RC_LH_GS_LAB_CRATE, logic->CanUse(RG_IRON_BOOTS) && logic->CanUse(RG_HOOKSHOT) && logic->CanBreakCrates()),
|
||||
LOCATION(RC_LH_LAB_FRONT_RUPEE, logic->CanUse(RG_IRON_BOOTS) || logic->HasItem(RG_GOLDEN_SCALE)),
|
||||
|
|
|
@ -1389,6 +1389,7 @@ bool Logic::SmallKeys(RandomizerRegion dungeon, uint8_t requiredAmountGlitchless
|
|||
static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE) || GetDifficultyValueFromString(GlitchHover) >=
|
||||
static_cast<uint8_t>(GlitchDifficulty::INTERMEDIATE))) { return FireTempleKeys >= requiredAmountGlitched;
|
||||
}*/
|
||||
// If the Fire Temple loop lock is removed, Small key Count is set to 1 before starting
|
||||
return GetSmallKeyCount(SCENE_FIRE_TEMPLE) >= requiredAmountGlitchless;
|
||||
|
||||
case RR_WATER_TEMPLE:
|
||||
|
@ -2331,14 +2332,16 @@ void Logic::SetInLogic(LogicVal logicVal, bool value) {
|
|||
inLogic[logicVal] = value;
|
||||
}
|
||||
|
||||
void Logic::Reset() {
|
||||
void Logic::Reset(bool resetSaveContext /*= true*/) {
|
||||
if (resetSaveContext) {
|
||||
NewSaveContext();
|
||||
}
|
||||
StartPerformanceTimer(PT_LOGIC_RESET);
|
||||
memset(inLogic, false, sizeof(inLogic));
|
||||
// Settings-dependent variables
|
||||
IsKeysanity = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
|
||||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
|
||||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE);
|
||||
IsFireLoopLocked = ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANYWHERE) ||
|
||||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_OVERWORLD) ||
|
||||
ctx->GetOption(RSK_KEYSANITY).Is(RO_DUNGEON_ITEM_LOC_ANY_DUNGEON);
|
||||
|
||||
// AmmoCanDrop = /*AmmoDrops.IsNot(AMMODROPS_NONE)*/ false; TODO: AmmoDrop setting
|
||||
|
||||
|
@ -2371,6 +2374,7 @@ void Logic::Reset() {
|
|||
ShadowTrialClear = false;
|
||||
LightTrialClear = false;
|
||||
|
||||
if (resetSaveContext) {
|
||||
// Ocarina C Buttons
|
||||
bool ocBtnShuffle = ctx->GetOption(RSK_SHUFFLE_OCARINA_BUTTONS).Is(true);
|
||||
SetRandoInf(RAND_INF_HAS_OCARINA_A, !ocBtnShuffle);
|
||||
|
@ -2398,11 +2402,12 @@ void Logic::Reset() {
|
|||
SetRandoInf(RAND_INF_FISHING_POLE_FOUND, true);
|
||||
}
|
||||
|
||||
// If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in vanilla
|
||||
// FiT
|
||||
if (!IsKeysanity && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) {
|
||||
// If not keysanity, start with 1 logical key to account for automatically unlocking the basement door in
|
||||
// vanilla FiT
|
||||
if (!IsFireLoopLocked && ctx->GetDungeon(Rando::FIRE_TEMPLE)->IsVanilla()) {
|
||||
SetSmallKeyCount(SCENE_FIRE_TEMPLE, 1);
|
||||
}
|
||||
}
|
||||
|
||||
// Bottle Count
|
||||
Bottles = 0;
|
||||
|
@ -2454,7 +2459,9 @@ void Logic::Reset() {
|
|||
// Other
|
||||
AtDay = false;
|
||||
AtNight = false;
|
||||
if (resetSaveContext) {
|
||||
GetSaveContext()->linkAge = !ctx->GetOption(RSK_SELECTED_STARTING_AGE).Get();
|
||||
}
|
||||
|
||||
// Events
|
||||
ShowedMidoSwordAndShield = false;
|
||||
|
@ -2519,6 +2526,8 @@ void Logic::Reset() {
|
|||
Spirit1FSilverRupees = false;
|
||||
JabuRutoIn1F = false;
|
||||
|
||||
CalculatingAvailableChecks = false;
|
||||
|
||||
StopPerformanceTimer(PT_LOGIC_RESET);
|
||||
}
|
||||
} // namespace Rando
|
||||
|
|
|
@ -59,7 +59,7 @@ class Logic {
|
|||
bool LightTrialClear = false;
|
||||
|
||||
// Logical keysanity
|
||||
bool IsKeysanity = false;
|
||||
bool IsFireLoopLocked = false;
|
||||
|
||||
// Bottle Count
|
||||
uint8_t Bottles = 0;
|
||||
|
@ -183,6 +183,9 @@ class Logic {
|
|||
|
||||
/* --- END OF HELPERS AND LOCATION ACCESS --- */
|
||||
|
||||
bool CalculatingAvailableChecks = false;
|
||||
bool ACProcessUndiscoveredExits = false;
|
||||
|
||||
SaveContext* mSaveContext = nullptr;
|
||||
Logic();
|
||||
bool CanUse(RandomizerGet itemName);
|
||||
|
@ -254,7 +257,7 @@ class Logic {
|
|||
bool CanUseProjectile();
|
||||
bool CanBuildRainbowBridge();
|
||||
bool CanTriggerLACS();
|
||||
void Reset();
|
||||
void Reset(bool resetSaveContext = true);
|
||||
void SetContext(std::shared_ptr<Context> _ctx);
|
||||
bool GetInLogic(LogicVal logicVal);
|
||||
void SetInLogic(LogicVal logicVal, bool remove);
|
||||
|
|
|
@ -65,7 +65,7 @@ const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi";
|
|||
const std::string Randomizer::IceTrapRandoMessageTableID = "RandomizerIceTrap";
|
||||
const std::string Randomizer::randoMiscHintsTableID = "RandomizerMiscHints";
|
||||
|
||||
static const char* englishRupeeNames[190] = {
|
||||
static const char* englishRupeeNames[188] = {
|
||||
"[P]",
|
||||
"Bad RNG Rolls",
|
||||
"Baht",
|
||||
|
@ -111,8 +111,6 @@ static const char* englishRupeeNames[190] = {
|
|||
"Dimes",
|
||||
"Dinars",
|
||||
"DNA",
|
||||
"Doge",
|
||||
"Dogecoin",
|
||||
"Doll Hairs",
|
||||
"Dollars",
|
||||
"Dollarydoos",
|
||||
|
@ -258,25 +256,25 @@ static const char* englishRupeeNames[190] = {
|
|||
"Zorkmids",
|
||||
};
|
||||
|
||||
static const char* germanRupeeNames[80] = {
|
||||
static const char* germanRupeeNames[79] = {
|
||||
"Baht", "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", "Brötchen", "Cent",
|
||||
"Diamanten", "Dinar", "Diridari", "Dogecoin", "Dollar", "Draken", "ECU", "Elexit",
|
||||
"Erz", "Erzbrocken", "Euro", "EXP", "Forint", "Franken", "Freunde", "Gil",
|
||||
"Gold", "Groschen", "Gulden", "Gummibären", "Heller", "Juwelen", "Karolin", "Kartoffeln",
|
||||
"Kies", "Knete", "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", "Kronkorken",
|
||||
"Kröten", "Lira", "Mark", "Mäuse", "Monde", "Moorhühner", "Moos", "Münzen",
|
||||
"Naira", "Penunze", "Pesa", "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks",
|
||||
"Pokédollar", "Radieschen", "Rand", "Rappen", "Real", "Rial", "Riyal", "Rubine",
|
||||
"Rupien", "Saphire", "Schilling", "Seelen", "Septime", "Smaragde", "Steine", "Sterne",
|
||||
"Sternis", "Tael", "Taler", "Wagenchips", "Won", "Yen", "Yuan", "Zenny",
|
||||
"Diamanten", "Dinar", "Diridari", "Dollar", "Draken", "ECU", "Elexit", "Erz",
|
||||
"Erzbrocken", "Euro", "EXP", "Forint", "Franken", "Freunde", "Gil", "Gold",
|
||||
"Groschen", "Gulden", "Gummibären", "Heller", "Juwelen", "Karolin", "Kartoffeln", "Kies",
|
||||
"Knete", "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", "Kronkorken", "Kröten",
|
||||
"Lira", "Mark", "Mäuse", "Monde", "Moorhühner", "Moos", "Münzen", "Naira",
|
||||
"Penunze", "Pesa", "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks", "Pokédollar",
|
||||
"Radieschen", "Rand", "Rappen", "Real", "Rial", "Riyal", "Rubine", "Rupien",
|
||||
"Saphire", "Schilling", "Seelen", "Septime", "Smaragde", "Steine", "Sterne", "Sternis",
|
||||
"Tael", "Taler", "Wagenchips", "Won", "Yen", "Yuan", "Zenny",
|
||||
};
|
||||
|
||||
static const char* frenchRupeeNames[40] = {
|
||||
static const char* frenchRupeeNames[39] = {
|
||||
"Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules",
|
||||
"Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", "Dollars",
|
||||
"Émeraudes", "Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils",
|
||||
"Grouses", "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", "Orbes", "Orens",
|
||||
"Pépètes", "Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies",
|
||||
"Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dollars", "Émeraudes",
|
||||
"Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils", "Grouses",
|
||||
"Halos", "Joyaux", "Lunes", "Mailles", "Munnies", "Orbes", "Orens", "Pépètes",
|
||||
"Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies",
|
||||
};
|
||||
|
||||
Randomizer::Randomizer() {
|
||||
|
@ -3726,13 +3724,15 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||
}
|
||||
|
||||
UIWidgets::Spacer(0);
|
||||
ImGui::BeginDisabled((gSaveContext.gameMode != GAMEMODE_FILE_SELECT) || GameInteractor::IsSaveLoaded());
|
||||
if (UIWidgets::Button("Generate Randomizer",
|
||||
UIWidgets::ButtonOptions().Size(ImVec2(250.f, 0.f)).Color(THEME_COLOR))) {
|
||||
UIWidgets::ButtonOptions options = UIWidgets::ButtonOptions().Size(ImVec2(250.f, 0.f)).Color(THEME_COLOR);
|
||||
options.Disabled((gSaveContext.gameMode != GAMEMODE_FILE_SELECT) || GameInteractor::IsSaveLoaded());
|
||||
if (options.disabled) {
|
||||
options.DisabledTooltip("Must be on File Select to generate a randomizer seed.");
|
||||
}
|
||||
if (UIWidgets::Button("Generate Randomizer", options)) {
|
||||
ctx->SetSpoilerLoaded(false);
|
||||
GenerateRandomizer(CVarGetInteger(CVAR_RANDOMIZER_SETTING("ManualSeedEntry"), 0) ? seedString : "");
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
ImGui::SameLine();
|
||||
if (!CVarGetInteger(CVAR_RANDOMIZER_SETTING("DontGenerateSpoiler"), 0)) {
|
||||
|
@ -4515,6 +4515,9 @@ CustomMessage Randomizer::GetMapGetItemMessageWithHint(GetItemEntry itemEntry) {
|
|||
messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage());
|
||||
}
|
||||
|
||||
// BUG: the icon is not in the message yet so are not accounted for, so overflows are possible
|
||||
messageEntry.AutoFormat();
|
||||
|
||||
return messageEntry;
|
||||
}
|
||||
|
||||
|
|
|
@ -566,6 +566,7 @@ typedef enum {
|
|||
RR_DEKU_TREE_MQ_OUTSIDE_BOSS_ROOM,
|
||||
|
||||
RR_DEKU_TREE_BOSS_ENTRYWAY,
|
||||
RR_DEKU_TREE_BOSS_EXIT,
|
||||
RR_DEKU_TREE_BOSS_ROOM,
|
||||
|
||||
RR_DODONGOS_CAVERN_BEGINNING,
|
||||
|
@ -613,7 +614,9 @@ typedef enum {
|
|||
RR_DODONGOS_CAVERN_MQ_BEHIND_MOUTH,
|
||||
RR_DODONGOS_CAVERN_MQ_BACK_BEHIND_FIRE,
|
||||
RR_DODONGOS_CAVERN_MQ_BACK_SWITCH_GRAVE,
|
||||
|
||||
RR_DODONGOS_CAVERN_BOSS_ENTRYWAY,
|
||||
RR_DODONGOS_CAVERN_BOSS_EXIT,
|
||||
RR_DODONGOS_CAVERN_BOSS_ROOM,
|
||||
|
||||
RR_JABU_JABUS_BELLY_BEGINNING,
|
||||
|
@ -642,6 +645,7 @@ typedef enum {
|
|||
RR_JABU_JABUS_BELLY_MQ_EAST_ROOM,
|
||||
|
||||
RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY,
|
||||
RR_JABU_JABUS_BELLY_BOSS_EXIT,
|
||||
RR_JABU_JABUS_BELLY_BOSS_ROOM,
|
||||
|
||||
RR_FOREST_TEMPLE_FIRST_ROOM,
|
||||
|
|
|
@ -580,6 +580,13 @@ void CheckTrackerLoadGame(int32_t fileNum) {
|
|||
UpdateAllOrdering();
|
||||
UpdateInventoryChecks();
|
||||
UpdateFilters();
|
||||
|
||||
RegionTable_Init();
|
||||
|
||||
if (Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_ENTRANCES).Get()) {
|
||||
Rando::Context::GetInstance()->GetEntranceShuffler()->ApplyEntranceOverrides();
|
||||
}
|
||||
|
||||
RecalculateAvailableChecks();
|
||||
}
|
||||
|
||||
|
@ -898,7 +905,6 @@ void LoadFile() {
|
|||
SaveManager::Instance->LoadData("areasSpoiled", areasSpoiled, (uint32_t)0);
|
||||
UpdateAllOrdering();
|
||||
UpdateAllAreas();
|
||||
RegionTable_Init();
|
||||
}
|
||||
|
||||
void Teardown() {
|
||||
|
@ -1481,6 +1487,27 @@ void LoadSettings() {
|
|||
showOverworldFreestanding = false;
|
||||
showDungeonFreestanding = true;
|
||||
}
|
||||
|
||||
switch (OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_GANONS_BOSS_KEY)) {
|
||||
case RO_GANON_BOSS_KEY_LACS_STONES:
|
||||
Rando::Context::GetInstance()->LACSCondition(RO_LACS_STONES);
|
||||
break;
|
||||
case RO_GANON_BOSS_KEY_LACS_MEDALLIONS:
|
||||
Rando::Context::GetInstance()->LACSCondition(RO_LACS_MEDALLIONS);
|
||||
break;
|
||||
case RO_GANON_BOSS_KEY_LACS_REWARDS:
|
||||
Rando::Context::GetInstance()->LACSCondition(RO_LACS_REWARDS);
|
||||
break;
|
||||
case RO_GANON_BOSS_KEY_LACS_DUNGEONS:
|
||||
Rando::Context::GetInstance()->LACSCondition(RO_LACS_DUNGEONS);
|
||||
break;
|
||||
case RO_GANON_BOSS_KEY_LACS_TOKENS:
|
||||
Rando::Context::GetInstance()->LACSCondition(RO_LACS_TOKENS);
|
||||
break;
|
||||
default:
|
||||
Rando::Context::GetInstance()->LACSCondition(RO_LACS_VANILLA);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool IsCheckShuffled(RandomizerCheck rc) {
|
||||
|
@ -1820,7 +1847,7 @@ void DrawLocation(RandomizerCheck rc) {
|
|||
case RCSHOW_IDENTIFIED:
|
||||
case RCSHOW_SEEN:
|
||||
if (IS_RANDO) {
|
||||
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP && !mystery && !itemLoc->IsAddedToPool()) {
|
||||
if (itemLoc->GetPlacedRandomizerGet() == RG_ICE_TRAP && !mystery) {
|
||||
if (status == RCSHOW_IDENTIFIED) {
|
||||
txt = OTRGlobals::Instance->gRandoContext->overrides[rc].GetTrickName().GetForLanguage(
|
||||
gSaveContext.language);
|
||||
|
@ -1830,11 +1857,10 @@ void DrawLocation(RandomizerCheck rc) {
|
|||
.GetName()
|
||||
.GetForLanguage(gSaveContext.language);
|
||||
}
|
||||
} else if (!mystery && !itemLoc->IsAddedToPool()) {
|
||||
} else if (!mystery) {
|
||||
txt = itemLoc->GetPlacedItem().GetName().GetForLanguage(gSaveContext.language);
|
||||
}
|
||||
if (IsVisibleInCheckTracker(rc) && status == RCSHOW_IDENTIFIED && !mystery &&
|
||||
!itemLoc->IsAddedToPool()) {
|
||||
if (IsVisibleInCheckTracker(rc) && status == RCSHOW_IDENTIFIED && !mystery) {
|
||||
auto price = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc)->GetPrice();
|
||||
if (price) {
|
||||
txt += fmt::format(" - {}", price);
|
||||
|
@ -1958,7 +1984,7 @@ void ImGuiDrawTwoColorPickerSection(const char* text, const char* cvarMainName,
|
|||
UIWidgets::PopStyleCombobox();
|
||||
}
|
||||
|
||||
void RecalculateAvailableChecks() {
|
||||
void RecalculateAvailableChecks(RandomizerRegion startingRegion /* = RR_ROOT */) {
|
||||
if (!enableAvailableChecks) {
|
||||
return;
|
||||
}
|
||||
|
@ -1966,35 +1992,30 @@ void RecalculateAvailableChecks() {
|
|||
ResetPerformanceTimer(PT_RECALCULATE_AVAILABLE_CHECKS);
|
||||
StartPerformanceTimer(PT_RECALCULATE_AVAILABLE_CHECKS);
|
||||
|
||||
const auto& ctx = Rando::Context::GetInstance();
|
||||
|
||||
std::vector<RandomizerCheck> targetLocations;
|
||||
targetLocations.reserve(RR_MAX);
|
||||
targetLocations.reserve(RC_MAX);
|
||||
for (auto& location : Rando::StaticData::GetLocationTable()) {
|
||||
RandomizerCheck rc = location.GetRandomizerCheck();
|
||||
Rando::ItemLocation* itemLocation = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
|
||||
Rando::ItemLocation* itemLocation = ctx->GetItemLocation(rc);
|
||||
itemLocation->SetAvailable(false);
|
||||
if (!itemLocation->HasObtained()) {
|
||||
targetLocations.emplace_back(rc);
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<RandomizerCheck> availableChecks = ReachabilitySearch(targetLocations, RG_NONE, true);
|
||||
std::vector<RandomizerCheck> availableChecks = ReachabilitySearch(targetLocations, RG_NONE, true, startingRegion);
|
||||
for (auto& rc : availableChecks) {
|
||||
const auto& location = Rando::StaticData::GetLocation(rc);
|
||||
const auto& itemLocation = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
|
||||
if (location->GetRCType() == RCTYPE_SHOP && itemLocation->GetCheckStatus() == RCSHOW_IDENTIFIED) {
|
||||
if (CanBuyAnother(rc)) {
|
||||
const auto& itemLocation = ctx->GetItemLocation(rc);
|
||||
itemLocation->SetAvailable(true);
|
||||
}
|
||||
} else {
|
||||
itemLocation->SetAvailable(true);
|
||||
}
|
||||
}
|
||||
|
||||
totalChecksAvailable = 0;
|
||||
for (auto& [rcArea, vec] : checksByArea) {
|
||||
areaChecksAvailable[rcArea] = 0;
|
||||
for (auto& rc : vec) {
|
||||
Rando::ItemLocation* itemLocation = OTRGlobals::Instance->gRandoContext->GetItemLocation(rc);
|
||||
Rando::ItemLocation* itemLocation = ctx->GetItemLocation(rc);
|
||||
if (itemLocation->IsAvailable() && IsVisibleInCheckTracker(rc) && !IsCheckHidden(rc)) {
|
||||
areaChecksAvailable[rcArea]++;
|
||||
}
|
||||
|
@ -2114,8 +2135,11 @@ void CheckTrackerSettingsWindow::DrawElement() {
|
|||
"with your current progress.")
|
||||
.Color(THEME_COLOR))) {
|
||||
enableAvailableChecks = CVarGetInteger(CVAR_TRACKER_CHECK("EnableAvailableChecks"), 0);
|
||||
|
||||
if (GameInteractor::IsSaveLoaded(true)) {
|
||||
RecalculateAvailableChecks();
|
||||
}
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
// Filtering settings
|
||||
|
|
|
@ -61,5 +61,5 @@ void UpdateAllOrdering();
|
|||
void UpdateAllAreas();
|
||||
void RecalculateAllAreaTotals();
|
||||
void SpoilAreaFromCheck(RandomizerCheck rc);
|
||||
void RecalculateAvailableChecks();
|
||||
void RecalculateAvailableChecks(RandomizerRegion startingRegion = RR_ROOT);
|
||||
} // namespace CheckTracker
|
||||
|
|
|
@ -809,6 +809,7 @@ void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance) {
|
|||
if (idx < SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT) {
|
||||
u32 entranceBit = 1 << (entranceIndex - (idx * bitsPerIndex));
|
||||
gSaveContext.ship.stats.entrancesDiscovered[idx] |= entranceBit;
|
||||
CheckTracker_RecalculateAvailableChecks();
|
||||
|
||||
// Set reverse entrance when not decoupled
|
||||
if (!Randomizer_GetSettingValue(RSK_DECOUPLED_ENTRANCES) && !isReversedEntrance) {
|
||||
|
|
|
@ -232,6 +232,8 @@ extern "C" void Randomizer_InitSaveFile() {
|
|||
// Reset triforce pieces collected.
|
||||
gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected = 0;
|
||||
|
||||
SetStartingItems();
|
||||
|
||||
// Set Cutscene flags and texts to skip them.
|
||||
Flags_SetEventChkInf(EVENTCHKINF_FIRST_SPOKE_TO_MIDO);
|
||||
Flags_SetInfTable(INFTABLE_SPOKE_TO_KAEPORA_IN_LAKE_HYLIA);
|
||||
|
@ -269,9 +271,9 @@ extern "C" void Randomizer_InitSaveFile() {
|
|||
|
||||
// Remove One Time Scrubs with Scrubsanity off
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_SCRUBS) == RO_SCRUBS_OFF) {
|
||||
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_NEAR_BRIDGE);
|
||||
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_LW_DEKU_SCRUB_GROTTO_FRONT);
|
||||
Flags_SetRandomizerInf(RAND_INF_SCRUBS_PURCHASED_HF_DEKU_SCRUB_GROTTO);
|
||||
Flags_SetItemGetInf(ITEMGETINF_DEKU_SCRUB_HEART_PIECE);
|
||||
Flags_SetInfTable(INFTABLE_BOUGHT_STICK_UPGRADE);
|
||||
Flags_SetInfTable(INFTABLE_BOUGHT_NUT_UPGRADE);
|
||||
}
|
||||
|
||||
int startingAge = OTRGlobals::Instance->gRandoContext->GetOption(RSK_SELECTED_STARTING_AGE).Get();
|
||||
|
@ -430,6 +432,4 @@ extern "C" void Randomizer_InitSaveFile() {
|
|||
gSaveContext.itemGetInf[3] |= 0x800; // Bunny Hood related
|
||||
gSaveContext.itemGetInf[3] |= 0x8000; // Obtained Mask of Truth
|
||||
}
|
||||
|
||||
SetStartingItems();
|
||||
}
|
||||
|
|
|
@ -251,7 +251,7 @@ void Settings::CreateOptions() {
|
|||
OPT_U8(RSK_LACS_REWARD_COUNT, "GCBK Reward Count", {NumOpts(0, 10)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardCount"), "", WidgetType::Slider, 9, true);
|
||||
OPT_U8(RSK_LACS_DUNGEON_COUNT, "GCBK Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsDungeonCount"), "", WidgetType::Slider, 8, true);
|
||||
OPT_U8(RSK_LACS_TOKEN_COUNT, "GCBK Token Count", {NumOpts(0, 100)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsTokenCount"), "", WidgetType::Slider, 100, true);
|
||||
OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), "", WidgetType::Combobox, RO_LACS_STANDARD_REWARD);
|
||||
OPT_U8(RSK_LACS_OPTIONS, "GCBK LACS Reward Options", {"Standard Reward", "Greg as Reward", "Greg as Wildcard"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("LacsRewardOptions"), mOptionDescriptions[RSK_LACS_OPTIONS], WidgetType::Combobox, RO_LACS_STANDARD_REWARD);
|
||||
OPT_U8(RSK_KEYRINGS, "Key Rings", {"Off", "Random", "Count", "Selection"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRings"), mOptionDescriptions[RSK_KEYRINGS], WidgetType::Combobox, RO_KEYRINGS_OFF);
|
||||
OPT_U8(RSK_KEYRINGS_RANDOM_COUNT, "Keyring Dungeon Count", {NumOpts(0, 9)}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsRandomCount"), "", WidgetType::Slider, 8);
|
||||
OPT_U8(RSK_KEYRINGS_GERUDO_FORTRESS, "Gerudo Fortress Keyring", {"No", "Random", "Yes"}, OptionCategory::Setting, CVAR_RANDOMIZER_SETTING("ShuffleKeyRingsGerudoFortress"), "", WidgetType::Combobox, 0);
|
||||
|
@ -1742,6 +1742,14 @@ TrickOption& Settings::GetTrickOption(const RandomizerTrick key) {
|
|||
return mTrickOptions[key];
|
||||
}
|
||||
|
||||
int Settings::GetRandomizerTrickByName(const std::string& name) {
|
||||
const auto& it = mTrickNameToEnum.find(name);
|
||||
if (it == mTrickNameToEnum.end()) {
|
||||
return -1;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void Context::ResetTrickOptions() {
|
||||
for (int count = 0; count < RT_MAX; count++) {
|
||||
mTrickOptions[count].Set(0); // RANDOTODO this can probably be done better
|
||||
|
|
|
@ -50,6 +50,14 @@ class Settings {
|
|||
*/
|
||||
TrickOption& GetTrickOption(RandomizerTrick key);
|
||||
|
||||
/**
|
||||
* @brief Get the RandomizerTrick corresponding to the provided name.
|
||||
*
|
||||
* @param name
|
||||
* @return int RandomizerTrick index or -1 if not found
|
||||
*/
|
||||
int GetRandomizerTrickByName(const std::string& name);
|
||||
|
||||
/**
|
||||
* @brief Returns a reference to the entire array of options.
|
||||
*
|
||||
|
|
|
@ -13,12 +13,14 @@ extern "C" {
|
|||
#include "src/overlays/actors/ovl_Bg_Treemouth/z_bg_treemouth.h"
|
||||
#include "src/overlays/actors/ovl_En_Owl/z_en_owl.h"
|
||||
#include "src/overlays/actors/ovl_En_Go2/z_en_go2.h"
|
||||
#include "src/overlays/actors/ovl_En_Heishi2/z_en_heishi2.h"
|
||||
#include "src/overlays/actors/ovl_En_Ko/z_en_ko.h"
|
||||
#include "src/overlays/actors/ovl_En_Ma1/z_en_ma1.h"
|
||||
#include "src/overlays/actors/ovl_En_Ru2/z_en_ru2.h"
|
||||
#include "src/overlays/actors/ovl_En_Zl4/z_en_zl4.h"
|
||||
#include "src/overlays/actors/ovl_En_Box/z_en_box.h"
|
||||
#include "src/overlays/actors/ovl_Demo_Im/z_demo_im.h"
|
||||
#include "src/overlays/actors/ovl_Demo_Kekkai/z_demo_kekkai.h"
|
||||
#include "src/overlays/actors/ovl_En_Sa/z_en_sa.h"
|
||||
#include "src/overlays/actors/ovl_Bg_Ddan_Kd/z_bg_ddan_kd.h"
|
||||
#include "src/overlays/actors/ovl_En_Tk/z_en_tk.h"
|
||||
|
@ -222,6 +224,25 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Entrances"), IS_RANDO) &&
|
||||
(entranceFlag != EVENTCHKINF_EPONA_OBTAINED) && entranceIndex != ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE) {
|
||||
*should = false;
|
||||
|
||||
// Check for dispulsion of Ganon's Tower barrier
|
||||
switch (entranceIndex) {
|
||||
case ENTR_INSIDE_GANONS_CASTLE_2:
|
||||
case ENTR_INSIDE_GANONS_CASTLE_3:
|
||||
case ENTR_INSIDE_GANONS_CASTLE_4:
|
||||
case ENTR_INSIDE_GANONS_CASTLE_5:
|
||||
case ENTR_INSIDE_GANONS_CASTLE_6:
|
||||
case ENTR_INSIDE_GANONS_CASTLE_7:
|
||||
if (Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FOREST_TRIAL) &&
|
||||
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_WATER_TRIAL) &&
|
||||
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SHADOW_TRIAL) &&
|
||||
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_FIRE_TRIAL) &&
|
||||
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_LIGHT_TRIAL) &&
|
||||
Flags_GetEventChkInf(EVENTCHKINF_COMPLETED_SPIRIT_TRIAL)) {
|
||||
Flags_SetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -280,7 +301,8 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
}
|
||||
switch (actor->id) {
|
||||
case ACTOR_OBJ_SWITCH: {
|
||||
if (actor->params == 8224 && gPlayState->sceneNum == SCENE_DODONGOS_CAVERN &&
|
||||
if ((actor->params == 8224 && gPlayState->sceneNum == SCENE_DODONGOS_CAVERN) ||
|
||||
(actor->params == 6979 && gPlayState->sceneNum == SCENE_WATER_TEMPLE) &&
|
||||
CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"), 0)) {
|
||||
break;
|
||||
}
|
||||
|
@ -358,6 +380,11 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
}
|
||||
break;
|
||||
}
|
||||
case VB_FREEZE_LINK_FOR_FOREST_PILLARS:
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
|
||||
*should = false;
|
||||
}
|
||||
break;
|
||||
case VB_SHOW_TITLE_CARD:
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.DisableTitleCard"), IS_RANDO)) {
|
||||
*should = false;
|
||||
|
@ -450,6 +477,26 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
*should = false;
|
||||
}
|
||||
break;
|
||||
case VB_PLAY_DISPEL_BARRIER_CS: {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.OnePoint"), IS_RANDO)) {
|
||||
static s16 trialEntrances[] = {
|
||||
0,
|
||||
ENTR_INSIDE_GANONS_CASTLE_3,
|
||||
ENTR_INSIDE_GANONS_CASTLE_6,
|
||||
ENTR_INSIDE_GANONS_CASTLE_5,
|
||||
ENTR_INSIDE_GANONS_CASTLE_4,
|
||||
ENTR_INSIDE_GANONS_CASTLE_7,
|
||||
ENTR_INSIDE_GANONS_CASTLE_2,
|
||||
};
|
||||
RateLimitedSuccessChime();
|
||||
DemoKekkai* kekkai = va_arg(args, DemoKekkai*);
|
||||
gPlayState->nextEntranceIndex = trialEntrances[kekkai->actor.params];
|
||||
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
|
||||
*should = false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VB_OWL_INTERACTION: {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipOwlInteractions"), IS_RANDO) && *should) {
|
||||
EnOwl* enOwl = va_arg(args, EnOwl*);
|
||||
|
@ -729,6 +776,18 @@ void TimeSaverOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_li
|
|||
|
||||
break;
|
||||
}
|
||||
case VB_PLAY_GATE_OPENING_OR_CLOSING_CS: {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipMiscInteractions"), IS_RANDO)) {
|
||||
EnHeishi2* enHeishi2 = va_arg(args, EnHeishi2*);
|
||||
enHeishi2->unk_2F2[0] = 0;
|
||||
|
||||
// The second argument determines whether the vanilla code should be run anyway. It
|
||||
// should be set to `true` ONLY IF said code calls `Play_ClearCamera`, false otherwise.
|
||||
bool clearCamera = (bool)va_arg(args, int);
|
||||
*should = clearCamera && enHeishi2->cameraId != MAIN_CAM;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case VB_PLAY_RAINBOW_BRIDGE_CS: {
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.Story"), IS_RANDO)) {
|
||||
*should = false;
|
||||
|
|
|
@ -1145,6 +1145,13 @@ extern "C" void InitOTR() {
|
|||
"Error", "SoH does not have proper file permissions. Please move it to a folder that does and run again.");
|
||||
exit(1);
|
||||
}
|
||||
if (ownPath.string().find("OneDrive") != std::string::npos) {
|
||||
Extractor::ShowErrorBox(
|
||||
"Error",
|
||||
"SoH appears to be in a OneDrive folder, which will cause issues. "
|
||||
"Please move it to a folder outside of OneDrive, like the root of a drive (e.g. \"C:\\Games\\SoH\").");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if not defined(__SWITCH__) && not defined(__WIIU__)
|
||||
|
@ -2437,15 +2444,15 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
|
|||
// animation until the text box auto-dismisses.
|
||||
// RANDOTODO: Implement a way to determine if an item came from a skulltula and
|
||||
// inject the auto-dismiss control code if it did.
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 &&
|
||||
!(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) {
|
||||
bool gsTokensShuffled = Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF;
|
||||
if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && !(IS_RANDO && gsTokensShuffled)) {
|
||||
textId = TEXT_GS_NO_FREEZE;
|
||||
} else {
|
||||
textId = TEXT_GS_FREEZE;
|
||||
}
|
||||
// In vanilla, GS token count is incremented prior to the text box displaying
|
||||
// In rando we need to bump the token count by one to show the correct count
|
||||
s16 gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0);
|
||||
s16 gsCount = gSaveContext.inventory.gsTokens + ((IS_RANDO && gsTokensShuffled) ? 1 : 0);
|
||||
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED);
|
||||
messageEntry.Replace("[[gsCount]]", std::to_string(gsCount));
|
||||
} else if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 &&
|
||||
|
@ -2608,4 +2615,7 @@ void SoH_ProcessDroppedFiles(std::string filePath) {
|
|||
return;
|
||||
}
|
||||
}
|
||||
// #endregion
|
||||
|
||||
extern "C" void CheckTracker_RecalculateAvailableChecks() {
|
||||
CheckTracker::RecalculateAvailableChecks();
|
||||
}
|
||||
|
|
|
@ -163,6 +163,7 @@ void Gfx_UnregisterBlendedTexture(const char* name);
|
|||
void Gfx_TextureCacheDelete(const uint8_t* addr);
|
||||
void SaveManager_ThreadPoolWait();
|
||||
void CheckTracker_OnMessageClose();
|
||||
void CheckTracker_RecalculateAvailableChecks();
|
||||
|
||||
GetItemID RetrieveGetItemIDFromItemID(ItemID itemID);
|
||||
RandomizerGet RetrieveRandomizerGetFromItemID(ItemID itemID);
|
||||
|
|
|
@ -342,10 +342,10 @@ void SohMenu::AddMenuEnhancements() {
|
|||
.Options(CheckboxOptions().DefaultValue(IS_RANDO));
|
||||
AddWidget(path, "Exclude Glitch-Aiding Cutscenes", WIDGET_CVAR_CHECKBOX)
|
||||
.CVar(CVAR_ENHANCEMENT("TimeSavers.SkipCutscene.GlitchAiding"))
|
||||
.Options(
|
||||
CheckboxOptions().Tooltip("Don't skip cutscenes that are associated with useful glitches. Currently, it is "
|
||||
.Options(CheckboxOptions().Tooltip(
|
||||
"Don't skip cutscenes that are associated with useful glitches. Currently, it is "
|
||||
"only the Fire Temple Darunia CS, Forest Temple Poe Sisters CS, Dodongo Boss "
|
||||
"Door Switch, and the Box Skip One Point in Jabu."));
|
||||
"Door Switch CS, Water Temple Dragon Switch CS, and the Box Skip One Point in Jabu."));
|
||||
|
||||
AddWidget(path, "Text", WIDGET_SEPARATOR_TEXT);
|
||||
AddWidget(path, "Skip Pickup Messages", WIDGET_CVAR_CHECKBOX)
|
||||
|
|
|
@ -145,7 +145,47 @@ void Audio_osWritebackDCache(void* mem, s32 size) {
|
|||
}
|
||||
|
||||
s32 osAiSetFrequency(u32 freq) {
|
||||
return 1;
|
||||
// this is based off the math from the original method
|
||||
/*
|
||||
|
||||
s32 osAiSetFrequency(u32 frequency) {
|
||||
u8 bitrate;
|
||||
f32 dacRateF = ((f32)osViClock / frequency) + 0.5f;
|
||||
u32 dacRate = dacRateF;
|
||||
|
||||
if (dacRate < 132) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
bitrate = (dacRate / 66);
|
||||
if (bitrate > 16) {
|
||||
bitrate = 16;
|
||||
}
|
||||
|
||||
HW_REG(AI_DACRATE_REG, u32) = dacRate - 1;
|
||||
HW_REG(AI_BITRATE_REG, u32) = bitrate - 1;
|
||||
return osViClock / (s32)dacRate;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
// bitrate is unused
|
||||
|
||||
// osViClock comes from
|
||||
// #define VI_NTSC_CLOCK 48681812 /* Hz = 48.681812 MHz */
|
||||
// s32 osViClock = VI_NTSC_CLOCK;
|
||||
|
||||
// frequency was originally 32000
|
||||
|
||||
// given all of that, dacRate is
|
||||
// (u32)(((f32)48681812 / 32000) + 0.5f)
|
||||
// which evaluates to 1521 (which is > 132)
|
||||
|
||||
// this leaves us with a final calculation of
|
||||
// 48681812 / 1521
|
||||
// which evaluates to 32006
|
||||
|
||||
return 32006;
|
||||
}
|
||||
|
||||
void osInvalDCache(void* vaddr, s32 nbytes) {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "z_bg_mori_kaitenkabe.h"
|
||||
#include "objects/object_mori_objects/object_mori_objects.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
|
||||
#define FLAGS 0
|
||||
|
||||
|
@ -97,7 +98,9 @@ void BgMoriKaitenkabe_Wait(BgMoriKaitenkabe* this, PlayState* play) {
|
|||
if ((this->timer > (28 - CVarGetInteger(CVAR_ENHANCEMENT("FasterBlockPush"), 0) * 4)) &&
|
||||
!Player_InCsMode(play)) {
|
||||
BgMoriKaitenkabe_SetupRotate(this);
|
||||
if (GameInteractor_Should(VB_FREEZE_LINK_FOR_FOREST_PILLARS, true)) {
|
||||
Player_SetCsActionWithHaltedActors(play, &this->dyna.actor, 8);
|
||||
}
|
||||
Math_Vec3f_Copy(&this->lockedPlayerPos, &player->actor.world.pos);
|
||||
push.x = Math_SinS(this->dyna.unk_158);
|
||||
push.y = 0.0f;
|
||||
|
@ -131,7 +134,9 @@ void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, PlayState* play) {
|
|||
Math_StepToF(&this->rotSpeed, 0.6f, 0.02f);
|
||||
if (Math_StepToF(&this->rotYdeg, this->rotDirection * 45.0f, this->rotSpeed)) {
|
||||
BgMoriKaitenkabe_SetupWait(this);
|
||||
if (GameInteractor_Should(VB_FREEZE_LINK_FOR_FOREST_PILLARS, true)) {
|
||||
Player_SetCsActionWithHaltedActors(play, thisx, 7);
|
||||
}
|
||||
if (this->rotDirection > 0.0f) {
|
||||
thisx->home.rot.y += 0x2000;
|
||||
} else {
|
||||
|
@ -148,7 +153,9 @@ void BgMoriKaitenkabe_Rotate(BgMoriKaitenkabe* this, PlayState* play) {
|
|||
this->dyna.unk_150 = 0.0f;
|
||||
player->stateFlags2 &= ~PLAYER_STATE2_MOVING_DYNAPOLY;
|
||||
}
|
||||
if (GameInteractor_Should(VB_FREEZE_LINK_FOR_FOREST_PILLARS, true)) {
|
||||
Math_Vec3f_Copy(&player->actor.world.pos, &this->lockedPlayerPos);
|
||||
}
|
||||
}
|
||||
|
||||
void BgMoriKaitenkabe_Update(Actor* thisx, PlayState* play) {
|
||||
|
|
|
@ -131,8 +131,14 @@ void func_808BAF40(BgTokiSwd* this, PlayState* play) {
|
|||
Item_Give(play, ITEM_SWORD_MASTER);
|
||||
}
|
||||
play->csCtx.segment = D_808BB2F0;
|
||||
|
||||
// Discover adult spawn
|
||||
Entrance_SetEntranceDiscovered(ENTR_HYRULE_FIELD_10, false);
|
||||
} else {
|
||||
play->csCtx.segment = D_808BB7A0;
|
||||
|
||||
// Discover child spawn
|
||||
Entrance_SetEntranceDiscovered(ENTR_LINKS_HOUSE_CHILD_SPAWN, false);
|
||||
}
|
||||
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_STOP);
|
||||
Audio_QueueSeqCmd(SEQ_PLAYER_BGM_MAIN << 24 | NA_BGM_MASTER_SWORD);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "z_demo_kekkai.h"
|
||||
#include "objects/object_demo_kekkai/object_demo_kekkai.h"
|
||||
#include "scenes/dungeons/ganontika/ganontika_scene.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h"
|
||||
#include "soh/ResourceManagerHelpers.h"
|
||||
|
||||
#define FLAGS (ACTOR_FLAG_UPDATE_CULLING_DISABLED | ACTOR_FLAG_DRAW_CULLING_DISABLED)
|
||||
|
@ -257,6 +258,7 @@ void DemoKekkai_TrialBarrierIdle(Actor* thisx, PlayState* play) {
|
|||
CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider1.base);
|
||||
CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider1.base);
|
||||
if (this->collider2.base.acFlags & AC_HIT) {
|
||||
if (GameInteractor_Should(VB_PLAY_DISPEL_BARRIER_CS, true, this)) {
|
||||
Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME);
|
||||
// "I got it"
|
||||
LOG_STRING("当ったよ");
|
||||
|
@ -265,6 +267,7 @@ void DemoKekkai_TrialBarrierIdle(Actor* thisx, PlayState* play) {
|
|||
play->csCtx.segment = SEGMENTED_TO_VIRTUAL(sSageCutscenes[this->actor.params]);
|
||||
gSaveContext.cutsceneTrigger = 1;
|
||||
}
|
||||
}
|
||||
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider2.base);
|
||||
func_8002F974(&this->actor, NA_SE_EV_TOWER_ENERGY - SFX_FLAG);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
struct DemoKekkai;
|
||||
|
||||
typedef void (*DemoKekkaiUpdateFunc)(struct DemoKekkai* this, PlayState* play);
|
||||
typedef void (*DemoKekkaiUpdateFunc)(struct DemoKekkai* thisx, PlayState* play);
|
||||
|
||||
typedef struct DemoKekkai {
|
||||
/* 0x0000 */ Actor actor;
|
||||
|
|
|
@ -314,6 +314,7 @@ void func_80A5372C(EnHeishi2* this, PlayState* play) {
|
|||
f32 frameCount = Animation_GetLastFrame(&gEnHeishiIdleAnim);
|
||||
|
||||
Animation_Change(&this->skelAnime, &gEnHeishiIdleAnim, 1.0f, 0.0f, (s16)frameCount, ANIMMODE_LOOP, -10.0f);
|
||||
if (GameInteractor_Should(VB_PLAY_GATE_OPENING_OR_CLOSING_CS, true, this, false)) {
|
||||
this->unk_2F2[0] = 200;
|
||||
this->cameraId = Play_CreateSubCamera(play);
|
||||
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
|
||||
|
@ -327,6 +328,7 @@ void func_80A5372C(EnHeishi2* this, PlayState* play) {
|
|||
this->unk_28C.z = 3014.0f;
|
||||
|
||||
Play_CameraSetAtEye(play, this->cameraId, &this->unk_280, &this->unk_28C);
|
||||
}
|
||||
this->actionFunc = func_80A53850;
|
||||
}
|
||||
|
||||
|
@ -334,11 +336,15 @@ void func_80A53850(EnHeishi2* this, PlayState* play) {
|
|||
BgSpot15Saku* gate;
|
||||
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
if (GameInteractor_Should(VB_PLAY_GATE_OPENING_OR_CLOSING_CS, true, this, false)) {
|
||||
Play_CameraSetAtEye(play, this->cameraId, &this->unk_280, &this->unk_28C);
|
||||
}
|
||||
gate = (BgSpot15Saku*)this->gate;
|
||||
if ((this->unk_2F2[0] == 0) || (gate->unk_168 == 0)) {
|
||||
if (GameInteractor_Should(VB_PLAY_GATE_OPENING_OR_CLOSING_CS, true, this, true)) {
|
||||
Play_ClearCamera(play, this->cameraId);
|
||||
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE);
|
||||
}
|
||||
Message_CloseTextbox(play);
|
||||
this->unk_30C = 1;
|
||||
Player_SetCsActionWithHaltedActors(play, NULL, 7);
|
||||
|
@ -479,6 +485,7 @@ void func_80A53DF8(EnHeishi2* this, PlayState* play) {
|
|||
f32 frameCount = Animation_GetLastFrame(&gEnHeishiIdleAnim);
|
||||
|
||||
Animation_Change(&this->skelAnime, &gEnHeishiIdleAnim, 1.0f, 0.0f, (s16)frameCount, ANIMMODE_LOOP, -10.0f);
|
||||
if (GameInteractor_Should(VB_PLAY_GATE_OPENING_OR_CLOSING_CS, true, this, false)) {
|
||||
this->unk_2F2[0] = 200;
|
||||
this->cameraId = Play_CreateSubCamera(play);
|
||||
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_WAIT);
|
||||
|
@ -496,6 +503,7 @@ void func_80A53DF8(EnHeishi2* this, PlayState* play) {
|
|||
this->unk_298.z = -1079.0f;
|
||||
this->unk_28C.z = -1079.0f;
|
||||
Play_CameraSetAtEye(play, this->cameraId, &this->unk_280, &this->unk_28C);
|
||||
}
|
||||
this->actionFunc = func_80A53F30;
|
||||
}
|
||||
|
||||
|
@ -503,11 +511,15 @@ void func_80A53F30(EnHeishi2* this, PlayState* play) {
|
|||
BgGateShutter* gate;
|
||||
|
||||
SkelAnime_Update(&this->skelAnime);
|
||||
if (GameInteractor_Should(VB_PLAY_GATE_OPENING_OR_CLOSING_CS, true, this, false)) {
|
||||
Play_CameraSetAtEye(play, this->cameraId, &this->unk_280, &this->unk_28C);
|
||||
}
|
||||
gate = (BgGateShutter*)this->gate;
|
||||
if ((this->unk_2F2[0] == 0) || (gate->openingState == 0)) {
|
||||
if (GameInteractor_Should(VB_PLAY_GATE_OPENING_OR_CLOSING_CS, true, this, true)) {
|
||||
Play_ClearCamera(play, this->cameraId);
|
||||
Play_ChangeCameraStatus(play, MAIN_CAM, CAM_STAT_ACTIVE);
|
||||
}
|
||||
if ((this->unk_30A != 2)) {
|
||||
if (this->unk_30A == 0) {
|
||||
this->actor.textId = 0x2015;
|
||||
|
|
|
@ -507,7 +507,7 @@ void EnRr_CollisionCheck(EnRr* this, PlayState* play) {
|
|||
this->collider2.base.ocFlags1 &= ~OC1_HIT;
|
||||
// "catch"
|
||||
osSyncPrintf(VT_FGCOL(GREEN) "キャッチ(%d)!!" VT_RST "\n", this->frameCount);
|
||||
if (play->grabPlayer(play, player)) {
|
||||
if (GameInteractor_Should(VB_LIKE_LIKE_GRAB_PLAYER, true, this) && play->grabPlayer(play, player)) {
|
||||
player->actor.parent = &this->actor;
|
||||
this->stopScroll = false;
|
||||
EnRr_SetupGrabPlayer(this, player);
|
||||
|
|
|
@ -706,7 +706,7 @@ void EnTorch2_Update(Actor* thisx, PlayState* play2) {
|
|||
sStaggerCount = 0;
|
||||
}
|
||||
}
|
||||
if (player->linearVelocity == -18.0f) {
|
||||
if (GameInteractor_Should(VB_TORCH2_HANDLE_CLANKING, player->linearVelocity == -18.0f, this)) {
|
||||
if (this->actor.xzDistToPlayer > 80.0f) {
|
||||
player->linearVelocity = 1.2f;
|
||||
} else if (this->actor.xzDistToPlayer < 70.0f) {
|
||||
|
|
|
@ -4764,8 +4764,10 @@ s32 func_808382DC(Player* this, PlayState* play) {
|
|||
gSaveContext.respawn[RESPAWN_MODE_DOWN].yaw = respawnInfo->yaw;
|
||||
}
|
||||
|
||||
if (GameInteractor_Should(VB_TRIGGER_VOIDOUT, true, this)) {
|
||||
Play_TriggerVoidOut(play);
|
||||
}
|
||||
}
|
||||
|
||||
Player_PlayVoiceSfx(this, NA_SE_VO_LI_TAKEN_AWAY);
|
||||
play->unk_11DE9 = 1;
|
||||
|
@ -5129,7 +5131,9 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol
|
|||
}
|
||||
|
||||
if (exitIndex == 0) {
|
||||
if (GameInteractor_Should(VB_TRIGGER_VOIDOUT, true, this)) {
|
||||
Play_TriggerVoidOut(play);
|
||||
}
|
||||
Scene_SetTransitionForNextEntrance(play);
|
||||
} else {
|
||||
play->nextEntranceIndex = play->setupExitList[exitIndex - 1];
|
||||
|
@ -5163,7 +5167,9 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol
|
|||
SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2,
|
||||
play->setupExitList[exitIndex - 1])) {
|
||||
gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = play->nextEntranceIndex;
|
||||
if (GameInteractor_Should(VB_TRIGGER_VOIDOUT, true, this)) {
|
||||
Play_TriggerVoidOut(play);
|
||||
}
|
||||
gSaveContext.respawnFlag = -2;
|
||||
}
|
||||
gSaveContext.retainWeatherMode = 1;
|
||||
|
@ -5226,7 +5232,7 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol
|
|||
if (this->actor.bgCheckFlags & 1) {
|
||||
if (this->floorProperty == 5) {
|
||||
Play_TriggerRespawn(play);
|
||||
} else {
|
||||
} else if (GameInteractor_Should(VB_TRIGGER_VOIDOUT, true, this)) {
|
||||
Play_TriggerVoidOut(play);
|
||||
}
|
||||
play->transitionType = TRANS_TYPE_FADE_BLACK_FAST;
|
||||
|
@ -9613,6 +9619,10 @@ static FallImpactInfo D_80854600[] = {
|
|||
s32 func_80843E64(PlayState* play, Player* this) {
|
||||
s32 sp34;
|
||||
|
||||
if (!GameInteractor_Should(VB_RECIEVE_FALL_DAMAGE, true, this)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((sFloorType == 6) || (sFloorType == 9)) {
|
||||
sp34 = 0;
|
||||
} else {
|
||||
|
@ -15009,7 +15019,7 @@ void Player_Action_8084F88C(Player* this, PlayState* play) {
|
|||
if (IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
|
||||
Grotto_ForceRegularVoidOut();
|
||||
}
|
||||
} else {
|
||||
} else if (GameInteractor_Should(VB_TRIGGER_VOIDOUT, true, this)) {
|
||||
Play_TriggerVoidOut(play);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue