fix crash when generating decoupled entrances with boss shuffle (#6189)
regression from ganon's tower shuffle
This commit is contained in:
@@ -211,6 +211,8 @@ void ProcessExits(Region* region, GetAccessibleLocationsStruct& gals, Randomizer
|
||||
// Include bluewarps when unshuffled but dungeon or boss shuffle is on
|
||||
if ((exit.IsShuffled() ||
|
||||
(exit.GetType() == Rando::EntranceType::BlueWarp &&
|
||||
(ctx->GetOption(RSK_SHUFFLE_GANONS_TOWER_ENTRANCE) ||
|
||||
exit.GetParentRegionKey() != RR_GANONS_TOWER_STAIRS_1) &&
|
||||
(ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES)))) &&
|
||||
!exit.IsAddedToPool() && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) {
|
||||
gals.entranceSphere.push_back(&exit);
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "pool_functions.hpp"
|
||||
#include "soh/Enhancements/randomizer/randomizer_entrance_tracker.h"
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <spdlog/fmt/fmt.h>
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
@@ -223,12 +224,8 @@ static void WriteChosenOptions() {
|
||||
static void WritePlaythrough() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
|
||||
for (uint32_t i = 0; i < ctx->playthroughLocations.size(); ++i) {
|
||||
auto sphereNum = std::to_string(i);
|
||||
std::string sphereString = "sphere ";
|
||||
if (i < 10)
|
||||
sphereString += "0";
|
||||
sphereString += sphereNum;
|
||||
for (size_t i = 0; i < ctx->playthroughLocations.size(); i++) {
|
||||
std::string sphereString = fmt::format("sphere {:0>2}", i);
|
||||
for (const RandomizerCheck key : ctx->playthroughLocations[i]) {
|
||||
if (!ctx->GetItemLocation(key)->IsHidden()) {
|
||||
WriteLocation(sphereString, key, true);
|
||||
@@ -240,12 +237,8 @@ static void WritePlaythrough() {
|
||||
// Write the randomized entrance playthrough to the spoiler log, if applicable
|
||||
static void WriteShuffledEntrances() {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (uint32_t i = 0; i < ctx->GetEntranceShuffler()->playthroughEntrances.size(); ++i) {
|
||||
auto sphereNum = std::to_string(i);
|
||||
std::string sphereString = "sphere ";
|
||||
if (i < 10)
|
||||
sphereString += "0";
|
||||
sphereString += sphereNum;
|
||||
for (size_t i = 0; i < ctx->GetEntranceShuffler()->playthroughEntrances.size(); i++) {
|
||||
std::string sphereString = fmt::format("sphere {:0>2}", i);
|
||||
for (Entrance* entrance : ctx->GetEntranceShuffler()->playthroughEntrances[i]) {
|
||||
WriteShuffledEntrance(sphereString, entrance);
|
||||
}
|
||||
|
||||
@@ -589,14 +589,13 @@ void SetAllEntrancesData() {
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP },
|
||||
NO_RETURN_ENTRANCE },
|
||||
{ { EntranceType::BlueWarp, RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_STAIRS_1, ENTR_GANONS_TOWER_0 },
|
||||
{ { EntranceType::BlueWarp, RR_GANONS_TOWER_STAIRS_1, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, ENTR_OUTSIDE_GANONS_CASTLE_1_2 },
|
||||
NO_RETURN_ENTRANCE },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
for (auto& entrancePair : entranceShuffleTable) {
|
||||
|
||||
auto& forwardEntry = entrancePair.first;
|
||||
auto& returnEntry = entrancePair.second;
|
||||
|
||||
@@ -695,7 +694,6 @@ std::vector<Entrance*> EntranceShuffler::AssumeEntrancePool(std::vector<Entrance
|
||||
}
|
||||
|
||||
static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::vector<EntrancePair>& rollbacks) {
|
||||
|
||||
// Entrances shouldn't connect to their own scene, fail in this situation
|
||||
if (
|
||||
// allow "special" areas to connect to eachother
|
||||
@@ -712,21 +710,19 @@ static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::ve
|
||||
target->GetConnectedRegion()->scene == SCENE_OUTSIDE_GANONS_CASTLE) ||
|
||||
(entrance->GetParentRegion()->scene == SCENE_OUTSIDE_GANONS_CASTLE &&
|
||||
target->GetConnectedRegion()->scene == SCENE_HYRULE_CASTLE))) {
|
||||
auto message = "Entrance " + entrance->GetName() + " attempted to connect with own scene target " +
|
||||
target->to_string() + ". Connection failed.\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("Entrance {} attempted to connect with own scene target {}. Connection failed.",
|
||||
entrance->GetName(), target->to_string());
|
||||
return false;
|
||||
}
|
||||
|
||||
// One way entrances shouldn't lead to the same scene as other already chosen one way entrances
|
||||
auto type = entrance->GetType();
|
||||
const std::vector<EntranceType> oneWayTypes = { EntranceType::OwlDrop, EntranceType::Spawn,
|
||||
EntranceType::WarpSong };
|
||||
const std::array<EntranceType, 3> oneWayTypes = { EntranceType::OwlDrop, EntranceType::Spawn,
|
||||
EntranceType::WarpSong };
|
||||
if (ElementInContainer(type, oneWayTypes)) {
|
||||
for (auto& rollback : rollbacks) {
|
||||
if (rollback.first->GetConnectedRegion()->scene == target->GetConnectedRegion()->scene) {
|
||||
auto message = "A one way entrance already leads to " + target->to_string() + ". Connection failed.\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("A one way entrance already leads to {}. Connection failed.", target->to_string());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -738,8 +734,7 @@ static bool AreEntrancesCompatible(Entrance* entrance, Entrance* target, std::ve
|
||||
// Change connections between an entrance and a target assumed entrance, in order to test the connections afterwards if
|
||||
// necessary
|
||||
static void ChangeConnections(Entrance* entrance, Entrance* targetEntrance) {
|
||||
auto message = "Attempting to connect " + entrance->GetName() + " to " + targetEntrance->to_string() + "\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("Attempting to connect {} to {}", entrance->GetName(), targetEntrance->to_string());
|
||||
entrance->Connect(targetEntrance->Disconnect());
|
||||
entrance->SetReplacement(targetEntrance->GetReplacement());
|
||||
if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) {
|
||||
@@ -791,7 +786,7 @@ static bool EntranceUnreachableAs(Entrance* entrance, uint8_t age, std::vector<E
|
||||
|
||||
static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||
auto ctx = Rando::Context::GetInstance();
|
||||
SPDLOG_DEBUG("Validating world\n");
|
||||
SPDLOG_DEBUG("Validating world");
|
||||
|
||||
// check certain conditions when certain types of ER are enabled
|
||||
EntranceType type = EntranceType::None;
|
||||
@@ -839,13 +834,11 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||
|
||||
if (ElementInContainer(replacementName, childForbidden) &&
|
||||
!EntranceUnreachableAs(entrance, RO_AGE_CHILD, alreadyChecked)) {
|
||||
auto message = replacementName + " is replaced by an entrance with a potential child access\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("{} is replaced by an entrance with a potential child access", replacementName);
|
||||
return false;
|
||||
} else if (ElementInContainer(replacementName, adultForbidden) &&
|
||||
!EntranceUnreachableAs(entrance, RO_AGE_ADULT, alreadyChecked)) {
|
||||
auto message = replacementName + " is replaced by an entrance with a potential adult access\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("{} is replaced by an entrance with a potential adult access", replacementName);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -855,13 +848,11 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||
|
||||
if (ElementInContainer(name, childForbidden) &&
|
||||
!EntranceUnreachableAs(entrance, RO_AGE_CHILD, alreadyChecked)) {
|
||||
auto message = name + " is potentially accessible as child\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("{} is potentially accessible as child", name);
|
||||
return false;
|
||||
} else if (ElementInContainer(name, adultForbidden) &&
|
||||
!EntranceUnreachableAs(entrance, RO_AGE_ADULT, alreadyChecked)) {
|
||||
auto message = name + " is potentially accessible as adult\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("{} is potentially accessible as adult");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -874,13 +865,13 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||
// At least one valid starting region with all basic refills should be reachable without using any items at
|
||||
// the beginning of the seed
|
||||
if (!RegionTable(RR_KOKIRI_FOREST)->HasAccess() && !RegionTable(RR_KAKARIKO_VILLAGE)->HasAccess()) {
|
||||
SPDLOG_DEBUG("Invalid starting area\n");
|
||||
SPDLOG_DEBUG("Invalid starting area");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check that a region where time passes is always reachable as both ages without having collected any items
|
||||
if (!Regions::HasTimePassAccess(RO_AGE_CHILD) || !Regions::HasTimePassAccess(RO_AGE_ADULT)) {
|
||||
SPDLOG_DEBUG("Time passing is not guaranteed as both ages\n");
|
||||
SPDLOG_DEBUG("Time passing is not guaranteed as both ages");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -888,16 +879,16 @@ static bool ValidateWorld(Entrance* entrancePlaced) {
|
||||
// This is important to ensure that the player never loses access to the pedestal after going through time
|
||||
if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_CHILD) &&
|
||||
!RegionTable(RR_TEMPLE_OF_TIME)->Adult()) {
|
||||
SPDLOG_DEBUG("Path to Temple of Time as adult is not guaranteed\n");
|
||||
SPDLOG_DEBUG("Path to Temple of Time as adult is not guaranteed");
|
||||
return false;
|
||||
} else if (ctx->GetOption(RSK_SELECTED_STARTING_AGE).Is(RO_AGE_ADULT) &&
|
||||
!RegionTable(RR_TEMPLE_OF_TIME)->Child()) {
|
||||
SPDLOG_DEBUG("Path to Temple of Time as child is not guaranteed\n");
|
||||
SPDLOG_DEBUG("Path to Temple of Time as child is not guaranteed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
SPDLOG_DEBUG("All Locations NOT REACHABLE\n");
|
||||
SPDLOG_DEBUG("All Locations NOT REACHABLE");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -933,7 +924,6 @@ static void ConfirmReplacement(Entrance* entrance, Entrance* targetEntrance) {
|
||||
}
|
||||
|
||||
bool EntranceShuffler::ReplaceEntrance(Entrance* entrance, Entrance* target, std::vector<EntrancePair>& rollbacks) {
|
||||
|
||||
if (!AreEntrancesCompatible(entrance, target, rollbacks)) {
|
||||
return false;
|
||||
}
|
||||
@@ -941,8 +931,7 @@ bool EntranceShuffler::ReplaceEntrance(Entrance* entrance, Entrance* target, std
|
||||
if (ValidateWorld(entrance)) {
|
||||
#ifdef ENABLE_DEBUG
|
||||
std::string ticks = std::to_string(svcGetSystemTick());
|
||||
auto message = "Dumping World Graph at " + ticks + "\n";
|
||||
// SPDLOG_DEBUG(message);
|
||||
// SPDLOG_DEBUG("Dumping World Graph at {}", ticks);
|
||||
// Regions::DumpWorldGraph(ticks);
|
||||
#endif
|
||||
rollbacks.push_back(EntrancePair{ entrance, target });
|
||||
@@ -951,8 +940,7 @@ bool EntranceShuffler::ReplaceEntrance(Entrance* entrance, Entrance* target, std
|
||||
} else {
|
||||
#ifdef ENABLE_DEBUG
|
||||
std::string ticks = std::to_string(svcGetSystemTick());
|
||||
auto message = "Dumping World Graph at " + ticks + "\n";
|
||||
// SPDLOG_DEBUG(message);
|
||||
// SPDLOG_DEBUG("Dumping World Graph at {}", ticks);
|
||||
// Regions::DumpWorldGraph(ticks);
|
||||
#endif
|
||||
if (entrance->GetConnectedRegionKey() != RR_NONE) {
|
||||
@@ -1006,7 +994,7 @@ bool EntranceShuffler::PlaceOneWayPriorityEntrance(
|
||||
}
|
||||
}
|
||||
}
|
||||
SPDLOG_DEBUG("ERROR: Unable to place priority one-way entrance for " + priorityName + "\n");
|
||||
SPDLOG_DEBUG("ERROR: Unable to place priority one-way entrance for {}", priorityName);
|
||||
assert(false);
|
||||
return false;
|
||||
}
|
||||
@@ -1044,7 +1032,7 @@ bool EntranceShuffler::ShuffleOneWayPriorityEntrances(std::map<std::string, Prio
|
||||
|
||||
if (retryCount <= 0) {
|
||||
SPDLOG_DEBUG(
|
||||
"Entrance placement attempt count for one way priorities exceeded. Restarting randomization completely\n");
|
||||
"Entrance placement attempt count for one way priorities exceeded. Restarting randomization completely");
|
||||
mEntranceShuffleFailure = true;
|
||||
return false;
|
||||
}
|
||||
@@ -1154,9 +1142,8 @@ void EntranceShuffler::ShuffleEntrancePool(std::vector<Entrance*>& entrancePool,
|
||||
if (retries != retryCount) {
|
||||
#ifdef ENABLE_DEBUG
|
||||
std::string ticks = std::to_string(svcGetSystemTick());
|
||||
auto message = "Failed to connect entrances. Retrying " + std::to_string(retries) +
|
||||
" more times.\nDumping World Graph at " + ticks + "\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("Failed to connect entrances. Retrying {} more times.", retries);
|
||||
SPDLOG_DEBUG("Dumping World Graph at {}", ticks);
|
||||
// Regions::DumpWorldGraph(ticks);
|
||||
#endif
|
||||
}
|
||||
@@ -1248,23 +1235,23 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||
if (ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES).Is(RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL)) {
|
||||
entrancePools[EntranceType::Boss] = GetShuffleableEntrances(EntranceType::ChildBoss);
|
||||
AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::AdultBoss));
|
||||
if (ctx->GetOption(RSK_SHUFFLE_GANONS_TOWER_ENTRANCE)) {
|
||||
AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::GanonTower));
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
for (Entrance* entrance : entrancePools[EntranceType::Boss]) {
|
||||
entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse());
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_GANONS_TOWER_ENTRANCE).IsNot(RO_GENERIC_OFF)) {
|
||||
AddElementsToPool(entrancePools[EntranceType::Boss], GetShuffleableEntrances(EntranceType::GanonTower));
|
||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
for (Entrance* entrance : GetShuffleableEntrances(EntranceType::GanonTower)) {
|
||||
entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse());
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss);
|
||||
entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss);
|
||||
if (ctx->GetOption(RSK_SHUFFLE_GANONS_TOWER_ENTRANCE)) {
|
||||
AddElementsToPool(entrancePools[EntranceType::AdultBoss],
|
||||
GetShuffleableEntrances(EntranceType::GanonTower));
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
for (Entrance* entrance : entrancePools[EntranceType::ChildBoss]) {
|
||||
entrancePools[EntranceType::ChildBossReverse].push_back(entrance->GetReverse());
|
||||
@@ -1273,16 +1260,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||
entrancePools[EntranceType::AdultBossReverse].push_back(entrance->GetReverse());
|
||||
}
|
||||
}
|
||||
|
||||
if (ctx->GetOption(RSK_SHUFFLE_GANONS_TOWER_ENTRANCE).IsNot(RO_GENERIC_OFF)) {
|
||||
AddElementsToPool(entrancePools[EntranceType::AdultBoss],
|
||||
GetShuffleableEntrances(EntranceType::GanonTower));
|
||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
for (Entrance* entrance : GetShuffleableEntrances(EntranceType::GanonTower)) {
|
||||
entrancePools[EntranceType::AdultBossReverse].push_back(entrance->GetReverse());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1376,7 +1353,6 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||
std::set<EntranceType> poolsToMix = {};
|
||||
if (ctx->GetOption(RSK_MIX_DUNGEON_ENTRANCES)) {
|
||||
poolsToMix.insert(EntranceType::Dungeon);
|
||||
// Insert reverse entrances when decoupled entrances is on
|
||||
if (ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
poolsToMix.insert(EntranceType::DungeonReverse);
|
||||
}
|
||||
@@ -1553,8 +1529,8 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||
GetEntrance(RR_SPIRIT_TEMPLE_ENTRYWAY, RR_DESERT_COLOSSUS_OUTSIDE_TEMPLE) },
|
||||
{ EntranceNameByRegions(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY),
|
||||
GetEntrance(RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION) },
|
||||
{ EntranceNameByRegions(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR),
|
||||
GetEntrance(RR_GANONS_TOWER_ENTRYWAY, RR_GANONS_TOWER_STAIRS_1) },
|
||||
{ EntranceNameByRegions(RR_GANONS_TOWER_STAIRS_1, RR_GANONS_TOWER_ENTRYWAY),
|
||||
GetEntrance(RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE) }
|
||||
};
|
||||
|
||||
// If a boss room is inside a dungeon entrance (or inside a dungeon which is inside a dungeon entrance), make
|
||||
@@ -1576,8 +1552,8 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||
GetEntrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_DESERT_COLOSSUS) },
|
||||
{ EntranceNameByRegions(RR_SHADOW_TEMPLE_ENTRYWAY, RR_GRAVEYARD_WARP_PAD_REGION),
|
||||
GetEntrance(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION) },
|
||||
{ EntranceNameByRegions(RR_GANONS_TOWER_ENTRYWAY, RR_GANONS_TOWER_STAIRS_1),
|
||||
GetEntrance(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_STAIRS_1) },
|
||||
{ EntranceNameByRegions(RR_GANONS_CASTLE_ENTRYWAY, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE),
|
||||
GetEntrance(RR_GANONS_TOWER_STAIRS_1, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE) }
|
||||
};
|
||||
|
||||
// Pair <BlueWarp exit, BossRoom reverse exit>
|
||||
@@ -1598,8 +1574,8 @@ int EntranceShuffler::ShuffleAllEntrances() {
|
||||
GetEntrance(RR_SPIRIT_TEMPLE_BOSS_ROOM, RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY) },
|
||||
{ GetEntrance(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_GRAVEYARD_WARP_PAD_REGION),
|
||||
GetEntrance(RR_SHADOW_TEMPLE_BOSS_ROOM, RR_SHADOW_TEMPLE_BOSS_ENTRYWAY) },
|
||||
{ GetEntrance(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_STAIRS_1),
|
||||
GetEntrance(RR_GANONS_TOWER_GANONDORF_LAIR, RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR) },
|
||||
{ GetEntrance(RR_GANONS_TOWER_STAIRS_1, RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE),
|
||||
GetEntrance(RR_GANONS_TOWER_STAIRS_1, RR_GANONS_TOWER_ENTRYWAY) }
|
||||
};
|
||||
|
||||
for (EntrancePair pair : bossRoomExitPairs) {
|
||||
@@ -1635,7 +1611,7 @@ void EntranceShuffler::CreateEntranceOverrides() {
|
||||
if (mNoRandomEntrances) {
|
||||
return;
|
||||
}
|
||||
SPDLOG_DEBUG("\nCREATING ENTRANCE OVERRIDES\n");
|
||||
SPDLOG_DEBUG("CREATING ENTRANCE OVERRIDES");
|
||||
auto allShuffleableEntrances = GetShuffleableEntrances(EntranceType::All, false);
|
||||
|
||||
int i = 0;
|
||||
@@ -1644,6 +1620,8 @@ void EntranceShuffler::CreateEntranceOverrides() {
|
||||
// Include blue warps when dungeons or bosses are shuffled
|
||||
bool includeBluewarps =
|
||||
entrance->GetType() == Rando::EntranceType::BlueWarp &&
|
||||
(ctx->GetOption(RSK_SHUFFLE_GANONS_TOWER_ENTRANCE) ||
|
||||
entrance->GetParentRegionKey() != RR_GANONS_TOWER_STAIRS_1) &&
|
||||
(ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES));
|
||||
|
||||
// Double-check to make sure the entrance is actually shuffled
|
||||
@@ -1651,8 +1629,7 @@ void EntranceShuffler::CreateEntranceOverrides() {
|
||||
continue;
|
||||
}
|
||||
|
||||
auto message = "Setting " + entrance->to_string() + "\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("Setting {}", entrance->to_string());
|
||||
|
||||
uint8_t type = (uint8_t)entrance->GetType();
|
||||
int16_t originalIndex = entrance->GetIndex();
|
||||
@@ -1661,8 +1638,7 @@ void EntranceShuffler::CreateEntranceOverrides() {
|
||||
int16_t destinationIndex = -1;
|
||||
int16_t replacementDestinationIndex = -1;
|
||||
|
||||
// Only set destination indices for two way entrances and when decouple entrances
|
||||
// is off
|
||||
// Only set destination indices for two way entrances and when decouple entrances is off
|
||||
if (entrance->GetReverse() != nullptr && !ctx->GetOption(RSK_DECOUPLED_ENTRANCES)) {
|
||||
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||
destinationIndex = entrance->GetReverse()->GetIndex();
|
||||
@@ -1676,10 +1652,8 @@ void EntranceShuffler::CreateEntranceOverrides() {
|
||||
.overrideDestination = replacementDestinationIndex,
|
||||
};
|
||||
|
||||
message = "\tOriginal: " + std::to_string(originalIndex) + "\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
message = "\tReplacement " + std::to_string(replacementIndex) + "\n";
|
||||
SPDLOG_DEBUG(message);
|
||||
SPDLOG_DEBUG("\tOriginal {}", originalIndex);
|
||||
SPDLOG_DEBUG("\tReplacement {}", replacementIndex);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,6 @@ class Entrance {
|
||||
ConditionFn condition_function;
|
||||
|
||||
EntranceType type = EntranceType::None;
|
||||
Entrance* target = nullptr;
|
||||
Entrance* reverse = nullptr;
|
||||
Entrance* assumed = nullptr;
|
||||
Entrance* replacement = nullptr;
|
||||
@@ -105,10 +104,10 @@ class Entrance {
|
||||
bool addedToPool = false;
|
||||
bool decoupled = false;
|
||||
std::string name = "";
|
||||
std::string condition_str = "";
|
||||
// If this is false, areas only spread to interiors through this entrance if there is no other choice
|
||||
// Set to false for owl drops, the windmill path between dampe's grave and windmill and blue warps
|
||||
bool spreadsAreasWithPriority = true;
|
||||
std::string condition_str = "";
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
|
||||
@@ -1188,10 +1188,8 @@ void DumpWorldGraph(std::string str) {
|
||||
} // namespace Regions
|
||||
|
||||
Region* RegionTable(const RandomizerRegion regionKey) {
|
||||
if (regionKey > RR_MAX) {
|
||||
printf("\x1b[1;1HERROR: AREAKEY TOO BIG");
|
||||
}
|
||||
return &(areaTable[regionKey]);
|
||||
assert(regionKey < RR_MAX);
|
||||
return &areaTable[regionKey];
|
||||
}
|
||||
|
||||
// Retrieve all the shuffable entrances of a specific type
|
||||
|
||||
@@ -678,6 +678,8 @@ void RegionTable_Init_GanonsCastle() {
|
||||
//Exits
|
||||
ENTRANCE(RR_GANONS_TOWER_ENTRYWAY, true),
|
||||
ENTRANCE(RR_GANONS_TOWER_FLOOR_1, true),
|
||||
// for imaginary blue warp
|
||||
ENTRANCE(RR_CASTLE_GROUNDS_FROM_GANONS_CASTLE, false),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_TOWER_FLOOR_1] = Region("Ganon's Tower Floor 1", SCENE_GANONS_TOWER, {}, {}, {
|
||||
@@ -686,7 +688,7 @@ void RegionTable_Init_GanonsCastle() {
|
||||
ENTRANCE(RR_GANONS_TOWER_STAIRS_2, AnyAgeTime([]{return logic->CanKillEnemy(RE_DINOLFOS, ED_CLOSE, true, 2);})),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_TOWER_STAIRS_2] = Region("Ganon's Tower Stairs 1", SCENE_GANONS_TOWER, {}, {}, {
|
||||
areaTable[RR_GANONS_TOWER_STAIRS_2] = Region("Ganon's Tower Stairs 2", SCENE_GANONS_TOWER, {}, {}, {
|
||||
//Exits
|
||||
ENTRANCE(RR_GANONS_TOWER_FLOOR_1, true),
|
||||
ENTRANCE(RR_GANONS_TOWER_FLOOR_2, true),
|
||||
@@ -701,7 +703,7 @@ void RegionTable_Init_GanonsCastle() {
|
||||
ENTRANCE(RR_GANONS_TOWER_STAIRS_3, AnyAgeTime([]{return logic->CanKillEnemy(RE_STALFOS, ED_CLOSE, true, 2);})),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_TOWER_STAIRS_3] = Region("Ganon's Tower Stairs 1", SCENE_GANONS_TOWER, {}, {}, {
|
||||
areaTable[RR_GANONS_TOWER_STAIRS_3] = Region("Ganon's Tower Stairs 3", SCENE_GANONS_TOWER, {}, {}, {
|
||||
//Exits
|
||||
ENTRANCE(RR_GANONS_TOWER_FLOOR_2, true),
|
||||
ENTRANCE(RR_GANONS_TOWER_FLOOR_3, true),
|
||||
@@ -713,7 +715,7 @@ void RegionTable_Init_GanonsCastle() {
|
||||
ENTRANCE(RR_GANONS_TOWER_STAIRS_4, AnyAgeTime([]{return logic->CanKillEnemy(RE_IRON_KNUCKLE, ED_CLOSE, true, 2);})),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_TOWER_STAIRS_4] = Region("Ganon's Tower Stairs 1", SCENE_GANONS_TOWER, {}, {}, {
|
||||
areaTable[RR_GANONS_TOWER_STAIRS_4] = Region("Ganon's Tower Stairs 4", SCENE_GANONS_TOWER, {}, {}, {
|
||||
//Exits
|
||||
ENTRANCE(RR_GANONS_TOWER_FLOOR_3, true),
|
||||
ENTRANCE(RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR, true),
|
||||
@@ -751,8 +753,6 @@ void RegionTable_Init_GanonsCastle() {
|
||||
}, {
|
||||
//Exits
|
||||
ENTRANCE(RR_GANONS_CASTLE_ESCAPE, logic->CanKillEnemy(RE_GANONDORF)),
|
||||
ENTRANCE(RR_GANONS_TOWER_BEFORE_GANONDORF_LAIR, false),
|
||||
ENTRANCE(RR_GANONS_TOWER_STAIRS_1, false),
|
||||
});
|
||||
|
||||
areaTable[RR_GANONS_CASTLE_ESCAPE] = Region("Ganon's Castle Escape", SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR, {}, {
|
||||
|
||||
@@ -59,23 +59,21 @@ typedef struct {
|
||||
s16 exit;
|
||||
s16 bossDoor;
|
||||
s16 bossDoorReverse;
|
||||
s16 blueWarp;
|
||||
s16 scene;
|
||||
s16 bossScene;
|
||||
} DungeonEntranceInfo;
|
||||
|
||||
static DungeonEntranceInfo dungeons[] = {
|
||||
// clang-format off
|
||||
//entryway exit, boss, reverse, bluewarp, dungeon scene, boss scene
|
||||
{ ENTR_DEKU_TREE_ENTRANCE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, ENTR_DEKU_TREE_BOSS_ENTRANCE, ENTR_DEKU_TREE_BOSS_DOOR, ENTR_KOKIRI_FOREST_DEKU_TREE_BLUE_WARP, SCENE_DEKU_TREE, SCENE_DEKU_TREE_BOSS },
|
||||
{ ENTR_DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, ENTR_DODONGOS_CAVERN_BOSS_DOOR, ENTR_DEATH_MOUNTAIN_TRAIL_DODONGO_BLUE_WARP, SCENE_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN_BOSS },
|
||||
{ ENTR_JABU_JABU_ENTRANCE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU, ENTR_JABU_JABU_BOSS_ENTRANCE, ENTR_JABU_JABU_BOSS_DOOR, ENTR_ZORAS_FOUNTAIN_JABU_JABU_BLUE_WARP, SCENE_JABU_JABU, SCENE_JABU_JABU_BOSS },
|
||||
{ ENTR_FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, ENTR_FOREST_TEMPLE_BOSS_DOOR, ENTR_SACRED_FOREST_MEADOW_FOREST_TEMPLE_BLUE_WARP, SCENE_FOREST_TEMPLE, SCENE_FOREST_TEMPLE_BOSS },
|
||||
{ ENTR_FIRE_TEMPLE_ENTRANCE, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, ENTR_FIRE_TEMPLE_BOSS_DOOR, ENTR_DEATH_MOUNTAIN_CRATER_FIRE_TEMPLE_BLUE_WARP, SCENE_FIRE_TEMPLE, SCENE_FIRE_TEMPLE_BOSS },
|
||||
{ ENTR_WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, ENTR_WATER_TEMPLE_BOSS_ENTRANCE, ENTR_WATER_TEMPLE_BOSS_DOOR, ENTR_LAKE_HYLIA_WATER_TEMPLE_BLUE_WARP, SCENE_WATER_TEMPLE, SCENE_WATER_TEMPLE_BOSS },
|
||||
{ ENTR_SPIRIT_TEMPLE_ENTRANCE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE, ENTR_SPIRIT_TEMPLE_BOSS_DOOR, ENTR_DESERT_COLOSSUS_SPIRIT_TEMPLE_BLUE_WARP, SCENE_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE_BOSS },
|
||||
{ ENTR_SHADOW_TEMPLE_ENTRANCE, ENTR_GRAVEYARD_OUTSIDE_TEMPLE, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, ENTR_SHADOW_TEMPLE_BOSS_DOOR, ENTR_GRAVEYARD_SHADOW_TEMPLE_BLUE_WARP, SCENE_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE_BOSS },
|
||||
|
||||
//entryway exit, boss, reverse, dungeon scene, boss scene
|
||||
{ ENTR_DEKU_TREE_ENTRANCE, ENTR_KOKIRI_FOREST_OUTSIDE_DEKU_TREE, ENTR_DEKU_TREE_BOSS_ENTRANCE, ENTR_DEKU_TREE_BOSS_DOOR, SCENE_DEKU_TREE, SCENE_DEKU_TREE_BOSS },
|
||||
{ ENTR_DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_OUTSIDE_DODONGOS_CAVERN, ENTR_DODONGOS_CAVERN_BOSS_ENTRANCE, ENTR_DODONGOS_CAVERN_BOSS_DOOR, SCENE_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN_BOSS },
|
||||
{ ENTR_JABU_JABU_ENTRANCE, ENTR_ZORAS_FOUNTAIN_OUTSIDE_JABU_JABU, ENTR_JABU_JABU_BOSS_ENTRANCE, ENTR_JABU_JABU_BOSS_DOOR, SCENE_JABU_JABU, SCENE_JABU_JABU_BOSS },
|
||||
{ ENTR_FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_OUTSIDE_TEMPLE, ENTR_FOREST_TEMPLE_BOSS_ENTRANCE, ENTR_FOREST_TEMPLE_BOSS_DOOR, SCENE_FOREST_TEMPLE, SCENE_FOREST_TEMPLE_BOSS },
|
||||
{ ENTR_FIRE_TEMPLE_ENTRANCE, ENTR_DEATH_MOUNTAIN_CRATER_OUTSIDE_TEMPLE, ENTR_FIRE_TEMPLE_BOSS_ENTRANCE, ENTR_FIRE_TEMPLE_BOSS_DOOR, SCENE_FIRE_TEMPLE, SCENE_FIRE_TEMPLE_BOSS },
|
||||
{ ENTR_WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_OUTSIDE_TEMPLE, ENTR_WATER_TEMPLE_BOSS_ENTRANCE, ENTR_WATER_TEMPLE_BOSS_DOOR, SCENE_WATER_TEMPLE, SCENE_WATER_TEMPLE_BOSS },
|
||||
{ ENTR_SPIRIT_TEMPLE_ENTRANCE, ENTR_DESERT_COLOSSUS_OUTSIDE_TEMPLE, ENTR_SPIRIT_TEMPLE_BOSS_ENTRANCE, ENTR_SPIRIT_TEMPLE_BOSS_DOOR, SCENE_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE_BOSS },
|
||||
{ ENTR_SHADOW_TEMPLE_ENTRANCE, ENTR_GRAVEYARD_OUTSIDE_TEMPLE, ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE, ENTR_SHADOW_TEMPLE_BOSS_DOOR, SCENE_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE_BOSS },
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
@@ -182,7 +180,6 @@ void Entrance_Init(void) {
|
||||
|
||||
// Then overwrite the indices which are shuffled
|
||||
for (size_t i = 0; i < ENTRANCE_OVERRIDES_MAX_COUNT; i++) {
|
||||
|
||||
if (Entrance_EntranceIsNull(&entranceOverrides[i])) {
|
||||
break;
|
||||
}
|
||||
@@ -265,7 +262,6 @@ void Entrance_Init(void) {
|
||||
}
|
||||
|
||||
s16 Entrance_GetOverride(s16 index) {
|
||||
|
||||
// The game sometimes uses special indices from 0x7FF9 -> 0x7FFF for exiting
|
||||
// grottos and fairy fountains. These aren't handled here since the game
|
||||
// naturally handles them later.
|
||||
@@ -273,6 +269,11 @@ s16 Entrance_GetOverride(s16 index) {
|
||||
return index;
|
||||
}
|
||||
|
||||
// special index for fake ganon's castle blue warp
|
||||
if (entranceOverrideTable[index] == ENTR_OUTSIDE_GANONS_CASTLE_1_2) {
|
||||
return ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT;
|
||||
}
|
||||
|
||||
return entranceOverrideTable[index];
|
||||
}
|
||||
|
||||
@@ -325,7 +326,6 @@ u32 Entrance_SceneAndSpawnAre(u8 scene, u8 spawn) {
|
||||
|
||||
// Properly respawn the player after a game over, accounting for dungeon entrance randomizer
|
||||
void Entrance_SetGameOverEntrance(void) {
|
||||
|
||||
s16 scene = gPlayState->sceneNum;
|
||||
|
||||
// When in a boss room and boss shuffle is on, use the boss scene to find the death warp entrance
|
||||
@@ -363,15 +363,14 @@ void Entrance_SetGameOverEntrance(void) {
|
||||
case ENTR_SHADOW_TEMPLE_BOSS_ENTRANCE: // Shadow Temple Boss Room
|
||||
gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_ENTRANCE;
|
||||
return;
|
||||
case ENTR_GANONDORF_BOSS_0: // Ganondorf Boss Room
|
||||
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb
|
||||
case ENTR_GANONDORF_BOSS_0: // Ganondorf Boss Room
|
||||
gSaveContext.entranceIndex = ENTR_INSIDE_GANONS_CASTLE_ENTRANCE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Properly savewarp the player accounting for dungeon entrance randomizer.
|
||||
void Entrance_SetSavewarpEntrance(void) {
|
||||
|
||||
s16 scene = gSaveContext.savedSceneNum;
|
||||
|
||||
// When in a boss room and boss shuffle is on, use the boss scene to find the savewarp entrance
|
||||
@@ -723,14 +722,14 @@ void Entrance_OverrideSpawnScene(s32 sceneNum, s32 spawn) {
|
||||
}
|
||||
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) {
|
||||
// Repair the authentically bugged entrance when leaving Barniades boss room -> JabuJabu's belly
|
||||
// Repair the authentically bugged entrance when leaving Barinade's boss room -> Jabu Jabu's belly
|
||||
// Link's position needs to be adjusted to prevent him from falling through the floor
|
||||
if (sceneNum == SCENE_JABU_JABU && spawn == 1) {
|
||||
modifiedLinkActorEntry.pos.z = 0xF7F4;
|
||||
gPlayState->linkActorEntry = &modifiedLinkActorEntry;
|
||||
}
|
||||
|
||||
// Repair the authentically bugged entrance when leaving Morpha's boass room -> Water Temple
|
||||
// Repair the authentically bugged entrance when leaving Morpha's boss room -> Water Temple
|
||||
// Link's position was at the start of the Water Temple entrance
|
||||
// This updates it to place him in the hallway outside of Morpha's boss room.
|
||||
if (sceneNum == SCENE_WATER_TEMPLE && spawn == 1) {
|
||||
@@ -754,13 +753,13 @@ void Entrance_OverrideSpawnScene(s32 sceneNum, s32 spawn) {
|
||||
|
||||
s32 Entrance_OverrideSpawnSceneRoom(s32 sceneNum, s32 spawn, s32 roomNum) {
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) {
|
||||
// Repair the authentically bugged scene/spawn info for leaving Barinade's boss room -> JabuJabu's belly
|
||||
// Repair the authentically bugged scene/spawn info for leaving Barinade's boss room -> Jabu Jabu's belly
|
||||
// to load the correct room outside Barniade's boss room
|
||||
if (sceneNum == SCENE_JABU_JABU && spawn == 1) {
|
||||
return 5;
|
||||
}
|
||||
|
||||
// Repair the authentically bugged scene/spawn info for leaving Morhpa's boss room -> Water Temple
|
||||
// Repair the authentically bugged scene/spawn info for leaving Morpha's boss room -> Water Temple
|
||||
// to load the correct room for the hallway before Morpha's boss room
|
||||
if (sceneNum == SCENE_WATER_TEMPLE && spawn == 1) {
|
||||
return 11;
|
||||
|
||||
@@ -414,8 +414,9 @@ const EntranceData entranceData[] = {
|
||||
{ ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "OGC Rainbow Bridge Exit", "Inside Ganon's Castle Entrance", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc", 1},
|
||||
{ ENTR_POTION_SHOP_KAKARIKO_1, ENTR_GREAT_FAIRYS_FOUNTAIN_MAGIC_OGC_DD, {{ SCENE_GREAT_FAIRYS_FOUNTAIN_MAGIC, 0x02 }}, "OGC Great Fairy Fountain", "OGC Behind Pillar", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_INTERIOR, "outside ganon's castle"},
|
||||
{ ENTR_CASTLE_GROUNDS_RAINBOW_BRIDGE_EXIT, ENTR_INSIDE_GANONS_CASTLE_ENTRANCE, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Entrance", "OGC Rainbow Bridge Exit", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "outside ganon's castle,gc"},
|
||||
{ ENTR_INSIDE_GANONS_CASTLE_1, ENTR_GANONS_TOWER_0, SINGLE_SCENE_INFO(SCENE_GANONS_TOWER), "Ganon's Tower Entrance", "Inside Ganon's Castle Past Trials", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "gc"},
|
||||
{ ENTR_GANONS_TOWER_0, ENTR_INSIDE_GANONS_CASTLE_1, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle Past Trials", "Ganon's Tower Entrance", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "gc"},
|
||||
{ ENTR_INSIDE_GANONS_CASTLE_1, ENTR_GANONS_TOWER_0, SINGLE_SCENE_INFO(SCENE_GANONS_TOWER), "Ganon's Tower Entrance", "Inside Ganon's Castle", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "gc"},
|
||||
{ ENTR_GANONS_TOWER_0, ENTR_INSIDE_GANONS_CASTLE_1, SINGLE_SCENE_INFO(SCENE_INSIDE_GANONS_CASTLE), "Inside Ganon's Castle", "Ganon's Tower Entrance", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_DUNGEON, "gc"},
|
||||
{ ENTR_OUTSIDE_GANONS_CASTLE_1_2, -1, SINGLE_SCENE_INFO(SCENE_OUTSIDE_GANONS_CASTLE), "Ganon's Blue Warp", "Ganon's Castle Blue Warp", ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_GROUP_HYRULE_CASTLE, ENTRANCE_TYPE_ONE_WAY, "gc,bw", 1},
|
||||
|
||||
// clang-format on
|
||||
};
|
||||
|
||||
@@ -186,7 +186,6 @@ s16 Grotto_GetEntranceValueHandlingGrottoRando(s16 nextEntranceIndex) {
|
||||
// Translates and overrides the passed in entrance index if it corresponds to a
|
||||
// special grotto entrance (grotto load or return point) and updates player respawn data correctly.
|
||||
s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||
|
||||
// Don't change anything unless grotto shuffle has been enabled
|
||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) &&
|
||||
!Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) &&
|
||||
@@ -233,7 +232,6 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||
lastEntranceType = GROTTO_RETURN;
|
||||
// Grotto Loads
|
||||
} else if (nextEntranceIndex >= ENTRANCE_GROTTO_LOAD_START && nextEntranceIndex < ENTRANCE_GROTTO_EXIT_START) {
|
||||
|
||||
// Set the respawn data to load the correct grotto
|
||||
GrottoLoadInfo grotto = grottoLoadTable[grottoId];
|
||||
gSaveContext.respawn[RESPAWN_MODE_RETURN].data = grotto.content;
|
||||
@@ -255,7 +253,6 @@ s16 Grotto_OverrideSpecialEntrance(s16 nextEntranceIndex) {
|
||||
// Override the entrance index when entering into a grotto actor
|
||||
// thisx - pointer to the grotto actor
|
||||
void Grotto_OverrideActorEntrance(Actor* thisx) {
|
||||
|
||||
// Vanilla Behavior if there's no possibility of ending up in a grotto randomly
|
||||
if (!Randomizer_GetSettingValue(RSK_SHUFFLE_GROTTO_ENTRANCES) &&
|
||||
!Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_SPAWNS) &&
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
#include "soh/Enhancements/gameconsole.h"
|
||||
#include "soh/frame_interpolation.h"
|
||||
#include "soh/Enhancements/debugconsole.h"
|
||||
#include "soh/Enhancements/game-interactor/GameInteractor.h"
|
||||
#include <overlays/actors/ovl_En_Niw/z_en_niw.h>
|
||||
#include <overlays/misc/ovl_kaleido_scope/z_kaleido_scope.h>
|
||||
#include "soh/Enhancements/enhancementTypes.h"
|
||||
|
||||
Reference in New Issue
Block a user