mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-25 19:02:19 -05:00
[Rando] Add Mix and Decouple support to Boss Entrances (#3261)
* initial support for mixing boss entrances in the mixed pool * support decouple for boss entrances * missed decouple change * add blue warp exits to boss rooms in location access * add entrance get helper methods * fix assumed targets not using root in entrance name * add dedicated blue warp entrances and handle blue warp changes during generation * change bluewarp handling in game to use unique blue warp entrances * handle blue warps in entrance tracker * fix overriding all jabu and water temple rooms * fix grotto returns when exiting boss rooms/dungeons * fix blue warp logic by tracking original connected region key * use entrance enums * remove unneeded entrance values * fix decouple generation crash * fix jabu mq backwards logic
This commit is contained in:
parent
3187564f5b
commit
13fce8258d
@ -26,7 +26,6 @@ typedef struct {
|
|||||||
AreaKey parentRegion;
|
AreaKey parentRegion;
|
||||||
AreaKey connectedRegion;
|
AreaKey connectedRegion;
|
||||||
int16_t index;
|
int16_t index;
|
||||||
int16_t blueWarp;
|
|
||||||
} EntranceLinkInfo;
|
} EntranceLinkInfo;
|
||||||
|
|
||||||
EntranceLinkInfo NO_RETURN_ENTRANCE = {EntranceType::None, NONE, NONE, -1};
|
EntranceLinkInfo NO_RETURN_ENTRANCE = {EntranceType::None, NONE, NONE, -1};
|
||||||
@ -40,6 +39,11 @@ using EntranceInfoPair = std::pair<EntranceLinkInfo, EntranceLinkInfo>;
|
|||||||
using EntrancePair = std::pair<Entrance*, Entrance*>;
|
using EntrancePair = std::pair<Entrance*, Entrance*>;
|
||||||
using EntrancePools = std::map<EntranceType, std::vector<Entrance*>>;
|
using EntrancePools = std::map<EntranceType, std::vector<Entrance*>>;
|
||||||
|
|
||||||
|
// Construct entrance name from parent and connected region keys
|
||||||
|
std::string EntranceNameByRegions(uint32_t parentRegion, uint32_t connectedRegion) {
|
||||||
|
return AreaTable(parentRegion)->regionName + " -> " + AreaTable(connectedRegion)->regionName;
|
||||||
|
}
|
||||||
|
|
||||||
//The entrance randomization algorithm used here is a direct copy of
|
//The entrance randomization algorithm used here is a direct copy of
|
||||||
//the algorithm used in the original N64 randomizer (except now in C++ instead
|
//the algorithm used in the original N64 randomizer (except now in C++ instead
|
||||||
//of python). It may be easier to understand the algorithm by looking at the
|
//of python). It may be easier to understand the algorithm by looking at the
|
||||||
@ -77,26 +81,22 @@ void SetAllEntrancesData(std::vector<EntranceInfoPair>& entranceShuffleTable) {
|
|||||||
//set data
|
//set data
|
||||||
Entrance* forwardEntrance = AreaTable(forwardEntry.parentRegion)->GetExit(forwardEntry.connectedRegion);
|
Entrance* forwardEntrance = AreaTable(forwardEntry.parentRegion)->GetExit(forwardEntry.connectedRegion);
|
||||||
forwardEntrance->SetIndex(forwardEntry.index);
|
forwardEntrance->SetIndex(forwardEntry.index);
|
||||||
forwardEntrance->SetBlueWarp(forwardEntry.blueWarp);
|
|
||||||
forwardEntrance->SetType(forwardEntry.type);
|
forwardEntrance->SetType(forwardEntry.type);
|
||||||
forwardEntrance->SetAsPrimary();
|
forwardEntrance->SetAsPrimary();
|
||||||
|
|
||||||
// When decouple entrances is on, mark it for entrances except boss rooms
|
// When decouple entrances is on, mark the forward entrance
|
||||||
if (Settings::DecoupleEntrances && forwardEntry.type != EntranceType::ChildBoss &&
|
if (Settings::DecoupleEntrances) {
|
||||||
forwardEntry.type != EntranceType::AdultBoss) {
|
|
||||||
forwardEntrance->SetDecoupled();
|
forwardEntrance->SetDecoupled();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnEntry.parentRegion != NONE) {
|
if (returnEntry.parentRegion != NONE) {
|
||||||
Entrance* returnEntrance = AreaTable(returnEntry.parentRegion)->GetExit(returnEntry.connectedRegion);
|
Entrance* returnEntrance = AreaTable(returnEntry.parentRegion)->GetExit(returnEntry.connectedRegion);
|
||||||
returnEntrance->SetIndex(returnEntry.index);
|
returnEntrance->SetIndex(returnEntry.index);
|
||||||
returnEntrance->SetBlueWarp(returnEntry.blueWarp);
|
|
||||||
returnEntrance->SetType(returnEntry.type);
|
returnEntrance->SetType(returnEntry.type);
|
||||||
forwardEntrance->BindTwoWay(returnEntrance);
|
forwardEntrance->BindTwoWay(returnEntrance);
|
||||||
|
|
||||||
// Mark reverse entrance as decoupled
|
// Mark reverse entrance as decoupled
|
||||||
if (Settings::DecoupleEntrances && returnEntry.type != EntranceType::ChildBoss &&
|
if (Settings::DecoupleEntrances) {
|
||||||
returnEntry.type != EntranceType::AdultBoss) {
|
|
||||||
returnEntrance->SetDecoupled();
|
returnEntrance->SetDecoupled();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -687,23 +687,23 @@ int ShuffleAllEntrances() {
|
|||||||
curNumRandomizedEntrances = 0;
|
curNumRandomizedEntrances = 0;
|
||||||
|
|
||||||
std::vector<EntranceInfoPair> entranceShuffleTable = {
|
std::vector<EntranceInfoPair> entranceShuffleTable = {
|
||||||
//Parent Region Connected Region index blue warp
|
//Parent Region Connected Region index
|
||||||
{{EntranceType::Dungeon, KF_OUTSIDE_DEKU_TREE, DEKU_TREE_ENTRYWAY, 0x0000},
|
{{EntranceType::Dungeon, KF_OUTSIDE_DEKU_TREE, DEKU_TREE_ENTRYWAY, 0x0000},
|
||||||
{EntranceType::Dungeon, DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE, 0x0209, 0x0457}},
|
{EntranceType::Dungeon, DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE, 0x0209}},
|
||||||
{{EntranceType::Dungeon, DEATH_MOUNTAIN_TRAIL, DODONGOS_CAVERN_ENTRYWAY, 0x0004},
|
{{EntranceType::Dungeon, DEATH_MOUNTAIN_TRAIL, DODONGOS_CAVERN_ENTRYWAY, 0x0004},
|
||||||
{EntranceType::Dungeon, DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL, 0x0242, 0x047A}},
|
{EntranceType::Dungeon, DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL, 0x0242}},
|
||||||
{{EntranceType::Dungeon, ZORAS_FOUNTAIN, JABU_JABUS_BELLY_ENTRYWAY, 0x0028},
|
{{EntranceType::Dungeon, ZORAS_FOUNTAIN, JABU_JABUS_BELLY_ENTRYWAY, 0x0028},
|
||||||
{EntranceType::Dungeon, JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN, 0x0221, 0x010E}},
|
{EntranceType::Dungeon, JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN, 0x0221}},
|
||||||
{{EntranceType::Dungeon, SACRED_FOREST_MEADOW, FOREST_TEMPLE_ENTRYWAY, 0x0169},
|
{{EntranceType::Dungeon, SACRED_FOREST_MEADOW, FOREST_TEMPLE_ENTRYWAY, 0x0169},
|
||||||
{EntranceType::Dungeon, FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW, 0x0215, 0x0608}},
|
{EntranceType::Dungeon, FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW, 0x0215}},
|
||||||
{{EntranceType::Dungeon, DMC_CENTRAL_LOCAL, FIRE_TEMPLE_ENTRYWAY, 0x0165},
|
{{EntranceType::Dungeon, DMC_CENTRAL_LOCAL, FIRE_TEMPLE_ENTRYWAY, 0x0165},
|
||||||
{EntranceType::Dungeon, FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL, 0x024A, 0x0564}},
|
{EntranceType::Dungeon, FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL, 0x024A}},
|
||||||
{{EntranceType::Dungeon, LAKE_HYLIA, WATER_TEMPLE_ENTRYWAY, 0x0010},
|
{{EntranceType::Dungeon, LAKE_HYLIA, WATER_TEMPLE_ENTRYWAY, 0x0010},
|
||||||
{EntranceType::Dungeon, WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA, 0x021D, 0x060C}},
|
{EntranceType::Dungeon, WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA, 0x021D}},
|
||||||
{{EntranceType::Dungeon, DESERT_COLOSSUS, SPIRIT_TEMPLE_ENTRYWAY, 0x0082},
|
{{EntranceType::Dungeon, DESERT_COLOSSUS, SPIRIT_TEMPLE_ENTRYWAY, 0x0082},
|
||||||
{EntranceType::Dungeon, SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1, 0x0610}},
|
{EntranceType::Dungeon, SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY, 0x01E1}},
|
||||||
{{EntranceType::Dungeon, GRAVEYARD_WARP_PAD_REGION, SHADOW_TEMPLE_ENTRYWAY, 0x0037},
|
{{EntranceType::Dungeon, GRAVEYARD_WARP_PAD_REGION, SHADOW_TEMPLE_ENTRYWAY, 0x0037},
|
||||||
{EntranceType::Dungeon, SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION, 0x0205, 0x0580}},
|
{EntranceType::Dungeon, SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION, 0x0205}},
|
||||||
{{EntranceType::Dungeon, KAKARIKO_VILLAGE, BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098},
|
{{EntranceType::Dungeon, KAKARIKO_VILLAGE, BOTTOM_OF_THE_WELL_ENTRYWAY, 0x0098},
|
||||||
{EntranceType::Dungeon, BOTTOM_OF_THE_WELL_ENTRYWAY, KAKARIKO_VILLAGE, 0x02A6}},
|
{EntranceType::Dungeon, BOTTOM_OF_THE_WELL_ENTRYWAY, KAKARIKO_VILLAGE, 0x02A6}},
|
||||||
{{EntranceType::Dungeon, ZORAS_FOUNTAIN, ICE_CAVERN_ENTRYWAY, 0x0088},
|
{{EntranceType::Dungeon, ZORAS_FOUNTAIN, ICE_CAVERN_ENTRYWAY, 0x0088},
|
||||||
@ -947,21 +947,30 @@ int ShuffleAllEntrances() {
|
|||||||
{{EntranceType::WarpSong, PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME, 0x05F4}, NO_RETURN_ENTRANCE},
|
{{EntranceType::WarpSong, PRELUDE_OF_LIGHT_WARP, TEMPLE_OF_TIME, 0x05F4}, NO_RETURN_ENTRANCE},
|
||||||
|
|
||||||
{{EntranceType::ChildBoss, DEKU_TREE_BOSS_ENTRYWAY, DEKU_TREE_BOSS_ROOM, 0x040F},
|
{{EntranceType::ChildBoss, DEKU_TREE_BOSS_ENTRYWAY, DEKU_TREE_BOSS_ROOM, 0x040F},
|
||||||
{EntranceType::ChildBoss, DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY, 0x0252, 0x0457}},
|
{EntranceType::ChildBoss, DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY, 0x0252}},
|
||||||
{{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ENTRYWAY, DODONGOS_CAVERN_BOSS_ROOM, 0x040B},
|
{{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ENTRYWAY, DODONGOS_CAVERN_BOSS_ROOM, 0x040B},
|
||||||
{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5, 0x047A}},
|
{EntranceType::ChildBoss, DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY, 0x00C5}},
|
||||||
{{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ENTRYWAY, JABU_JABUS_BELLY_BOSS_ROOM, 0x0301},
|
{{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ENTRYWAY, JABU_JABUS_BELLY_BOSS_ROOM, 0x0301},
|
||||||
{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407, 0x010E}},
|
{EntranceType::ChildBoss, JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY, 0x0407}},
|
||||||
{{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ENTRYWAY, FOREST_TEMPLE_BOSS_ROOM, 0x000C},
|
{{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ENTRYWAY, FOREST_TEMPLE_BOSS_ROOM, 0x000C},
|
||||||
{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E, 0x0608}},
|
{EntranceType::AdultBoss, FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY, 0x024E}},
|
||||||
{{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ENTRYWAY, FIRE_TEMPLE_BOSS_ROOM, 0x0305},
|
{{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ENTRYWAY, FIRE_TEMPLE_BOSS_ROOM, 0x0305},
|
||||||
{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175, 0x0564}},
|
{EntranceType::AdultBoss, FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY, 0x0175}},
|
||||||
{{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ENTRYWAY, WATER_TEMPLE_BOSS_ROOM, 0x0417},
|
{{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ENTRYWAY, WATER_TEMPLE_BOSS_ROOM, 0x0417},
|
||||||
{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423, 0x060C}},
|
{EntranceType::AdultBoss, WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY, 0x0423}},
|
||||||
{{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ENTRYWAY, SPIRIT_TEMPLE_BOSS_ROOM, 0x008D},
|
{{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ENTRYWAY, SPIRIT_TEMPLE_BOSS_ROOM, 0x008D},
|
||||||
{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5, 0x0610}},
|
{EntranceType::AdultBoss, SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY, 0x02F5}},
|
||||||
{{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ENTRYWAY, SHADOW_TEMPLE_BOSS_ROOM, 0x0413},
|
{{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ENTRYWAY, SHADOW_TEMPLE_BOSS_ROOM, 0x0413},
|
||||||
{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2, 0x0580}},
|
{EntranceType::AdultBoss, SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY, 0x02B2}},
|
||||||
|
|
||||||
|
{{EntranceType::BlueWarp, DEKU_TREE_BOSS_ROOM, KF_OUTSIDE_DEKU_TREE, 0x0457}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::BlueWarp, DODONGOS_CAVERN_BOSS_ROOM, DEATH_MOUNTAIN_TRAIL, 0x047A}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::BlueWarp, JABU_JABUS_BELLY_BOSS_ROOM, ZORAS_FOUNTAIN, 0x010E}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::BlueWarp, FOREST_TEMPLE_BOSS_ROOM, SACRED_FOREST_MEADOW, 0x0608}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::BlueWarp, FIRE_TEMPLE_BOSS_ROOM, DMC_CENTRAL_LOCAL, 0x0564}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::BlueWarp, WATER_TEMPLE_BOSS_ROOM, LAKE_HYLIA, 0x060C}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::BlueWarp, SPIRIT_TEMPLE_BOSS_ROOM, DESERT_COLOSSUS, 0x0610}, NO_RETURN_ENTRANCE},
|
||||||
|
{{EntranceType::BlueWarp, SHADOW_TEMPLE_BOSS_ROOM, GRAVEYARD_WARP_PAD_REGION, 0x0580}, NO_RETURN_ENTRANCE},
|
||||||
};
|
};
|
||||||
|
|
||||||
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
|
std::map<std::string, PriorityEntrance> priorityEntranceTable = {
|
||||||
@ -1011,6 +1020,11 @@ int ShuffleAllEntrances() {
|
|||||||
FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY &&
|
FilterAndEraseFromPool(entrancePools[EntranceType::Boss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY &&
|
||||||
entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;});
|
entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;});
|
||||||
}
|
}
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
|
for (Entrance* entrance : entrancePools[EntranceType::Boss]) {
|
||||||
|
entrancePools[EntranceType::BossReverse].push_back(entrance->GetReverse());
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss);
|
entrancePools[EntranceType::ChildBoss] = GetShuffleableEntrances(EntranceType::ChildBoss);
|
||||||
entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss);
|
entrancePools[EntranceType::AdultBoss] = GetShuffleableEntrances(EntranceType::AdultBoss);
|
||||||
@ -1019,6 +1033,14 @@ int ShuffleAllEntrances() {
|
|||||||
FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY &&
|
FilterAndEraseFromPool(entrancePools[EntranceType::ChildBoss], [](const Entrance* entrance){return entrance->GetParentRegionKey() == DEKU_TREE_BOSS_ENTRYWAY &&
|
||||||
entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;});
|
entrance->GetConnectedRegionKey() == DEKU_TREE_BOSS_ROOM;});
|
||||||
}
|
}
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
|
for (Entrance* entrance : entrancePools[EntranceType::ChildBoss]) {
|
||||||
|
entrancePools[EntranceType::ChildBossReverse].push_back(entrance->GetReverse());
|
||||||
|
}
|
||||||
|
for (Entrance* entrance : entrancePools[EntranceType::AdultBoss]) {
|
||||||
|
entrancePools[EntranceType::AdultBossReverse].push_back(entrance->GetReverse());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,10 +1104,13 @@ int ShuffleAllEntrances() {
|
|||||||
SetShuffledEntrances(oneWayEntrancePools);
|
SetShuffledEntrances(oneWayEntrancePools);
|
||||||
|
|
||||||
//combine entrance pools if mixing pools. Only continue if more than one pool is selected.
|
//combine entrance pools if mixing pools. Only continue if more than one pool is selected.
|
||||||
int totalMixedPools = (Settings::MixDungeons ? 1 : 0) + (Settings::MixOverworld ? 1 : 0) + (Settings::MixInteriors ? 1 : 0) + (Settings::MixGrottos ? 1 : 0);
|
int totalMixedPools = (Settings::MixDungeons ? 1 : 0) + (Settings::MixBosses ? 1 : 0) +
|
||||||
|
(Settings::MixOverworld ? 1 : 0) + (Settings::MixInteriors ? 1 : 0) +
|
||||||
|
(Settings::MixGrottos ? 1 : 0);
|
||||||
if (totalMixedPools < 2) {
|
if (totalMixedPools < 2) {
|
||||||
Settings::MixedEntrancePools.SetSelectedIndex(OFF);
|
Settings::MixedEntrancePools.SetSelectedIndex(OFF);
|
||||||
Settings::MixDungeons.SetSelectedIndex(OFF);
|
Settings::MixDungeons.SetSelectedIndex(OFF);
|
||||||
|
Settings::MixBosses.SetSelectedIndex(OFF);
|
||||||
Settings::MixOverworld.SetSelectedIndex(OFF);
|
Settings::MixOverworld.SetSelectedIndex(OFF);
|
||||||
Settings::MixInteriors.SetSelectedIndex(OFF);
|
Settings::MixInteriors.SetSelectedIndex(OFF);
|
||||||
Settings::MixGrottos.SetSelectedIndex(OFF);
|
Settings::MixGrottos.SetSelectedIndex(OFF);
|
||||||
@ -1099,6 +1124,12 @@ int ShuffleAllEntrances() {
|
|||||||
poolsToMix.insert(EntranceType::DungeonReverse);
|
poolsToMix.insert(EntranceType::DungeonReverse);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (Settings::MixBosses) {
|
||||||
|
poolsToMix.insert(EntranceType::Boss);
|
||||||
|
if (Settings::DecoupleEntrances) {
|
||||||
|
poolsToMix.insert(EntranceType::BossReverse);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Settings::MixOverworld) {
|
if (Settings::MixOverworld) {
|
||||||
poolsToMix.insert(EntranceType::Overworld);
|
poolsToMix.insert(EntranceType::Overworld);
|
||||||
}
|
}
|
||||||
@ -1232,6 +1263,87 @@ int ShuffleAllEntrances() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Determine blue warp targets
|
||||||
|
if (true /* Settings.BlueWarps.Is(BLUEWARPS_DUNGEON) */) { // RANDOTODO: add bluewarp shuffle
|
||||||
|
// 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(DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE)) },
|
||||||
|
{ EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL)) },
|
||||||
|
{ EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN)) },
|
||||||
|
{ EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW)) },
|
||||||
|
{ EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL)) },
|
||||||
|
{ EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA)) },
|
||||||
|
{ EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY)) },
|
||||||
|
{ EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION)) },
|
||||||
|
};
|
||||||
|
|
||||||
|
// If a boss room is inside a dungeon entrance (or inside a dungeon which is inside a dungeon entrance), make the blue warp go to that dungeon's blue warp target
|
||||||
|
std::map<std::string, Entrance*> dungeonExits = {
|
||||||
|
{ EntranceNameByRegions(DEKU_TREE_ENTRYWAY, KF_OUTSIDE_DEKU_TREE),
|
||||||
|
GetEntrance(EntranceNameByRegions(DEKU_TREE_BOSS_ROOM, KF_OUTSIDE_DEKU_TREE)) },
|
||||||
|
{ EntranceNameByRegions(DODONGOS_CAVERN_ENTRYWAY, DEATH_MOUNTAIN_TRAIL),
|
||||||
|
GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DEATH_MOUNTAIN_TRAIL)) },
|
||||||
|
{ EntranceNameByRegions(JABU_JABUS_BELLY_ENTRYWAY, ZORAS_FOUNTAIN),
|
||||||
|
GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, ZORAS_FOUNTAIN)) },
|
||||||
|
{ EntranceNameByRegions(FOREST_TEMPLE_ENTRYWAY, SACRED_FOREST_MEADOW),
|
||||||
|
GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, SACRED_FOREST_MEADOW)) },
|
||||||
|
{ EntranceNameByRegions(FIRE_TEMPLE_ENTRYWAY, DMC_CENTRAL_LOCAL),
|
||||||
|
GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, DMC_CENTRAL_LOCAL)) },
|
||||||
|
{ EntranceNameByRegions(WATER_TEMPLE_ENTRYWAY, LAKE_HYLIA),
|
||||||
|
GetEntrance(EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, LAKE_HYLIA)) },
|
||||||
|
{ EntranceNameByRegions(SPIRIT_TEMPLE_ENTRYWAY, DESERT_COLOSSUS_FROM_SPIRIT_ENTRYWAY),
|
||||||
|
GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, DESERT_COLOSSUS)) },
|
||||||
|
{ EntranceNameByRegions(SHADOW_TEMPLE_ENTRYWAY, GRAVEYARD_WARP_PAD_REGION),
|
||||||
|
GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, GRAVEYARD_WARP_PAD_REGION)) },
|
||||||
|
};
|
||||||
|
|
||||||
|
// Pair <BlueWarp exit, BossRoom reverse exit>
|
||||||
|
std::vector<EntrancePair> bossRoomExitPairs = {
|
||||||
|
{ GetEntrance(EntranceNameByRegions(DEKU_TREE_BOSS_ROOM, KF_OUTSIDE_DEKU_TREE)),
|
||||||
|
GetEntrance(EntranceNameByRegions(DEKU_TREE_BOSS_ROOM, DEKU_TREE_BOSS_ENTRYWAY)) },
|
||||||
|
{ GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DEATH_MOUNTAIN_TRAIL)),
|
||||||
|
GetEntrance(EntranceNameByRegions(DODONGOS_CAVERN_BOSS_ROOM, DODONGOS_CAVERN_BOSS_ENTRYWAY)) },
|
||||||
|
{ GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, ZORAS_FOUNTAIN)),
|
||||||
|
GetEntrance(EntranceNameByRegions(JABU_JABUS_BELLY_BOSS_ROOM, JABU_JABUS_BELLY_BOSS_ENTRYWAY)) },
|
||||||
|
{ GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, SACRED_FOREST_MEADOW)),
|
||||||
|
GetEntrance(EntranceNameByRegions(FOREST_TEMPLE_BOSS_ROOM, FOREST_TEMPLE_BOSS_ENTRYWAY)) },
|
||||||
|
{ GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, DMC_CENTRAL_LOCAL)),
|
||||||
|
GetEntrance(EntranceNameByRegions(FIRE_TEMPLE_BOSS_ROOM, FIRE_TEMPLE_BOSS_ENTRYWAY)) },
|
||||||
|
{ GetEntrance(EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, LAKE_HYLIA)),
|
||||||
|
GetEntrance(EntranceNameByRegions(WATER_TEMPLE_BOSS_ROOM, WATER_TEMPLE_BOSS_ENTRYWAY)) },
|
||||||
|
{ GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, DESERT_COLOSSUS)),
|
||||||
|
GetEntrance(EntranceNameByRegions(SPIRIT_TEMPLE_BOSS_ROOM, SPIRIT_TEMPLE_BOSS_ENTRYWAY)) },
|
||||||
|
{ GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, GRAVEYARD_WARP_PAD_REGION)),
|
||||||
|
GetEntrance(EntranceNameByRegions(SHADOW_TEMPLE_BOSS_ROOM, SHADOW_TEMPLE_BOSS_ENTRYWAY)) },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (EntrancePair pair : bossRoomExitPairs) {
|
||||||
|
Entrance* target = pair.second->GetReplacement() != nullptr ? pair.second->GetReplacement() : pair.second;
|
||||||
|
|
||||||
|
if (!Settings::DecoupleEntrances) {
|
||||||
|
while (bossExits.find(target->GetName()) != bossExits.end()) {
|
||||||
|
Entrance* next = bossExits.at(target->GetName());
|
||||||
|
target = next->GetReplacement() != nullptr ? next->GetReplacement() : next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dungeonExits.find(target->GetName()) != dungeonExits.end()) {
|
||||||
|
target = dungeonExits.at(target->GetName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pair.first->Connect(target->GetOriginalConnectedRegionKey());
|
||||||
|
pair.first->SetReplacement(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Validate the world one last time to ensure all special conditions are still valid
|
// Validate the world one last time to ensure all special conditions are still valid
|
||||||
if (!ValidateWorld(nullptr)) {
|
if (!ValidateWorld(nullptr)) {
|
||||||
return ENTRANCE_SHUFFLE_FAILURE;
|
return ENTRANCE_SHUFFLE_FAILURE;
|
||||||
@ -1259,8 +1371,8 @@ void CreateEntranceOverrides() {
|
|||||||
auto message = "Setting " + entrance->to_string() + "\n";
|
auto message = "Setting " + entrance->to_string() + "\n";
|
||||||
SPDLOG_DEBUG(message);
|
SPDLOG_DEBUG(message);
|
||||||
|
|
||||||
|
uint8_t type = (uint8_t)entrance->GetType();
|
||||||
int16_t originalIndex = entrance->GetIndex();
|
int16_t originalIndex = entrance->GetIndex();
|
||||||
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
|
||||||
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
||||||
|
|
||||||
int16_t destinationIndex = -1;
|
int16_t destinationIndex = -1;
|
||||||
@ -1274,9 +1386,9 @@ void CreateEntranceOverrides() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
entranceOverrides.push_back({
|
entranceOverrides.push_back({
|
||||||
|
.type = type,
|
||||||
.index = originalIndex,
|
.index = originalIndex,
|
||||||
.destination = destinationIndex,
|
.destination = destinationIndex,
|
||||||
.blueWarp = originalBlueWarp,
|
|
||||||
.override = replacementIndex,
|
.override = replacementIndex,
|
||||||
.overrideDestination = replacementDestinationIndex,
|
.overrideDestination = replacementDestinationIndex,
|
||||||
});
|
});
|
||||||
|
@ -18,12 +18,16 @@ enum class EntranceType {
|
|||||||
OwlDrop,
|
OwlDrop,
|
||||||
Spawn,
|
Spawn,
|
||||||
WarpSong,
|
WarpSong,
|
||||||
|
BlueWarp,
|
||||||
Dungeon,
|
Dungeon,
|
||||||
GanonDungeon,
|
GanonDungeon,
|
||||||
DungeonReverse,
|
DungeonReverse,
|
||||||
Boss,
|
Boss,
|
||||||
|
BossReverse,
|
||||||
ChildBoss,
|
ChildBoss,
|
||||||
|
ChildBossReverse,
|
||||||
AdultBoss,
|
AdultBoss,
|
||||||
|
AdultBossReverse,
|
||||||
Interior,
|
Interior,
|
||||||
InteriorReverse,
|
InteriorReverse,
|
||||||
SpecialInterior,
|
SpecialInterior,
|
||||||
@ -40,6 +44,7 @@ public:
|
|||||||
|
|
||||||
Entrance(uint32_t connectedRegion_, std::vector<ConditionFn> conditions_met_)
|
Entrance(uint32_t connectedRegion_, std::vector<ConditionFn> conditions_met_)
|
||||||
: connectedRegion(connectedRegion_) {
|
: connectedRegion(connectedRegion_) {
|
||||||
|
originalConnectedRegion = connectedRegion_;
|
||||||
conditions_met.resize(2);
|
conditions_met.resize(2);
|
||||||
for (size_t i = 0; i < conditions_met_.size(); i++) {
|
for (size_t i = 0; i < conditions_met_.size(); i++) {
|
||||||
conditions_met[i] = conditions_met_[i];
|
conditions_met[i] = conditions_met_[i];
|
||||||
@ -134,6 +139,10 @@ public:
|
|||||||
return connectedRegion;
|
return connectedRegion;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t GetOriginalConnectedRegionKey() const {
|
||||||
|
return originalConnectedRegion;
|
||||||
|
}
|
||||||
|
|
||||||
Area* GetConnectedRegion() const {
|
Area* GetConnectedRegion() const {
|
||||||
return AreaTable(connectedRegion);
|
return AreaTable(connectedRegion);
|
||||||
}
|
}
|
||||||
@ -198,14 +207,6 @@ public:
|
|||||||
index = newIndex;
|
index = newIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
int16_t GetBlueWarp() const {
|
|
||||||
return blueWarp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetBlueWarp(int16_t newBlueWarp) {
|
|
||||||
blueWarp = newBlueWarp;
|
|
||||||
}
|
|
||||||
|
|
||||||
Entrance* GetAssumed() const {
|
Entrance* GetAssumed() const {
|
||||||
return assumed;
|
return assumed;
|
||||||
}
|
}
|
||||||
@ -251,7 +252,7 @@ public:
|
|||||||
AreaTable(ROOT)->AddExit(ROOT, connectedRegion, []{return true;});
|
AreaTable(ROOT)->AddExit(ROOT, connectedRegion, []{return true;});
|
||||||
Entrance* targetEntrance = AreaTable(ROOT)->GetExit(connectedRegion);
|
Entrance* targetEntrance = AreaTable(ROOT)->GetExit(connectedRegion);
|
||||||
targetEntrance->SetReplacement(this);
|
targetEntrance->SetReplacement(this);
|
||||||
targetEntrance->SetName(GetParentRegion()->regionName + " -> " + GetConnectedRegion()->regionName);
|
targetEntrance->SetName(AreaTable(ROOT)->regionName + " -> " + GetConnectedRegion()->regionName);
|
||||||
return targetEntrance;
|
return targetEntrance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -266,6 +267,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
uint32_t parentRegion;
|
uint32_t parentRegion;
|
||||||
uint32_t connectedRegion;
|
uint32_t connectedRegion;
|
||||||
|
uint32_t originalConnectedRegion;
|
||||||
std::vector<ConditionFn> conditions_met;
|
std::vector<ConditionFn> conditions_met;
|
||||||
|
|
||||||
//Entrance Randomizer stuff
|
//Entrance Randomizer stuff
|
||||||
@ -275,7 +277,6 @@ private:
|
|||||||
Entrance* assumed = nullptr;
|
Entrance* assumed = nullptr;
|
||||||
Entrance* replacement = nullptr;
|
Entrance* replacement = nullptr;
|
||||||
int16_t index = 0xFFFF;
|
int16_t index = 0xFFFF;
|
||||||
int16_t blueWarp = 0;
|
|
||||||
bool shuffled = false;
|
bool shuffled = false;
|
||||||
bool primary = false;
|
bool primary = false;
|
||||||
bool addedToPool = false;
|
bool addedToPool = false;
|
||||||
@ -285,6 +286,7 @@ private:
|
|||||||
|
|
||||||
int ShuffleAllEntrances();
|
int ShuffleAllEntrances();
|
||||||
void CreateEntranceOverrides();
|
void CreateEntranceOverrides();
|
||||||
|
std::string EntranceNameByRegions(uint32_t parentRegion, uint32_t connectedRegion);
|
||||||
|
|
||||||
extern std::vector<std::list<Entrance*>> playthroughEntrances;
|
extern std::vector<std::list<Entrance*>> playthroughEntrances;
|
||||||
extern bool noRandomEntrances;
|
extern bool noRandomEntrances;
|
||||||
|
@ -294,7 +294,12 @@ std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowe
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add shuffled entrances to the entrance playthrough
|
// Add shuffled entrances to the entrance playthrough
|
||||||
if (mode == SearchMode::GeneratePlaythrough && exit.IsShuffled() && !exit.IsAddedToPool() && !noRandomEntrances) {
|
// Include bluewarps when unshuffled but dungeon or boss shuffle is on
|
||||||
|
if (mode == SearchMode::GeneratePlaythrough &&
|
||||||
|
(exit.IsShuffled() || (exit.GetType() == EntranceType::BlueWarp &&
|
||||||
|
(Settings::ShuffleDungeonEntrances.IsNot(SHUFFLEDUNGEONS_OFF) ||
|
||||||
|
Settings::ShuffleBossEntrances.IsNot(SHUFFLEBOSSES_OFF)))) &&
|
||||||
|
!exit.IsAddedToPool() && !noRandomEntrances) {
|
||||||
entranceSphere.push_back(&exit);
|
entranceSphere.push_back(&exit);
|
||||||
exit.AddToPool();
|
exit.AddToPool();
|
||||||
// Don't list a two-way coupled entrance from both directions
|
// Don't list a two-way coupled entrance from both directions
|
||||||
|
@ -503,3 +503,16 @@ std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrima
|
|||||||
}
|
}
|
||||||
return entrancesToShuffle;
|
return entrancesToShuffle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the specific entrance by name
|
||||||
|
Entrance* GetEntrance(const std::string name) {
|
||||||
|
for (uint32_t area : Areas::GetAllAreas()) {
|
||||||
|
for (auto& exit : AreaTable(area)->exits) {
|
||||||
|
if (exit.GetName() == name) {
|
||||||
|
return &exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
@ -242,6 +242,7 @@ namespace Areas {
|
|||||||
void AreaTable_Init();
|
void AreaTable_Init();
|
||||||
Area* AreaTable(const uint32_t areaKey);
|
Area* AreaTable(const uint32_t areaKey);
|
||||||
std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrimary = true);
|
std::vector<Entrance*> GetShuffleableEntrances(EntranceType type, bool onlyPrimary = true);
|
||||||
|
Entrance* GetEntrance(const std::string name);
|
||||||
|
|
||||||
// Overworld
|
// Overworld
|
||||||
void AreaTable_Init_LostWoods();
|
void AreaTable_Init_LostWoods();
|
||||||
|
@ -267,5 +267,6 @@ void AreaTable_Init_DekuTree() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(DEKU_TREE_BOSS_ENTRYWAY, { [] { return true; } }),
|
Entrance(DEKU_TREE_BOSS_ENTRYWAY, { [] { return true; } }),
|
||||||
|
Entrance(KF_OUTSIDE_DEKU_TREE, { [] { return DekuTreeClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -309,5 +309,6 @@ void AreaTable_Init_DodongosCavern() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, { [] { return true; } }),
|
Entrance(DODONGOS_CAVERN_BOSS_ENTRYWAY, { [] { return true; } }),
|
||||||
|
Entrance(DEATH_MOUNTAIN_TRAIL, { [] { return DodongosCavernClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -420,5 +420,6 @@ void AreaTable_Init_FireTemple() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
Entrance(FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||||
|
Entrance(DMC_CENTRAL_LOCAL, { [] { return FireTempleClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -433,5 +433,6 @@ void AreaTable_Init_ForestTemple() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
Entrance(FOREST_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||||
|
Entrance(SACRED_FOREST_MEADOW, { [] { return ForestTempleClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -179,17 +179,17 @@ void AreaTable_Init_JabuJabusBelly() {
|
|||||||
//Locations
|
//Locations
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, {[]{return (IsAdult && (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT))) || ChildCanAccess(JABU_JABUS_BELLY_MQ_BOSS_AREA);}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, {[]{return (IsAdult && (CanUse(HOVER_BOOTS) || CanUse(HOOKSHOT))) || ChildCanAccess(JABU_JABUS_BELLY_MQ_BOSS_AREA);}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_COMPASS_CHEST, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_COMPASS_CHEST, {[]{return (IsChild || CanDive || CanUse(IRON_BOOTS) || LogicJabuAlcoveJumpDive) && (CanUse(SLINGSHOT) || CanUse(BOW) || CanUse(HOOKSHOT) || HasBombchus || (LogicJabuMQRangJump && CanUse(BOOMERANG)));}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return CanUse(SLINGSHOT);}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return CanUse(SLINGSHOT);}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return CanUse(KOKIRI_SWORD) || CanUse(MASTER_SWORD) || CanUse(BIGGORON_SWORD) || CanUse(MEGATON_HAMMER) || CanUse(SLINGSHOT) || CanUse(BOW) || CanUse(STICKS) || Bombs;}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG));}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG));}}),
|
||||||
//Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG))
|
//Trick: CanPlay(SongOfTime) || (LogicJabuMQSoTGS && IsChild && CanUse(BOOMERANG))
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
|
Entrance(JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
|
||||||
Entrance(JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return HasExplosives && IsChild && CanUse(BOOMERANG);}}),
|
Entrance(JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return HasExplosives && CanUse(SLINGSHOT) && CanUse(BOOMERANG);}}),
|
||||||
});
|
});
|
||||||
|
|
||||||
areaTable[JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
|
areaTable[JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
|
||||||
@ -209,8 +209,8 @@ void AreaTable_Init_JabuJabusBelly() {
|
|||||||
}, {
|
}, {
|
||||||
//Locations
|
//Locations
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_COW, {[]{return CanPlay(EponasSong);}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_COW, {[]{return CanPlay(EponasSong);}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return CanUse(SLINGSHOT);}}),
|
||||||
LocationAccess(JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}),
|
LocationAccess(JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return CanUse(BOOMERANG) || (LogicJabuNearBossRanged && CanUse(HOOKSHOT));}}),
|
||||||
}, {
|
}, {
|
||||||
//Exits
|
//Exits
|
||||||
Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
|
Entrance(JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
|
||||||
@ -245,5 +245,6 @@ void AreaTable_Init_JabuJabusBelly() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }),
|
Entrance(JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||||
|
Entrance(ZORAS_FOUNTAIN, { [] { return JabuJabusBellyClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -209,5 +209,6 @@ void AreaTable_Init_ShadowTemple() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
Entrance(SHADOW_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||||
|
Entrance(GRAVEYARD_WARP_PAD_REGION, { [] { return ShadowTempleClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -271,5 +271,6 @@ void AreaTable_Init_SpiritTemple() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
Entrance(SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||||
|
Entrance(DESERT_COLOSSUS, { [] { return SpiritTempleClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -331,5 +331,6 @@ void AreaTable_Init_WaterTemple() {
|
|||||||
{
|
{
|
||||||
// Exits
|
// Exits
|
||||||
Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
Entrance(WATER_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||||
|
Entrance(LAKE_HYLIA, { [] { return WaterTempleClear; } }),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -94,6 +94,7 @@ namespace Settings {
|
|||||||
Option ShuffleOverworldSpawns = Option::Bool("Overworld Spawns", {"Off", "On"});
|
Option ShuffleOverworldSpawns = Option::Bool("Overworld Spawns", {"Off", "On"});
|
||||||
Option MixedEntrancePools = Option::Bool("Mixed Entrance Pools", {"Off", "On"});
|
Option MixedEntrancePools = Option::Bool("Mixed Entrance Pools", {"Off", "On"});
|
||||||
Option MixDungeons = Option::Bool("Mix Dungeons", {"Off", "On"});
|
Option MixDungeons = Option::Bool("Mix Dungeons", {"Off", "On"});
|
||||||
|
Option MixBosses = Option::Bool("Mix Bosses", {"Off", "On"});
|
||||||
Option MixOverworld = Option::Bool("Mix Overworld", {"Off", "On"});
|
Option MixOverworld = Option::Bool("Mix Overworld", {"Off", "On"});
|
||||||
Option MixInteriors = Option::Bool("Mix Interiors", {"Off", "On"});
|
Option MixInteriors = Option::Bool("Mix Interiors", {"Off", "On"});
|
||||||
Option MixGrottos = Option::Bool("Mix Grottos", {"Off", "On"});
|
Option MixGrottos = Option::Bool("Mix Grottos", {"Off", "On"});
|
||||||
@ -135,6 +136,7 @@ namespace Settings {
|
|||||||
&ShuffleOverworldSpawns,
|
&ShuffleOverworldSpawns,
|
||||||
&MixedEntrancePools,
|
&MixedEntrancePools,
|
||||||
&MixDungeons,
|
&MixDungeons,
|
||||||
|
&MixBosses,
|
||||||
&MixOverworld,
|
&MixOverworld,
|
||||||
&MixInteriors,
|
&MixInteriors,
|
||||||
&MixGrottos,
|
&MixGrottos,
|
||||||
@ -1298,6 +1300,7 @@ namespace Settings {
|
|||||||
ctx.shuffleOverworldSpawns = (ShuffleOverworldSpawns) ? 1 : 0;
|
ctx.shuffleOverworldSpawns = (ShuffleOverworldSpawns) ? 1 : 0;
|
||||||
ctx.mixedEntrancePools = (MixedEntrancePools) ? 1 : 0;
|
ctx.mixedEntrancePools = (MixedEntrancePools) ? 1 : 0;
|
||||||
ctx.mixDungeons = (MixDungeons) ? 1 : 0;
|
ctx.mixDungeons = (MixDungeons) ? 1 : 0;
|
||||||
|
ctx.mixBosses = (MixBosses) ? 1 : 0;
|
||||||
ctx.mixOverworld = (MixOverworld) ? 1 : 0;
|
ctx.mixOverworld = (MixOverworld) ? 1 : 0;
|
||||||
ctx.mixInteriors = (MixInteriors) ? 1 : 0;
|
ctx.mixInteriors = (MixInteriors) ? 1 : 0;
|
||||||
ctx.mixGrottos = (MixGrottos) ? 1 : 0;
|
ctx.mixGrottos = (MixGrottos) ? 1 : 0;
|
||||||
@ -1891,6 +1894,13 @@ namespace Settings {
|
|||||||
MixDungeons.SetSelectedIndex(OFF);
|
MixDungeons.SetSelectedIndex(OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ShuffleBossEntrances.Is(SHUFFLEBOSSES_FULL)) {
|
||||||
|
MixBosses.Unhide();
|
||||||
|
} else {
|
||||||
|
MixBosses.Hide();
|
||||||
|
MixBosses.SetSelectedIndex(OFF);
|
||||||
|
}
|
||||||
|
|
||||||
if (ShuffleOverworldEntrances) {
|
if (ShuffleOverworldEntrances) {
|
||||||
MixOverworld.Unhide();
|
MixOverworld.Unhide();
|
||||||
} else {
|
} else {
|
||||||
@ -1914,6 +1924,8 @@ namespace Settings {
|
|||||||
} else {
|
} else {
|
||||||
MixDungeons.Hide();
|
MixDungeons.Hide();
|
||||||
MixDungeons.SetSelectedIndex(OFF);
|
MixDungeons.SetSelectedIndex(OFF);
|
||||||
|
MixBosses.Hide();
|
||||||
|
MixBosses.SetSelectedIndex(OFF);
|
||||||
MixOverworld.Hide();
|
MixOverworld.Hide();
|
||||||
MixOverworld.SetSelectedIndex(OFF);
|
MixOverworld.SetSelectedIndex(OFF);
|
||||||
MixInteriors.Hide();
|
MixInteriors.Hide();
|
||||||
@ -2190,6 +2202,7 @@ namespace Settings {
|
|||||||
|
|
||||||
if (!MixedEntrancePools) {
|
if (!MixedEntrancePools) {
|
||||||
MixDungeons.SetSelectedIndex(OFF);
|
MixDungeons.SetSelectedIndex(OFF);
|
||||||
|
MixBosses.SetSelectedIndex(OFF);
|
||||||
MixOverworld.SetSelectedIndex(OFF);
|
MixOverworld.SetSelectedIndex(OFF);
|
||||||
MixInteriors.SetSelectedIndex(OFF);
|
MixInteriors.SetSelectedIndex(OFF);
|
||||||
MixGrottos.SetSelectedIndex(OFF);
|
MixGrottos.SetSelectedIndex(OFF);
|
||||||
@ -2344,6 +2357,7 @@ namespace Settings {
|
|||||||
ShuffleOverworldSpawns.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS]);
|
ShuffleOverworldSpawns.SetSelectedIndex(cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS]);
|
||||||
MixedEntrancePools.SetSelectedIndex(cvarSettings[RSK_MIXED_ENTRANCE_POOLS]);
|
MixedEntrancePools.SetSelectedIndex(cvarSettings[RSK_MIXED_ENTRANCE_POOLS]);
|
||||||
MixDungeons.SetSelectedIndex(cvarSettings[RSK_MIX_DUNGEON_ENTRANCES]);
|
MixDungeons.SetSelectedIndex(cvarSettings[RSK_MIX_DUNGEON_ENTRANCES]);
|
||||||
|
MixBosses.SetSelectedIndex(cvarSettings[RSK_MIX_BOSS_ENTRANCES]);
|
||||||
MixOverworld.SetSelectedIndex(cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES]);
|
MixOverworld.SetSelectedIndex(cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES]);
|
||||||
MixInteriors.SetSelectedIndex(cvarSettings[RSK_MIX_INTERIOR_ENTRANCES]);
|
MixInteriors.SetSelectedIndex(cvarSettings[RSK_MIX_INTERIOR_ENTRANCES]);
|
||||||
MixGrottos.SetSelectedIndex(cvarSettings[RSK_MIX_GROTTO_ENTRANCES]);
|
MixGrottos.SetSelectedIndex(cvarSettings[RSK_MIX_GROTTO_ENTRANCES]);
|
||||||
|
@ -397,6 +397,7 @@ typedef struct {
|
|||||||
uint8_t shuffleOverworldSpawns;
|
uint8_t shuffleOverworldSpawns;
|
||||||
uint8_t mixedEntrancePools;
|
uint8_t mixedEntrancePools;
|
||||||
uint8_t mixDungeons;
|
uint8_t mixDungeons;
|
||||||
|
uint8_t mixBosses;
|
||||||
uint8_t mixOverworld;
|
uint8_t mixOverworld;
|
||||||
uint8_t mixInteriors;
|
uint8_t mixInteriors;
|
||||||
uint8_t mixGrottos;
|
uint8_t mixGrottos;
|
||||||
@ -784,6 +785,7 @@ void UpdateSettings(std::unordered_map<RandomizerSettingKey, uint8_t> cvarSettin
|
|||||||
extern Option ShuffleOverworldSpawns;
|
extern Option ShuffleOverworldSpawns;
|
||||||
extern Option MixedEntrancePools;
|
extern Option MixedEntrancePools;
|
||||||
extern Option MixDungeons;
|
extern Option MixDungeons;
|
||||||
|
extern Option MixBosses;
|
||||||
extern Option MixOverworld;
|
extern Option MixOverworld;
|
||||||
extern Option MixInteriors;
|
extern Option MixInteriors;
|
||||||
extern Option MixGrottos;
|
extern Option MixGrottos;
|
||||||
|
@ -307,35 +307,36 @@ static void WriteLocation(
|
|||||||
static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance) {
|
static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance) {
|
||||||
int16_t originalIndex = entrance->GetIndex();
|
int16_t originalIndex = entrance->GetIndex();
|
||||||
int16_t destinationIndex = -1;
|
int16_t destinationIndex = -1;
|
||||||
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
|
||||||
int16_t replacementBlueWarp = -1;
|
|
||||||
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
||||||
int16_t replacementDestinationIndex = -1;
|
int16_t replacementDestinationIndex = -1;
|
||||||
std::string name = entrance->GetName();
|
std::string name = entrance->GetName();
|
||||||
std::string text = entrance->GetConnectedRegion()->regionName + " from " + entrance->GetReplacement()->GetParentRegion()->regionName;
|
std::string text = entrance->GetConnectedRegion()->regionName + " from " + entrance->GetReplacement()->GetParentRegion()->regionName;
|
||||||
|
|
||||||
if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) {
|
// Track the reverse destination, useful for savewarp handling
|
||||||
|
if (entrance->GetReverse() != nullptr) {
|
||||||
destinationIndex = entrance->GetReverse()->GetIndex();
|
destinationIndex = entrance->GetReverse()->GetIndex();
|
||||||
|
// When decouple is off we track the replacement's reverse destination, useful for recording visited entrances
|
||||||
|
if (!entrance->IsDecoupled()) {
|
||||||
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||||
replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
json entranceJson = json::object({
|
json entranceJson = json::object({
|
||||||
|
{"type", entrance->GetType()},
|
||||||
{"index", originalIndex},
|
{"index", originalIndex},
|
||||||
{"destination", destinationIndex},
|
{"destination", destinationIndex},
|
||||||
{"blueWarp", originalBlueWarp},
|
|
||||||
{"override", replacementIndex},
|
{"override", replacementIndex},
|
||||||
{"overrideDestination", replacementDestinationIndex},
|
{"overrideDestination", replacementDestinationIndex},
|
||||||
});
|
});
|
||||||
|
|
||||||
jsonData["entrances"].push_back(entranceJson);
|
jsonData["entrances"].push_back(entranceJson);
|
||||||
|
|
||||||
// When decoupled entrances is off, handle saving reverse entrances with blue warps
|
// When decoupled entrances is off, handle saving reverse entrances
|
||||||
if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) {
|
if (entrance->GetReverse() != nullptr && !entrance->IsDecoupled()) {
|
||||||
json reverseEntranceJson = json::object({
|
json reverseEntranceJson = json::object({
|
||||||
|
{"type", entrance->GetReverse()->GetType()},
|
||||||
{"index", replacementDestinationIndex},
|
{"index", replacementDestinationIndex},
|
||||||
{"destination", replacementIndex},
|
{"destination", replacementIndex},
|
||||||
{"blueWarp", replacementBlueWarp},
|
|
||||||
{"override", destinationIndex},
|
{"override", destinationIndex},
|
||||||
{"overrideDestination", originalIndex},
|
{"overrideDestination", originalIndex},
|
||||||
});
|
});
|
||||||
|
@ -315,6 +315,7 @@ std::unordered_map<std::string, RandomizerSettingKey> SpoilerfileSettingNameToEn
|
|||||||
{ "World Settings:Overworld Spawns", RSK_SHUFFLE_OVERWORLD_SPAWNS },
|
{ "World Settings:Overworld Spawns", RSK_SHUFFLE_OVERWORLD_SPAWNS },
|
||||||
{ "World Settings:Mixed Entrance Pools", RSK_MIXED_ENTRANCE_POOLS },
|
{ "World Settings:Mixed Entrance Pools", RSK_MIXED_ENTRANCE_POOLS },
|
||||||
{ "World Settings:Mix Dungeons", RSK_MIX_DUNGEON_ENTRANCES },
|
{ "World Settings:Mix Dungeons", RSK_MIX_DUNGEON_ENTRANCES },
|
||||||
|
{ "World Settings:Mix Bosses", RSK_MIX_BOSS_ENTRANCES },
|
||||||
{ "World Settings:Mix Overworld", RSK_MIX_OVERWORLD_ENTRANCES },
|
{ "World Settings:Mix Overworld", RSK_MIX_OVERWORLD_ENTRANCES },
|
||||||
{ "World Settings:Mix Interiors", RSK_MIX_INTERIOR_ENTRANCES },
|
{ "World Settings:Mix Interiors", RSK_MIX_INTERIOR_ENTRANCES },
|
||||||
{ "World Settings:Mix Grottos", RSK_MIX_GROTTO_ENTRANCES },
|
{ "World Settings:Mix Grottos", RSK_MIX_GROTTO_ENTRANCES },
|
||||||
@ -899,6 +900,7 @@ void Randomizer::ParseRandomizerSettingsFile(const char* spoilerFileName) {
|
|||||||
case RSK_SHUFFLE_OVERWORLD_SPAWNS:
|
case RSK_SHUFFLE_OVERWORLD_SPAWNS:
|
||||||
case RSK_MIXED_ENTRANCE_POOLS:
|
case RSK_MIXED_ENTRANCE_POOLS:
|
||||||
case RSK_MIX_DUNGEON_ENTRANCES:
|
case RSK_MIX_DUNGEON_ENTRANCES:
|
||||||
|
case RSK_MIX_BOSS_ENTRANCES:
|
||||||
case RSK_MIX_OVERWORLD_ENTRANCES:
|
case RSK_MIX_OVERWORLD_ENTRANCES:
|
||||||
case RSK_MIX_INTERIOR_ENTRANCES:
|
case RSK_MIX_INTERIOR_ENTRANCES:
|
||||||
case RSK_MIX_GROTTO_ENTRANCES:
|
case RSK_MIX_GROTTO_ENTRANCES:
|
||||||
@ -1562,9 +1564,9 @@ void Randomizer::ParseEntranceDataFile(const char* spoilerFileName, bool silent)
|
|||||||
|
|
||||||
// set all the entrances to be 0 to indicate an unshuffled entrance
|
// set all the entrances to be 0 to indicate an unshuffled entrance
|
||||||
for (auto &entranceOveride : gSaveContext.entranceOverrides) {
|
for (auto &entranceOveride : gSaveContext.entranceOverrides) {
|
||||||
|
entranceOveride.type = 0;
|
||||||
entranceOveride.index = 0;
|
entranceOveride.index = 0;
|
||||||
entranceOveride.destination = 0;
|
entranceOveride.destination = 0;
|
||||||
entranceOveride.blueWarp = 0;
|
|
||||||
entranceOveride.override = 0;
|
entranceOveride.override = 0;
|
||||||
entranceOveride.overrideDestination = 0;
|
entranceOveride.overrideDestination = 0;
|
||||||
}
|
}
|
||||||
@ -1579,12 +1581,12 @@ void Randomizer::ParseEntranceDataFile(const char* spoilerFileName, bool silent)
|
|||||||
json entranceJson = *it;
|
json entranceJson = *it;
|
||||||
|
|
||||||
for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) {
|
for (auto entranceIt = entranceJson.begin(); entranceIt != entranceJson.end(); ++entranceIt) {
|
||||||
if (entranceIt.key() == "index") {
|
if (entranceIt.key() == "type") {
|
||||||
|
gSaveContext.entranceOverrides[i].type = entranceIt.value();
|
||||||
|
} else if (entranceIt.key() == "index") {
|
||||||
gSaveContext.entranceOverrides[i].index = entranceIt.value();
|
gSaveContext.entranceOverrides[i].index = entranceIt.value();
|
||||||
} else if (entranceIt.key() == "destination") {
|
} else if (entranceIt.key() == "destination") {
|
||||||
gSaveContext.entranceOverrides[i].destination = entranceIt.value();
|
gSaveContext.entranceOverrides[i].destination = entranceIt.value();
|
||||||
} else if (entranceIt.key() == "blueWarp") {
|
|
||||||
gSaveContext.entranceOverrides[i].blueWarp = entranceIt.value();
|
|
||||||
} else if (entranceIt.key() == "override") {
|
} else if (entranceIt.key() == "override") {
|
||||||
gSaveContext.entranceOverrides[i].override = entranceIt.value();
|
gSaveContext.entranceOverrides[i].override = entranceIt.value();
|
||||||
} else if (entranceIt.key() == "overrideDestination") {
|
} else if (entranceIt.key() == "overrideDestination") {
|
||||||
@ -3008,6 +3010,7 @@ void GenerateRandomizerImgui(std::string seed = "") {
|
|||||||
cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVarGetInteger("gRandomizeShuffleOverworldSpawns", RO_GENERIC_OFF);
|
cvarSettings[RSK_SHUFFLE_OVERWORLD_SPAWNS] = CVarGetInteger("gRandomizeShuffleOverworldSpawns", RO_GENERIC_OFF);
|
||||||
cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVarGetInteger("gRandomizeMixedEntrances", RO_GENERIC_OFF);
|
cvarSettings[RSK_MIXED_ENTRANCE_POOLS] = CVarGetInteger("gRandomizeMixedEntrances", RO_GENERIC_OFF);
|
||||||
cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVarGetInteger("gRandomizeMixDungeons", RO_GENERIC_OFF);
|
cvarSettings[RSK_MIX_DUNGEON_ENTRANCES] = CVarGetInteger("gRandomizeMixDungeons", RO_GENERIC_OFF);
|
||||||
|
cvarSettings[RSK_MIX_BOSS_ENTRANCES] = CVarGetInteger("gRandomizeMixBosses", RO_GENERIC_OFF);
|
||||||
cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVarGetInteger("gRandomizeMixOverworld", RO_GENERIC_OFF);
|
cvarSettings[RSK_MIX_OVERWORLD_ENTRANCES] = CVarGetInteger("gRandomizeMixOverworld", RO_GENERIC_OFF);
|
||||||
cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVarGetInteger("gRandomizeMixInteriors", RO_GENERIC_OFF);
|
cvarSettings[RSK_MIX_INTERIOR_ENTRANCES] = CVarGetInteger("gRandomizeMixInteriors", RO_GENERIC_OFF);
|
||||||
cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVarGetInteger("gRandomizeMixGrottos", RO_GENERIC_OFF);
|
cvarSettings[RSK_MIX_GROTTO_ENTRANCES] = CVarGetInteger("gRandomizeMixGrottos", RO_GENERIC_OFF);
|
||||||
@ -3706,7 +3709,8 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
// Mixed Entrance Pools
|
// Mixed Entrance Pools
|
||||||
UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", "gRandomizeMixedEntrances");
|
UIWidgets::EnhancementCheckbox("Mixed Entrance Pools", "gRandomizeMixedEntrances");
|
||||||
UIWidgets::InsertHelpHoverText(
|
UIWidgets::InsertHelpHoverText(
|
||||||
"Shuffle entrances into a mixed pool instead of separate ones.\n"
|
"Shuffle entrances into a mixed pool instead of separate ones. Has no affect on pools whose "
|
||||||
|
"entrances aren't shuffled, and \"Shuffle Boss Entrances\" must be set to \"Full\" to include them.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"For example, enabling the settings to shuffle grotto, dungeon, and overworld entrances and "
|
"For example, enabling the settings to shuffle grotto, dungeon, and overworld entrances and "
|
||||||
"selecting grotto and dungeon entrances here will allow a dungeon to be inside a grotto or "
|
"selecting grotto and dungeon entrances here will allow a dungeon to be inside a grotto or "
|
||||||
@ -3720,6 +3724,13 @@ void RandomizerSettingsWindow::DrawElement() {
|
|||||||
UIWidgets::EnhancementCheckbox("Mix Dungeons", "gRandomizeMixDungeons");
|
UIWidgets::EnhancementCheckbox("Mix Dungeons", "gRandomizeMixDungeons");
|
||||||
UIWidgets::InsertHelpHoverText("Dungeon entrances will be part of the mixed pool");
|
UIWidgets::InsertHelpHoverText("Dungeon entrances will be part of the mixed pool");
|
||||||
}
|
}
|
||||||
|
if (CVarGetInteger("gRandomizeShuffleBossEntrances", RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) ==
|
||||||
|
RO_BOSS_ROOM_ENTRANCE_SHUFFLE_FULL) {
|
||||||
|
UIWidgets::Spacer(0);
|
||||||
|
ImGui::SetCursorPosX(20);
|
||||||
|
UIWidgets::EnhancementCheckbox("Mix Bosses", "gRandomizeMixBosses");
|
||||||
|
UIWidgets::InsertHelpHoverText("Boss entrances will be part of the mixed pool");
|
||||||
|
}
|
||||||
if (CVarGetInteger("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF)) {
|
if (CVarGetInteger("gRandomizeShuffleOverworldEntrances", RO_GENERIC_OFF)) {
|
||||||
UIWidgets::Spacer(0);
|
UIWidgets::Spacer(0);
|
||||||
ImGui::SetCursorPosX(20);
|
ImGui::SetCursorPosX(20);
|
||||||
|
@ -1467,6 +1467,7 @@ typedef enum {
|
|||||||
RSK_SHUFFLE_OVERWORLD_SPAWNS,
|
RSK_SHUFFLE_OVERWORLD_SPAWNS,
|
||||||
RSK_MIXED_ENTRANCE_POOLS,
|
RSK_MIXED_ENTRANCE_POOLS,
|
||||||
RSK_MIX_DUNGEON_ENTRANCES,
|
RSK_MIX_DUNGEON_ENTRANCES,
|
||||||
|
RSK_MIX_BOSS_ENTRANCES,
|
||||||
RSK_MIX_OVERWORLD_ENTRANCES,
|
RSK_MIX_OVERWORLD_ENTRANCES,
|
||||||
RSK_MIX_INTERIOR_ENTRANCES,
|
RSK_MIX_INTERIOR_ENTRANCES,
|
||||||
RSK_MIX_GROTTO_ENTRANCES,
|
RSK_MIX_GROTTO_ENTRANCES,
|
||||||
|
@ -39,17 +39,12 @@ s16 dynamicExitList[] = {
|
|||||||
// Owl Flights : 0x492064 and 0x492080
|
// Owl Flights : 0x492064 and 0x492080
|
||||||
|
|
||||||
static s16 entranceOverrideTable[ENTRANCE_TABLE_SIZE] = {0};
|
static s16 entranceOverrideTable[ENTRANCE_TABLE_SIZE] = {0};
|
||||||
// Boss scenes (normalize boss scene range to 0 on lookup) to the replaced dungeon scene it is connected to
|
// Boss scenes (normalize boss scene range to 0 on lookup) mapped to save/death warp entrance
|
||||||
static s16 dungeonBossSceneOverrides[SHUFFLEABLE_BOSS_COUNT] = {0};
|
static s16 bossSceneSaveDeathWarps[SHUFFLEABLE_BOSS_COUNT] = {0};
|
||||||
static ActorEntry modifiedLinkActorEntry = {0};
|
static ActorEntry modifiedLinkActorEntry = {0};
|
||||||
|
|
||||||
EntranceInfo originalEntranceTable[ENTRANCE_TABLE_SIZE] = {0};
|
EntranceInfo originalEntranceTable[ENTRANCE_TABLE_SIZE] = {0};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
s16 blueWarp;
|
|
||||||
s16 destination;
|
|
||||||
} BlueWarpReplacement;
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
s16 entryway;
|
s16 entryway;
|
||||||
s16 exit;
|
s16 exit;
|
||||||
@ -62,39 +57,24 @@ typedef struct {
|
|||||||
|
|
||||||
static DungeonEntranceInfo dungeons[] = {
|
static DungeonEntranceInfo dungeons[] = {
|
||||||
//entryway exit, boss, reverse, bluewarp, dungeon scene, boss scene
|
//entryway exit, boss, reverse, bluewarp, dungeon scene, boss scene
|
||||||
{ DEKU_TREE_ENTRANCE, ENTR_KOKIRI_FOREST_1, ENTR_DEKU_TREE_BOSS_0, ENTR_DEKU_TREE_1, ENTR_KOKIRI_FOREST_11, SCENE_DEKU_TREE, SCENE_DEKU_TREE_BOSS },
|
{ ENTR_DEKU_TREE_0, ENTR_KOKIRI_FOREST_1, ENTR_DEKU_TREE_BOSS_0, ENTR_DEKU_TREE_1, ENTR_KOKIRI_FOREST_11, SCENE_DEKU_TREE, SCENE_DEKU_TREE_BOSS },
|
||||||
{ DODONGOS_CAVERN_ENTRANCE, ENTR_DEATH_MOUNTAIN_TRAIL_3, ENTR_DODONGOS_CAVERN_BOSS_0, ENTR_DODONGOS_CAVERN_1, ENTR_DEATH_MOUNTAIN_TRAIL_5, SCENE_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN_BOSS },
|
{ ENTR_DODONGOS_CAVERN_0, ENTR_DEATH_MOUNTAIN_TRAIL_3, ENTR_DODONGOS_CAVERN_BOSS_0, ENTR_DODONGOS_CAVERN_1, ENTR_DEATH_MOUNTAIN_TRAIL_5, SCENE_DODONGOS_CAVERN, SCENE_DODONGOS_CAVERN_BOSS },
|
||||||
{ JABU_JABUS_BELLY_ENTRANCE, ENTR_ZORAS_FOUNTAIN_1, ENTR_JABU_JABU_BOSS_0, ENTR_JABU_JABU_1, ENTR_ZORAS_FOUNTAIN_0, SCENE_JABU_JABU, SCENE_JABU_JABU_BOSS },
|
{ ENTR_JABU_JABU_0, ENTR_ZORAS_FOUNTAIN_1, ENTR_JABU_JABU_BOSS_0, ENTR_JABU_JABU_1, ENTR_ZORAS_FOUNTAIN_0, SCENE_JABU_JABU, SCENE_JABU_JABU_BOSS },
|
||||||
{ FOREST_TEMPLE_ENTRANCE, ENTR_SACRED_FOREST_MEADOW_1, ENTR_FOREST_TEMPLE_BOSS_0, ENTR_FOREST_TEMPLE_1, ENTR_SACRED_FOREST_MEADOW_3, SCENE_FOREST_TEMPLE, SCENE_FOREST_TEMPLE_BOSS },
|
{ ENTR_FOREST_TEMPLE_0, ENTR_SACRED_FOREST_MEADOW_1, ENTR_FOREST_TEMPLE_BOSS_0, ENTR_FOREST_TEMPLE_1, ENTR_SACRED_FOREST_MEADOW_3, SCENE_FOREST_TEMPLE, SCENE_FOREST_TEMPLE_BOSS },
|
||||||
{ FIRE_TEMPLE_ENTRANCE, ENTR_DEATH_MOUNTAIN_CRATER_2, ENTR_FIRE_TEMPLE_BOSS_0, ENTR_FIRE_TEMPLE_1, ENTR_DEATH_MOUNTAIN_CRATER_5, SCENE_FIRE_TEMPLE, SCENE_FIRE_TEMPLE_BOSS },
|
{ ENTR_FIRE_TEMPLE_0, ENTR_DEATH_MOUNTAIN_CRATER_2, ENTR_FIRE_TEMPLE_BOSS_0, ENTR_FIRE_TEMPLE_1, ENTR_DEATH_MOUNTAIN_CRATER_5, SCENE_FIRE_TEMPLE, SCENE_FIRE_TEMPLE_BOSS },
|
||||||
{ WATER_TEMPLE_ENTRANCE, ENTR_LAKE_HYLIA_2, ENTR_WATER_TEMPLE_BOSS_0, ENTR_WATER_TEMPLE_1, ENTR_LAKE_HYLIA_9, SCENE_WATER_TEMPLE, SCENE_WATER_TEMPLE_BOSS },
|
{ ENTR_WATER_TEMPLE_0, ENTR_LAKE_HYLIA_2, ENTR_WATER_TEMPLE_BOSS_0, ENTR_WATER_TEMPLE_1, ENTR_LAKE_HYLIA_9, SCENE_WATER_TEMPLE, SCENE_WATER_TEMPLE_BOSS },
|
||||||
{ SPIRIT_TEMPLE_ENTRANCE, ENTR_DESERT_COLOSSUS_1, ENTR_SPIRIT_TEMPLE_BOSS_0, ENTR_SPIRIT_TEMPLE_1, ENTR_DESERT_COLOSSUS_8, SCENE_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE_BOSS },
|
{ ENTR_SPIRIT_TEMPLE_0, ENTR_DESERT_COLOSSUS_1, ENTR_SPIRIT_TEMPLE_BOSS_0, ENTR_SPIRIT_TEMPLE_1, ENTR_DESERT_COLOSSUS_8, SCENE_SPIRIT_TEMPLE, SCENE_SPIRIT_TEMPLE_BOSS },
|
||||||
{ SHADOW_TEMPLE_ENTRANCE, ENTR_GRAVEYARD_1, ENTR_SHADOW_TEMPLE_BOSS_0, ENTR_SHADOW_TEMPLE_1, ENTR_GRAVEYARD_8, SCENE_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE_BOSS },
|
{ ENTR_SHADOW_TEMPLE_0, ENTR_GRAVEYARD_1, ENTR_SHADOW_TEMPLE_BOSS_0, ENTR_SHADOW_TEMPLE_1, ENTR_GRAVEYARD_8, SCENE_SHADOW_TEMPLE, SCENE_SHADOW_TEMPLE_BOSS },
|
||||||
};
|
};
|
||||||
|
|
||||||
//These variables store the new entrance indices for dungeons so that
|
|
||||||
//savewarping and game overs respawn players at the proper entrance.
|
|
||||||
//By default, these will be their vanilla values.
|
|
||||||
static s16 newDekuTreeEntrance = DEKU_TREE_ENTRANCE;
|
|
||||||
static s16 newDodongosCavernEntrance = DODONGOS_CAVERN_ENTRANCE;
|
|
||||||
static s16 newJabuJabusBellyEntrance = JABU_JABUS_BELLY_ENTRANCE;
|
|
||||||
static s16 newForestTempleEntrance = FOREST_TEMPLE_ENTRANCE;
|
|
||||||
static s16 newFireTempleEntrance = FIRE_TEMPLE_ENTRANCE;
|
|
||||||
static s16 newWaterTempleEntrance = WATER_TEMPLE_ENTRANCE;
|
|
||||||
static s16 newSpiritTempleEntrance = SPIRIT_TEMPLE_ENTRANCE;
|
|
||||||
static s16 newShadowTempleEntrance = SHADOW_TEMPLE_ENTRANCE;
|
|
||||||
static s16 newBottomOfTheWellEntrance = BOTTOM_OF_THE_WELL_ENTRANCE;
|
|
||||||
static s16 newGerudoTrainingGroundsEntrance = GERUDO_TRAINING_GROUNDS_ENTRANCE;
|
|
||||||
static s16 newIceCavernEntrance = ICE_CAVERN_ENTRANCE;
|
|
||||||
|
|
||||||
static s8 hasCopiedEntranceTable = 0;
|
static s8 hasCopiedEntranceTable = 0;
|
||||||
static s8 hasModifiedEntranceTable = 0;
|
static s8 hasModifiedEntranceTable = 0;
|
||||||
|
|
||||||
void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance);
|
void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance);
|
||||||
|
|
||||||
u8 Entrance_EntranceIsNull(EntranceOverride* entranceOverride) {
|
u8 Entrance_EntranceIsNull(EntranceOverride* entranceOverride) {
|
||||||
return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->blueWarp == 0
|
return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->override == 0 &&
|
||||||
&& entranceOverride->override == 0 && entranceOverride->overrideDestination == 0;
|
entranceOverride->overrideDestination == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void Entrance_SeparateOGCFairyFountainExit(void) {
|
static void Entrance_SeparateOGCFairyFountainExit(void) {
|
||||||
@ -113,6 +93,28 @@ static void Entrance_SeparateAdultSpawnAndPrelude() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Fix Adult dungeon blue warps as Child by assigning the child values for the warp pads
|
||||||
|
static void Entrance_ReplaceChildTempleWarps() {
|
||||||
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_DUNGEON_ENTRANCES) != RO_DUNGEON_ENTRANCE_SHUFFLE_OFF ||
|
||||||
|
Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) {
|
||||||
|
// Forest Temple
|
||||||
|
gEntranceTable[ENTR_SACRED_FOREST_MEADOW_3] = gEntranceTable[ENTR_SACRED_FOREST_MEADOW_2];
|
||||||
|
gEntranceTable[ENTR_SACRED_FOREST_MEADOW_3_1] = gEntranceTable[ENTR_SACRED_FOREST_MEADOW_2_1];
|
||||||
|
// Fire Temple
|
||||||
|
gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_5] = gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_4];
|
||||||
|
gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_5_1] = gEntranceTable[ENTR_DEATH_MOUNTAIN_CRATER_4_1];
|
||||||
|
// Water Temple
|
||||||
|
gEntranceTable[ENTR_LAKE_HYLIA_9] = gEntranceTable[ENTR_LAKE_HYLIA_8];
|
||||||
|
gEntranceTable[ENTR_LAKE_HYLIA_9_1] = gEntranceTable[ENTR_LAKE_HYLIA_8_1];
|
||||||
|
// Shadow Temple
|
||||||
|
gEntranceTable[ENTR_GRAVEYARD_8] = gEntranceTable[ENTR_GRAVEYARD_7];
|
||||||
|
gEntranceTable[ENTR_GRAVEYARD_8_1] = gEntranceTable[ENTR_GRAVEYARD_7_1];
|
||||||
|
// Spirit Temple
|
||||||
|
gEntranceTable[ENTR_DESERT_COLOSSUS_8] = gEntranceTable[ENTR_DESERT_COLOSSUS_5];
|
||||||
|
gEntranceTable[ENTR_DESERT_COLOSSUS_8_1] = gEntranceTable[ENTR_DESERT_COLOSSUS_5_1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Entrance_CopyOriginalEntranceTable(void) {
|
void Entrance_CopyOriginalEntranceTable(void) {
|
||||||
if (!hasCopiedEntranceTable) {
|
if (!hasCopiedEntranceTable) {
|
||||||
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE);
|
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE);
|
||||||
@ -130,9 +132,6 @@ void Entrance_ResetEntranceTable(void) {
|
|||||||
void Entrance_Init(void) {
|
void Entrance_Init(void) {
|
||||||
s32 index;
|
s32 index;
|
||||||
|
|
||||||
size_t blueWarpRemapIdx = 0;
|
|
||||||
BlueWarpReplacement bluewarps[SHUFFLEABLE_BOSS_COUNT] = {0};
|
|
||||||
|
|
||||||
Entrance_CopyOriginalEntranceTable();
|
Entrance_CopyOriginalEntranceTable();
|
||||||
|
|
||||||
// Skip Child Stealth if given by settings
|
// Skip Child Stealth if given by settings
|
||||||
@ -149,6 +148,7 @@ void Entrance_Init(void) {
|
|||||||
|
|
||||||
Entrance_SeparateOGCFairyFountainExit();
|
Entrance_SeparateOGCFairyFountainExit();
|
||||||
Entrance_SeparateAdultSpawnAndPrelude();
|
Entrance_SeparateAdultSpawnAndPrelude();
|
||||||
|
Entrance_ReplaceChildTempleWarps();
|
||||||
|
|
||||||
// Initialize the entrance override table with each index leading to itself. An
|
// Initialize the entrance override table with each index leading to itself. An
|
||||||
// index referring to itself means that the entrance is not currently shuffled.
|
// index referring to itself means that the entrance is not currently shuffled.
|
||||||
@ -156,9 +156,9 @@ void Entrance_Init(void) {
|
|||||||
entranceOverrideTable[i] = i;
|
entranceOverrideTable[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize all boss rooms connected to their vanilla dungeon
|
// Initialize all boss room save/death warps with their vanilla dungeon entryway
|
||||||
for (s16 i = 1; i < SHUFFLEABLE_BOSS_COUNT; i++) {
|
for (s16 i = 1; i < SHUFFLEABLE_BOSS_COUNT; i++) {
|
||||||
dungeonBossSceneOverrides[i] = i;
|
bossSceneSaveDeathWarps[i] = dungeons[i].entryway;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize the grotto exit and load lists
|
// Initialize the grotto exit and load lists
|
||||||
@ -172,9 +172,30 @@ void Entrance_Init(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
s16 originalIndex = gSaveContext.entranceOverrides[i].index;
|
s16 originalIndex = gSaveContext.entranceOverrides[i].index;
|
||||||
s16 blueWarpIndex = gSaveContext.entranceOverrides[i].blueWarp;
|
s16 originalDestination = gSaveContext.entranceOverrides[i].destination;
|
||||||
s16 overrideIndex = gSaveContext.entranceOverrides[i].override;
|
s16 overrideIndex = gSaveContext.entranceOverrides[i].override;
|
||||||
|
|
||||||
|
int16_t bossScene = -1;
|
||||||
|
int16_t saveWarpEntrance = originalDestination; // Default save warp to the original return entrance
|
||||||
|
|
||||||
|
// Search for boss room overrides and look for the matching save/death warp value to use
|
||||||
|
// If the boss room is in a dungeon, use the dungeons entryway as the save warp
|
||||||
|
// Otherwise use the "exit" value for the entrance that lead to the boss room
|
||||||
|
for (int j = 0; j <= SHUFFLEABLE_BOSS_COUNT; j++) {
|
||||||
|
if (overrideIndex == dungeons[j].bossDoor) {
|
||||||
|
bossScene = dungeons[j].bossScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index == dungeons[j].bossDoor) {
|
||||||
|
saveWarpEntrance = dungeons[j].entryway;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Found a boss scene and a valid save/death warp value
|
||||||
|
if (bossScene != -1 && saveWarpEntrance != -1) {
|
||||||
|
bossSceneSaveDeathWarps[bossScene - SCENE_DEKU_TREE_BOSS] = saveWarpEntrance;
|
||||||
|
}
|
||||||
|
|
||||||
//Overwrite grotto related indices
|
//Overwrite grotto related indices
|
||||||
if (originalIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START) {
|
if (originalIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START) {
|
||||||
Grotto_SetExitOverride(originalIndex, overrideIndex);
|
Grotto_SetExitOverride(originalIndex, overrideIndex);
|
||||||
@ -189,36 +210,6 @@ void Entrance_Init(void) {
|
|||||||
// Overwrite the indices which we want to shuffle, leaving the rest as they are
|
// Overwrite the indices which we want to shuffle, leaving the rest as they are
|
||||||
entranceOverrideTable[originalIndex] = overrideIndex;
|
entranceOverrideTable[originalIndex] = overrideIndex;
|
||||||
|
|
||||||
if (blueWarpIndex != 0) {
|
|
||||||
// When boss shuffle is enabled, we need to know what dungeon the boss room is connected to for
|
|
||||||
// death/save warping, and for the blue warp
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF) {
|
|
||||||
s16 bossScene = -1;
|
|
||||||
s16 replacedDungeonScene = -1;
|
|
||||||
s16 replacedDungeonExit = -1;
|
|
||||||
// Search for the boss scene and replaced blue warp exits
|
|
||||||
for (s16 j = 0; j <= SHUFFLEABLE_BOSS_COUNT; j++) {
|
|
||||||
if (blueWarpIndex == dungeons[j].blueWarp) {
|
|
||||||
bossScene = dungeons[j].bossScene;
|
|
||||||
}
|
|
||||||
if (overrideIndex == dungeons[j].bossDoorReverse) {
|
|
||||||
replacedDungeonScene = dungeons[j].scene;
|
|
||||||
replacedDungeonExit = dungeons[j].exit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// assign the boss scene override
|
|
||||||
if (bossScene != -1 && replacedDungeonScene != -1 && replacedDungeonExit != -1) {
|
|
||||||
dungeonBossSceneOverrides[bossScene - SCENE_DEKU_TREE_BOSS] = replacedDungeonScene;
|
|
||||||
bluewarps[blueWarpRemapIdx].blueWarp = blueWarpIndex;
|
|
||||||
bluewarps[blueWarpRemapIdx].destination = replacedDungeonExit;
|
|
||||||
blueWarpRemapIdx++;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
entranceOverrideTable[blueWarpIndex] = overrideIndex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Override both land and water entrances for Hyrule Field -> ZR Front and vice versa
|
//Override both land and water entrances for Hyrule Field -> ZR Front and vice versa
|
||||||
if (originalIndex == ENTR_ZORAS_RIVER_0) { //Hyrule Field -> ZR Front land entrance
|
if (originalIndex == ENTR_ZORAS_RIVER_0) { //Hyrule Field -> ZR Front land entrance
|
||||||
entranceOverrideTable[ENTR_ZORAS_RIVER_3] = overrideIndex;
|
entranceOverrideTable[ENTR_ZORAS_RIVER_3] = overrideIndex;
|
||||||
@ -227,14 +218,6 @@ void Entrance_Init(void) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we have remapped blue warps from boss shuffle, handle setting those and grabbing the override for
|
|
||||||
// the replaced dungeons exit in the event that dungeon shuffle is also turned on
|
|
||||||
for (size_t i = 0; i < ARRAY_COUNT(bluewarps); i++) {
|
|
||||||
if (bluewarps[i].blueWarp != 0 && bluewarps[i].destination != 0) {
|
|
||||||
entranceOverrideTable[bluewarps[i].blueWarp] = Entrance_GetOverride(bluewarps[i].destination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Stop playing background music during shuffled entrance transitions
|
// Stop playing background music during shuffled entrance transitions
|
||||||
// so that we don't get duplicated or overlapping music tracks
|
// so that we don't get duplicated or overlapping music tracks
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) {
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) {
|
||||||
@ -328,40 +311,39 @@ void Entrance_SetGameOverEntrance(void) {
|
|||||||
|
|
||||||
s16 scene = gPlayState->sceneNum;
|
s16 scene = gPlayState->sceneNum;
|
||||||
|
|
||||||
// When in a boss room and boss shuffle is on, get the connected dungeon's original boss room entrance
|
// When in a boss room and boss shuffle is on, use the boss scene to find the death warp entrance
|
||||||
// then run the normal game over overrides on it
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF &&
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF &&
|
||||||
scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) {
|
scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) {
|
||||||
// Normalize boss scene range to 0 on lookup
|
// Normalize boss scene range to 0 on lookup and handle for grotto entrances
|
||||||
scene = dungeonBossSceneOverrides[scene - SCENE_DEKU_TREE_BOSS];
|
gSaveContext.entranceIndex = Grotto_OverrideSpecialEntrance(bossSceneSaveDeathWarps[scene - SCENE_DEKU_TREE_BOSS]);
|
||||||
gSaveContext.entranceIndex = dungeons[scene].bossDoor;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Set the current entrance depending on which entrance the player last came through
|
//Set the current entrance depending on which entrance the player last came through
|
||||||
switch (gSaveContext.entranceIndex) {
|
switch (gSaveContext.entranceIndex) {
|
||||||
case ENTR_DEKU_TREE_BOSS_0 : //Deku Tree Boss Room
|
case ENTR_DEKU_TREE_BOSS_0 : //Deku Tree Boss Room
|
||||||
gSaveContext.entranceIndex = newDekuTreeEntrance;
|
gSaveContext.entranceIndex = ENTR_DEKU_TREE_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_DODONGOS_CAVERN_BOSS_0 : //Dodongos Cavern Boss Room
|
case ENTR_DODONGOS_CAVERN_BOSS_0 : //Dodongos Cavern Boss Room
|
||||||
gSaveContext.entranceIndex = newDodongosCavernEntrance;
|
gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_JABU_JABU_BOSS_0 : //Jabu Jabus Belly Boss Room
|
case ENTR_JABU_JABU_BOSS_0 : //Jabu Jabus Belly Boss Room
|
||||||
gSaveContext.entranceIndex = newJabuJabusBellyEntrance;
|
gSaveContext.entranceIndex = ENTR_JABU_JABU_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_FOREST_TEMPLE_BOSS_0 : //Forest Temple Boss Room
|
case ENTR_FOREST_TEMPLE_BOSS_0 : //Forest Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newForestTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_FIRE_TEMPLE_BOSS_0 : //Fire Temple Boss Room
|
case ENTR_FIRE_TEMPLE_BOSS_0 : //Fire Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newFireTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_FIRE_TEMPLE_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_WATER_TEMPLE_BOSS_0 : //Water Temple Boss Room
|
case ENTR_WATER_TEMPLE_BOSS_0 : //Water Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newWaterTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_SPIRIT_TEMPLE_BOSS_0 : //Spirit Temple Boss Room
|
case ENTR_SPIRIT_TEMPLE_BOSS_0 : //Spirit Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newSpiritTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_SPIRIT_TEMPLE_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_SHADOW_TEMPLE_BOSS_0 : //Shadow Temple Boss Room
|
case ENTR_SHADOW_TEMPLE_BOSS_0 : //Shadow Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newShadowTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0;
|
||||||
return;
|
return;
|
||||||
case ENTR_GANONDORF_BOSS_0 : //Ganondorf Boss Room
|
case ENTR_GANONDORF_BOSS_0 : //Ganondorf Boss Room
|
||||||
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb
|
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb
|
||||||
@ -374,46 +356,46 @@ void Entrance_SetSavewarpEntrance(void) {
|
|||||||
|
|
||||||
s16 scene = gSaveContext.savedSceneNum;
|
s16 scene = gSaveContext.savedSceneNum;
|
||||||
|
|
||||||
// When in a boss room and boss shuffle is on, use the boss scene override to remap to its
|
// When in a boss room and boss shuffle is on, use the boss scene to find the savewarp entrance
|
||||||
// connected dungeon and use that for the final entrance
|
|
||||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF &&
|
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF &&
|
||||||
scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) {
|
scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) {
|
||||||
// Normalize boss scene range to 0 on lookup
|
// Normalize boss scene range to 0 on lookup and handle for grotto entrances
|
||||||
scene = dungeonBossSceneOverrides[scene - SCENE_DEKU_TREE_BOSS];
|
gSaveContext.entranceIndex = Grotto_OverrideSpecialEntrance(bossSceneSaveDeathWarps[scene - SCENE_DEKU_TREE_BOSS]);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (scene == SCENE_DEKU_TREE || scene == SCENE_DEKU_TREE_BOSS) {
|
if (scene == SCENE_DEKU_TREE || scene == SCENE_DEKU_TREE_BOSS) {
|
||||||
gSaveContext.entranceIndex = newDekuTreeEntrance;
|
gSaveContext.entranceIndex = ENTR_DEKU_TREE_0;
|
||||||
} else if (scene == SCENE_DODONGOS_CAVERN || scene == SCENE_DODONGOS_CAVERN_BOSS) {
|
} else if (scene == SCENE_DODONGOS_CAVERN || scene == SCENE_DODONGOS_CAVERN_BOSS) {
|
||||||
gSaveContext.entranceIndex = newDodongosCavernEntrance;
|
gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0;
|
||||||
} else if (scene == SCENE_JABU_JABU || scene == SCENE_JABU_JABU_BOSS) {
|
} else if (scene == SCENE_JABU_JABU || scene == SCENE_JABU_JABU_BOSS) {
|
||||||
gSaveContext.entranceIndex = newJabuJabusBellyEntrance;
|
gSaveContext.entranceIndex = ENTR_JABU_JABU_0;
|
||||||
} else if (scene == SCENE_FOREST_TEMPLE || scene == SCENE_FOREST_TEMPLE_BOSS) { //Forest Temple Boss Room
|
} else if (scene == SCENE_FOREST_TEMPLE || scene == SCENE_FOREST_TEMPLE_BOSS) { //Forest Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newForestTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0;
|
||||||
} else if (scene == SCENE_FIRE_TEMPLE || scene == SCENE_FIRE_TEMPLE_BOSS) { //Fire Temple Boss Room
|
} else if (scene == SCENE_FIRE_TEMPLE || scene == SCENE_FIRE_TEMPLE_BOSS) { //Fire Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newFireTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_FIRE_TEMPLE_0;
|
||||||
} else if (scene == SCENE_WATER_TEMPLE || scene == SCENE_WATER_TEMPLE_BOSS) { //Water Temple Boss Room
|
} else if (scene == SCENE_WATER_TEMPLE || scene == SCENE_WATER_TEMPLE_BOSS) { //Water Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newWaterTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0;
|
||||||
} else if (scene == SCENE_SPIRIT_TEMPLE || scene == SCENE_SPIRIT_TEMPLE_BOSS) { //Spirit Temple Boss Room
|
} else if (scene == SCENE_SPIRIT_TEMPLE || scene == SCENE_SPIRIT_TEMPLE_BOSS) { //Spirit Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newSpiritTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_SPIRIT_TEMPLE_0;
|
||||||
} else if (scene == SCENE_SHADOW_TEMPLE || scene == SCENE_SHADOW_TEMPLE_BOSS) { //Shadow Temple Boss Room
|
} else if (scene == SCENE_SHADOW_TEMPLE || scene == SCENE_SHADOW_TEMPLE_BOSS) { //Shadow Temple Boss Room
|
||||||
gSaveContext.entranceIndex = newShadowTempleEntrance;
|
gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0;
|
||||||
} else if (scene == SCENE_BOTTOM_OF_THE_WELL) { // BOTW
|
} else if (scene == SCENE_BOTTOM_OF_THE_WELL) { // BOTW
|
||||||
gSaveContext.entranceIndex = newBottomOfTheWellEntrance;
|
gSaveContext.entranceIndex = ENTR_BOTTOM_OF_THE_WELL_0;
|
||||||
} else if (scene == SCENE_GERUDO_TRAINING_GROUND) { // GTG
|
} else if (scene == SCENE_GERUDO_TRAINING_GROUND) { // GTG
|
||||||
gSaveContext.entranceIndex = newGerudoTrainingGroundsEntrance;
|
gSaveContext.entranceIndex = ENTR_GERUDO_TRAINING_GROUND_0;
|
||||||
} else if (scene == SCENE_ICE_CAVERN) { // Ice cavern
|
} else if (scene == SCENE_ICE_CAVERN) { // Ice cavern
|
||||||
gSaveContext.entranceIndex = newIceCavernEntrance;
|
gSaveContext.entranceIndex = ENTR_ICE_CAVERN_0;
|
||||||
} else if (scene == SCENE_INSIDE_GANONS_CASTLE) {
|
} else if (scene == SCENE_INSIDE_GANONS_CASTLE) {
|
||||||
gSaveContext.entranceIndex = GANONS_CASTLE_ENTRANCE;
|
gSaveContext.entranceIndex = ENTR_INSIDE_GANONS_CASTLE_0;
|
||||||
} else if (scene == SCENE_GANONS_TOWER || scene == SCENE_INSIDE_GANONS_CASTLE_COLLAPSE || scene == SCENE_GANONS_TOWER_COLLAPSE_INTERIOR || scene == SCENE_GANON_BOSS || scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) {
|
} else if (scene == SCENE_GANONS_TOWER || scene == SCENE_INSIDE_GANONS_CASTLE_COLLAPSE || scene == SCENE_GANONS_TOWER_COLLAPSE_INTERIOR || scene == SCENE_GANON_BOSS || scene == SCENE_GANONS_TOWER_COLLAPSE_EXTERIOR) {
|
||||||
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb
|
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb
|
||||||
} else if (scene == SCENE_THIEVES_HIDEOUT) { // Theives hideout
|
} else if (scene == SCENE_THIEVES_HIDEOUT) { // Theives hideout
|
||||||
gSaveContext.entranceIndex = ENTR_THIEVES_HIDEOUT_0; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
gSaveContext.entranceIndex = ENTR_THIEVES_HIDEOUT_0; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
||||||
} else if (scene == SCENE_LINKS_HOUSE) {
|
} else if (scene == SCENE_LINKS_HOUSE) {
|
||||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE);
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0);
|
||||||
} else if (LINK_IS_CHILD) {
|
} else if (LINK_IS_CHILD) {
|
||||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0); // Child Overworld Spawn
|
||||||
} else {
|
} else {
|
||||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_HYRULE_FIELD_10); // Adult Overworld Spawn (Normally 0x5F4 (ENTR_TEMPLE_OF_TIME_7), but 0x282 (ENTR_HYRULE_FIELD_10) has been repurposed to differentiate from Prelude which also uses 0x5F4)
|
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_HYRULE_FIELD_10); // Adult Overworld Spawn (Normally 0x5F4 (ENTR_TEMPLE_OF_TIME_7), but 0x282 (ENTR_HYRULE_FIELD_10) has been repurposed to differentiate from Prelude which also uses 0x5F4)
|
||||||
}
|
}
|
||||||
@ -494,7 +476,7 @@ void Entrance_OverrideBlueWarp(void) {
|
|||||||
void Entrance_OverrideCutsceneEntrance(u16 cutsceneCmd) {
|
void Entrance_OverrideCutsceneEntrance(u16 cutsceneCmd) {
|
||||||
switch (cutsceneCmd) {
|
switch (cutsceneCmd) {
|
||||||
case 24: // Dropping a fish for Jabu Jabu
|
case 24: // Dropping a fish for Jabu Jabu
|
||||||
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(newJabuJabusBellyEntrance);
|
gPlayState->nextEntranceIndex = Entrance_OverrideNextIndex(ENTR_JABU_JABU_0);
|
||||||
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
gPlayState->transitionTrigger = TRANS_TRIGGER_START;
|
||||||
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
|
gPlayState->transitionType = TRANS_TYPE_FADE_BLACK;
|
||||||
// In case Jabu's mouth leads to a grotto return
|
// In case Jabu's mouth leads to a grotto return
|
||||||
|
@ -8,20 +8,6 @@
|
|||||||
|
|
||||||
#define ENTRANCE_TABLE_SIZE ENTR_MAX
|
#define ENTRANCE_TABLE_SIZE ENTR_MAX
|
||||||
|
|
||||||
#define DEKU_TREE_ENTRANCE ENTR_DEKU_TREE_0
|
|
||||||
#define DODONGOS_CAVERN_ENTRANCE ENTR_DODONGOS_CAVERN_0
|
|
||||||
#define JABU_JABUS_BELLY_ENTRANCE ENTR_JABU_JABU_0
|
|
||||||
#define FOREST_TEMPLE_ENTRANCE ENTR_FOREST_TEMPLE_0
|
|
||||||
#define FIRE_TEMPLE_ENTRANCE ENTR_FIRE_TEMPLE_0
|
|
||||||
#define WATER_TEMPLE_ENTRANCE ENTR_WATER_TEMPLE_0
|
|
||||||
#define SPIRIT_TEMPLE_ENTRANCE ENTR_SPIRIT_TEMPLE_0
|
|
||||||
#define SHADOW_TEMPLE_ENTRANCE ENTR_SHADOW_TEMPLE_0
|
|
||||||
#define BOTTOM_OF_THE_WELL_ENTRANCE ENTR_BOTTOM_OF_THE_WELL_0
|
|
||||||
#define GERUDO_TRAINING_GROUNDS_ENTRANCE ENTR_GERUDO_TRAINING_GROUND_0
|
|
||||||
#define ICE_CAVERN_ENTRANCE ENTR_ICE_CAVERN_0
|
|
||||||
#define GANONS_CASTLE_ENTRANCE ENTR_INSIDE_GANONS_CASTLE_0
|
|
||||||
#define LINK_HOUSE_SAVEWARP_ENTRANCE ENTR_LINKS_HOUSE_0
|
|
||||||
|
|
||||||
#define ENTRANCE_RANDO_GROTTO_LOAD_START 0x0700
|
#define ENTRANCE_RANDO_GROTTO_LOAD_START 0x0700
|
||||||
#define ENTRANCE_RANDO_GROTTO_EXIT_START 0x0800
|
#define ENTRANCE_RANDO_GROTTO_EXIT_START 0x0800
|
||||||
#define MAX_ENTRANCE_RANDO_USED_INDEX 0x0820
|
#define MAX_ENTRANCE_RANDO_USED_INDEX 0x0820
|
||||||
@ -66,7 +52,7 @@ typedef enum {
|
|||||||
#define ENTRANCE_RANDO_GROTTO_LOAD(index) ENTRANCE_RANDO_GROTTO_LOAD_START + index
|
#define ENTRANCE_RANDO_GROTTO_LOAD(index) ENTRANCE_RANDO_GROTTO_LOAD_START + index
|
||||||
#define ENTRANCE_RANDO_GROTTO_EXIT(index) ENTRANCE_RANDO_GROTTO_EXIT_START + index
|
#define ENTRANCE_RANDO_GROTTO_EXIT(index) ENTRANCE_RANDO_GROTTO_EXIT_START + index
|
||||||
|
|
||||||
#define ENTRANCE_OVERRIDES_MAX_COUNT 259 // 11 one-way entrances + 124 two-way entrances (x2)
|
#define ENTRANCE_OVERRIDES_MAX_COUNT 267 // 19 one-way entrances + 124 two-way entrances (x2)
|
||||||
#define SHUFFLEABLE_BOSS_COUNT 8
|
#define SHUFFLEABLE_BOSS_COUNT 8
|
||||||
|
|
||||||
#define SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT 66 // Max entrance rando index is 0x0820, (2080 / 32 == 65) + 1
|
#define SAVEFILE_ENTRANCES_DISCOVERED_IDX_COUNT 66 // Max entrance rando index is 0x0820, (2080 / 32 == 65) + 1
|
||||||
@ -79,9 +65,9 @@ typedef enum {
|
|||||||
(((startTransType) << ENTRANCE_INFO_START_TRANS_TYPE_SHIFT) & ENTRANCE_INFO_START_TRANS_TYPE_MASK))
|
(((startTransType) << ENTRANCE_INFO_START_TRANS_TYPE_SHIFT) & ENTRANCE_INFO_START_TRANS_TYPE_MASK))
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
|
uint16_t type;
|
||||||
int16_t index;
|
int16_t index;
|
||||||
int16_t destination;
|
int16_t destination;
|
||||||
int16_t blueWarp;
|
|
||||||
int16_t override;
|
int16_t override;
|
||||||
int16_t overrideDestination;
|
int16_t overrideDestination;
|
||||||
} EntranceOverride;
|
} EntranceOverride;
|
||||||
|
@ -104,6 +104,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_KOKIRI_FOREST_1, ENTR_DEKU_TREE_0, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, ""},
|
{ ENTR_KOKIRI_FOREST_1, ENTR_DEKU_TREE_0, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree", "KF", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, ""},
|
||||||
{ ENTR_DEKU_TREE_BOSS_0, ENTR_DEKU_TREE_1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Boss Door", "Gohma", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_DEKU_TREE_BOSS_0, ENTR_DEKU_TREE_1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE), "Deku Tree Boss Door", "Gohma", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
{ ENTR_DEKU_TREE_1, ENTR_DEKU_TREE_BOSS_0, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Boss Door", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_DEKU_TREE_1, ENTR_DEKU_TREE_BOSS_0, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Boss Door", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
|
{ ENTR_KOKIRI_FOREST_11, -1, SINGLE_SCENE_INFO(SCENE_DEKU_TREE_BOSS), "Gohma", "Deku Tree Blue Warp", ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
|
||||||
|
|
||||||
// Lost Woods
|
// Lost Woods
|
||||||
{ ENTR_KOKIRI_FOREST_2, ENTR_LOST_WOODS_9, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge", "KF", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
|
{ ENTR_KOKIRI_FOREST_2, ENTR_LOST_WOODS_9, SINGLE_SCENE_INFO(SCENE_LOST_WOODS), "Lost Woods Bridge", "KF", ENTRANCE_GROUP_LOST_WOODS, ENTRANCE_GROUP_KOKIRI_FOREST, ENTRANCE_TYPE_OVERWORLD, "lw"},
|
||||||
@ -131,6 +132,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_SACRED_FOREST_MEADOW_1, ENTR_FOREST_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple", "SFM", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON},
|
{ ENTR_SACRED_FOREST_MEADOW_1, ENTR_FOREST_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple", "SFM", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON},
|
||||||
{ ENTR_FOREST_TEMPLE_BOSS_0, ENTR_FOREST_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Boss Door", "Phantom Ganon", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_FOREST_TEMPLE_BOSS_0, ENTR_FOREST_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE), "Forest Temple Boss Door", "Phantom Ganon", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
{ ENTR_FOREST_TEMPLE_1, ENTR_FOREST_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Boss Door", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_FOREST_TEMPLE_1, ENTR_FOREST_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Boss Door", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
|
{ ENTR_SACRED_FOREST_MEADOW_3, -1, SINGLE_SCENE_INFO(SCENE_FOREST_TEMPLE_BOSS), "Phantom Ganon", "Forest Temple Blue Warp", ENTRANCE_GROUP_SFM, ENTRANCE_GROUP_SFM, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
|
||||||
|
|
||||||
// Kakariko Village
|
// Kakariko Village
|
||||||
{ ENTR_HYRULE_FIELD_1, ENTR_KAKARIKO_VILLAGE_0, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko", "Hyrule Field", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
|
{ ENTR_HYRULE_FIELD_1, ENTR_KAKARIKO_VILLAGE_0, SINGLE_SCENE_INFO(SCENE_KAKARIKO_VILLAGE), "Kakariko", "Hyrule Field", ENTRANCE_GROUP_KAKARIKO, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
|
||||||
@ -179,6 +181,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_GRAVEYARD_1, ENTR_SHADOW_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON},
|
{ ENTR_GRAVEYARD_1, ENTR_SHADOW_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple", "Graveyard", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON},
|
||||||
{ ENTR_SHADOW_TEMPLE_BOSS_0, ENTR_SHADOW_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Boss Door", "Bongo-Bongo", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_SHADOW_TEMPLE_BOSS_0, ENTR_SHADOW_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE), "Shadow Temple Boss Door", "Bongo-Bongo", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
{ ENTR_SHADOW_TEMPLE_1, ENTR_SHADOW_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Boss Door", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_SHADOW_TEMPLE_1, ENTR_SHADOW_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Boss Door", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
|
{ ENTR_GRAVEYARD_8, -1, SINGLE_SCENE_INFO(SCENE_SHADOW_TEMPLE_BOSS), "Bongo-Bongo", "Shadow Temple Blue Warp", ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_GROUP_GRAVEYARD, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
|
||||||
|
|
||||||
// Death Mountain Trail
|
// Death Mountain Trail
|
||||||
{ ENTR_GORON_CITY_0, ENTR_DEATH_MOUNTAIN_TRAIL_1, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
|
{ ENTR_GORON_CITY_0, ENTR_DEATH_MOUNTAIN_TRAIL_1, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_TRAIL), "DMT", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
|
||||||
@ -194,6 +197,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_DEATH_MOUNTAIN_TRAIL_3, ENTR_DODONGOS_CAVERN_0, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"},
|
{ ENTR_DEATH_MOUNTAIN_TRAIL_3, ENTR_DODONGOS_CAVERN_0, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern", "DMT", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc"},
|
||||||
{ ENTR_DODONGOS_CAVERN_BOSS_0, ENTR_DODONGOS_CAVERN_1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Boss Door", "King Dodongo", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
|
{ ENTR_DODONGOS_CAVERN_BOSS_0, ENTR_DODONGOS_CAVERN_1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN), "Dodongo's Cavern Boss Door", "King Dodongo", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
|
||||||
{ ENTR_DODONGOS_CAVERN_1, ENTR_DODONGOS_CAVERN_BOSS_0, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
|
{ ENTR_DODONGOS_CAVERN_1, ENTR_DODONGOS_CAVERN_BOSS_0, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_DUNGEON, "dc", 1},
|
||||||
|
{ ENTR_DEATH_MOUNTAIN_TRAIL_5, -1, SINGLE_SCENE_INFO(SCENE_DODONGOS_CAVERN_BOSS), "King Dodongo", "Dodongo's Cavern Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_ONE_WAY, "dc,bw", 1},
|
||||||
|
|
||||||
// Death Mountain Crater
|
// Death Mountain Crater
|
||||||
{ ENTR_GORON_CITY_1, ENTR_DEATH_MOUNTAIN_CRATER_1, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
|
{ ENTR_GORON_CITY_1, ENTR_DEATH_MOUNTAIN_CRATER_1, SINGLE_SCENE_INFO(SCENE_DEATH_MOUNTAIN_CRATER), "DMC", "Goron City", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_GORON_CITY, ENTRANCE_TYPE_OVERWORLD, "gc"},
|
||||||
@ -208,6 +212,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_DEATH_MOUNTAIN_CRATER_2, ENTR_FIRE_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON},
|
{ ENTR_DEATH_MOUNTAIN_CRATER_2, ENTR_FIRE_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple", "DMC", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON},
|
||||||
{ ENTR_FIRE_TEMPLE_BOSS_0, ENTR_FIRE_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Boss Door", "Volvagia", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_FIRE_TEMPLE_BOSS_0, ENTR_FIRE_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE), "Fire Temple Boss Door", "Volvagia", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
{ ENTR_FIRE_TEMPLE_1, ENTR_FIRE_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_FIRE_TEMPLE_1, ENTR_FIRE_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Boss Door", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
|
{ ENTR_DEATH_MOUNTAIN_CRATER_5, -1, SINGLE_SCENE_INFO(SCENE_FIRE_TEMPLE_BOSS), "Volvagia", "Fire Temple Blue Warp", ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_GROUP_DEATH_MOUNTAIN_CRATER, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
|
||||||
|
|
||||||
// Goron City
|
// Goron City
|
||||||
{ ENTR_DEATH_MOUNTAIN_TRAIL_1, ENTR_GORON_CITY_0, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City", "DMT", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD, "gc"},
|
{ ENTR_DEATH_MOUNTAIN_TRAIL_1, ENTR_GORON_CITY_0, SINGLE_SCENE_INFO(SCENE_GORON_CITY), "Goron City", "DMT", ENTRANCE_GROUP_GORON_CITY, ENTRANCE_GROUP_DEATH_MOUNTAIN_TRAIL, ENTRANCE_TYPE_OVERWORLD, "gc"},
|
||||||
@ -247,6 +252,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_ZORAS_FOUNTAIN_1, ENTR_JABU_JABU_0, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
|
{ ENTR_ZORAS_FOUNTAIN_1, ENTR_JABU_JABU_0, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
|
||||||
{ ENTR_JABU_JABU_BOSS_0, ENTR_JABU_JABU_1, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Boss Door", "Barinade", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_JABU_JABU_BOSS_0, ENTR_JABU_JABU_1, SINGLE_SCENE_INFO(SCENE_JABU_JABU), "Jabu Jabu's Belly Boss Door", "Barinade", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
{ ENTR_JABU_JABU_1, ENTR_JABU_JABU_BOSS_0, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Boss Door", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_JABU_JABU_1, ENTR_JABU_JABU_BOSS_0, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Boss Door", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
|
{ ENTR_ZORAS_FOUNTAIN_0, -1, SINGLE_SCENE_INFO(SCENE_JABU_JABU_BOSS), "Barinade", "Jabu Jabu's Belly Blue Warp", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
|
||||||
{ ENTR_ZORAS_FOUNTAIN_3, ENTR_ICE_CAVERN_0, SINGLE_SCENE_INFO(SCENE_ICE_CAVERN), "Ice Cavern", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
|
{ ENTR_ZORAS_FOUNTAIN_3, ENTR_ICE_CAVERN_0, SINGLE_SCENE_INFO(SCENE_ICE_CAVERN), "Ice Cavern", "ZF", ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_GROUP_ZORAS_FOUNTAIN, ENTRANCE_TYPE_DUNGEON},
|
||||||
|
|
||||||
// Hyrule Field
|
// Hyrule Field
|
||||||
@ -298,6 +304,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_LAKE_HYLIA_2, ENTR_WATER_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"},
|
{ ENTR_LAKE_HYLIA_2, ENTR_WATER_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple", "Lake Hylia", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh"},
|
||||||
{ ENTR_WATER_TEMPLE_BOSS_0, ENTR_WATER_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Boss Door", "Morpha", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
|
{ ENTR_WATER_TEMPLE_BOSS_0, ENTR_WATER_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE), "Water Temple Boss Door", "Morpha", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
|
||||||
{ ENTR_WATER_TEMPLE_1, ENTR_WATER_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Boss Door", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
|
{ ENTR_WATER_TEMPLE_1, ENTR_WATER_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Boss Door", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_DUNGEON, "lh", 1},
|
||||||
|
{ ENTR_LAKE_HYLIA_9, -1, SINGLE_SCENE_INFO(SCENE_WATER_TEMPLE_BOSS), "Morpha", "Water Temple Blue Warp", ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_GROUP_LAKE_HYLIA, ENTRANCE_TYPE_ONE_WAY, "lh,bw", 1},
|
||||||
|
|
||||||
// Gerudo Area
|
// Gerudo Area
|
||||||
{ ENTR_HYRULE_FIELD_5, ENTR_GERUDO_VALLEY_0, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV", "Hyrule Field", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
|
{ ENTR_HYRULE_FIELD_5, ENTR_GERUDO_VALLEY_0, SINGLE_SCENE_INFO(SCENE_GERUDO_VALLEY), "GV", "Hyrule Field", ENTRANCE_GROUP_GERUDO_VALLEY, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
|
||||||
@ -328,6 +335,7 @@ const EntranceData entranceData[] = {
|
|||||||
{ ENTR_DESERT_COLOSSUS_1, ENTR_SPIRIT_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple", "Desert Colossus", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc"},
|
{ ENTR_DESERT_COLOSSUS_1, ENTR_SPIRIT_TEMPLE_0, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple", "Desert Colossus", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "dc"},
|
||||||
{ ENTR_SPIRIT_TEMPLE_BOSS_0, ENTR_SPIRIT_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple Boss Door", "Twinrova", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_SPIRIT_TEMPLE_BOSS_0, ENTR_SPIRIT_TEMPLE_1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE), "Spirit Temple Boss Door", "Twinrova", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
{ ENTR_SPIRIT_TEMPLE_1, ENTR_SPIRIT_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Boss Door", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
|
{ ENTR_SPIRIT_TEMPLE_1, ENTR_SPIRIT_TEMPLE_BOSS_0, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Boss Door", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_DUNGEON, "", 1},
|
||||||
|
{ ENTR_DESERT_COLOSSUS_8, -1, SINGLE_SCENE_INFO(SCENE_SPIRIT_TEMPLE_BOSS), "Twinrova", "Spirit Temple Blue Warp", ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_GROUP_HAUNTED_WASTELAND, ENTRANCE_TYPE_ONE_WAY, "bw", 1},
|
||||||
|
|
||||||
// Market
|
// Market
|
||||||
{ ENTR_HYRULE_FIELD_7, ENTR_MARKET_ENTRANCE_DAY_1, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance", "Hyrule Field", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
|
{ ENTR_HYRULE_FIELD_7, ENTR_MARKET_ENTRANCE_DAY_1, {SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_DAY), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_NIGHT), SCENE_NO_SPAWN(SCENE_MARKET_ENTRANCE_RUINS)}, "Market Entrance", "Hyrule Field", ENTRANCE_GROUP_MARKET, ENTRANCE_GROUP_HYRULE_FIELD, ENTRANCE_TYPE_OVERWORLD, "hf"},
|
||||||
@ -797,6 +805,11 @@ void EntranceTrackerWindow::DrawElement() {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RANDOTODO: Only show blue warps if bluewarp shuffle is on
|
||||||
|
if (original->metaTag.ends_with("bw") || override->metaTag.ends_with("bw")) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
bool isDiscovered = IsEntranceDiscovered(entrance.index);
|
bool isDiscovered = IsEntranceDiscovered(entrance.index);
|
||||||
|
|
||||||
bool showOriginal = (!destToggle ? CVarGetInteger("gEntranceTrackerShowTo", 0) : CVarGetInteger("gEntranceTrackerShowFrom", 0)) || isDiscovered;
|
bool showOriginal = (!destToggle ? CVarGetInteger("gEntranceTrackerShowTo", 0) : CVarGetInteger("gEntranceTrackerShowFrom", 0)) || isDiscovered;
|
||||||
|
@ -184,9 +184,9 @@ void SaveManager::LoadRandomizerVersion2() {
|
|||||||
|
|
||||||
SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(gSaveContext.entranceOverrides), [&](size_t i) {
|
SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(gSaveContext.entranceOverrides), [&](size_t i) {
|
||||||
SaveManager::Instance->LoadStruct("", [&]() {
|
SaveManager::Instance->LoadStruct("", [&]() {
|
||||||
|
SaveManager::Instance->LoadData("type", gSaveContext.entranceOverrides[i].type);
|
||||||
SaveManager::Instance->LoadData("index", gSaveContext.entranceOverrides[i].index);
|
SaveManager::Instance->LoadData("index", gSaveContext.entranceOverrides[i].index);
|
||||||
SaveManager::Instance->LoadData("destination", gSaveContext.entranceOverrides[i].destination);
|
SaveManager::Instance->LoadData("destination", gSaveContext.entranceOverrides[i].destination);
|
||||||
SaveManager::Instance->LoadData("blueWarp", gSaveContext.entranceOverrides[i].blueWarp);
|
|
||||||
SaveManager::Instance->LoadData("override", gSaveContext.entranceOverrides[i].override);
|
SaveManager::Instance->LoadData("override", gSaveContext.entranceOverrides[i].override);
|
||||||
SaveManager::Instance->LoadData("overrideDestination", gSaveContext.entranceOverrides[i].overrideDestination);
|
SaveManager::Instance->LoadData("overrideDestination", gSaveContext.entranceOverrides[i].overrideDestination);
|
||||||
});
|
});
|
||||||
@ -292,9 +292,9 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
|
|||||||
|
|
||||||
SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(saveContext->entranceOverrides), [&](size_t i) {
|
SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(saveContext->entranceOverrides), [&](size_t i) {
|
||||||
SaveManager::Instance->SaveStruct("", [&]() {
|
SaveManager::Instance->SaveStruct("", [&]() {
|
||||||
|
SaveManager::Instance->SaveData("type", saveContext->entranceOverrides[i].type);
|
||||||
SaveManager::Instance->SaveData("index", saveContext->entranceOverrides[i].index);
|
SaveManager::Instance->SaveData("index", saveContext->entranceOverrides[i].index);
|
||||||
SaveManager::Instance->SaveData("destination", saveContext->entranceOverrides[i].destination);
|
SaveManager::Instance->SaveData("destination", saveContext->entranceOverrides[i].destination);
|
||||||
SaveManager::Instance->SaveData("blueWarp", saveContext->entranceOverrides[i].blueWarp);
|
|
||||||
SaveManager::Instance->SaveData("override", saveContext->entranceOverrides[i].override);
|
SaveManager::Instance->SaveData("override", saveContext->entranceOverrides[i].override);
|
||||||
SaveManager::Instance->SaveData("overrideDestination", saveContext->entranceOverrides[i].overrideDestination);
|
SaveManager::Instance->SaveData("overrideDestination", saveContext->entranceOverrides[i].overrideDestination);
|
||||||
});
|
});
|
||||||
|
@ -575,6 +575,13 @@ u32 func_80096FE8(PlayState* play, RoomContext* roomCtx) {
|
|||||||
|
|
||||||
frontRoom = gSaveContext.respawnFlag > 0 ? ((void)0, gSaveContext.respawn[gSaveContext.respawnFlag - 1].roomIndex)
|
frontRoom = gSaveContext.respawnFlag > 0 ? ((void)0, gSaveContext.respawn[gSaveContext.respawnFlag - 1].roomIndex)
|
||||||
: play->setupEntranceList[play->curSpawn].room;
|
: play->setupEntranceList[play->curSpawn].room;
|
||||||
|
|
||||||
|
// In ER, override roomNum to load based on scene and spawn during scene init
|
||||||
|
if (IS_RANDO && gSaveContext.respawnFlag <= 0 &&
|
||||||
|
Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
|
||||||
|
frontRoom = Entrance_OverrideSpawnSceneRoom(play->sceneNum, play->curSpawn, frontRoom);
|
||||||
|
}
|
||||||
|
|
||||||
func_8009728C(play, roomCtx, frontRoom);
|
func_8009728C(play, roomCtx, frontRoom);
|
||||||
|
|
||||||
return maxRoomSize;
|
return maxRoomSize;
|
||||||
@ -583,12 +590,6 @@ u32 func_80096FE8(PlayState* play, RoomContext* roomCtx) {
|
|||||||
s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum) {
|
s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum) {
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
// In ER, override roomNum to load based on scene and spawn
|
|
||||||
if (IS_RANDO && gSaveContext.respawnFlag <= 0 &&
|
|
||||||
Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES)) {
|
|
||||||
roomNum = Entrance_OverrideSpawnSceneRoom(play->sceneNum, play->curSpawn, roomNum);
|
|
||||||
}
|
|
||||||
|
|
||||||
return OTRfunc_8009728C(play, roomCtx, roomNum);
|
return OTRfunc_8009728C(play, roomCtx, roomNum);
|
||||||
|
|
||||||
if (roomCtx->status == 0) {
|
if (roomCtx->status == 0) {
|
||||||
|
@ -4538,7 +4538,9 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol
|
|||||||
|
|
||||||
Scene_SetTransitionForNextEntrance(play);
|
Scene_SetTransitionForNextEntrance(play);
|
||||||
} else {
|
} else {
|
||||||
if (SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2) {
|
// In Entrance rando, if our respawnFlag is set for a grotto return, we don't want the void out to happen
|
||||||
|
if (SurfaceType_GetSlope(&play->colCtx, poly, bgId) == 2 &&
|
||||||
|
(!IS_RANDO || (Randomizer_GetSettingValue(RSK_SHUFFLE_ENTRANCES) && gSaveContext.respawnFlag != 2))) {
|
||||||
gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = play->nextEntranceIndex;
|
gSaveContext.respawn[RESPAWN_MODE_DOWN].entranceIndex = play->nextEntranceIndex;
|
||||||
Play_TriggerVoidOut(play);
|
Play_TriggerVoidOut(play);
|
||||||
gSaveContext.respawnFlag = -2;
|
gSaveContext.respawnFlag = -2;
|
||||||
|
Loading…
Reference in New Issue
Block a user