mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-03-03 02:01:47 -05:00
Merge commit '13fce8258d92e80ea09900f83d338ccba2e7b1f9' into rando-dev-merge-feb
This commit is contained in:
commit
37b960ab0e
@ -324,7 +324,12 @@ std::vector<RandomizerCheck> GetAccessibleLocations(const std::vector<Randomizer
|
||||
}
|
||||
|
||||
// Add shuffled entrances to the entrance playthrough
|
||||
if (mode == SearchMode::GeneratePlaythrough && exit.IsShuffled() && !exit.IsAddedToPool() && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) {
|
||||
// Include bluewarps when unshuffled but dungeon or boss shuffle is on
|
||||
if (mode == SearchMode::GeneratePlaythrough &&
|
||||
(exit.IsShuffled() ||
|
||||
(exit.GetType() == Rando::EntranceType::BlueWarp &&
|
||||
(ctx->GetOption(RSK_SHUFFLE_DUNGEON_ENTRANCES) || ctx->GetOption(RSK_SHUFFLE_BOSS_ENTRANCES)))) &&
|
||||
!exit.IsAddedToPool() && !ctx->GetEntranceShuffler()->HasNoRandomEntrances()) {
|
||||
entranceSphere.push_back(&exit);
|
||||
exit.AddToPool();
|
||||
// Don't list a two-way coupled entrance from both directions
|
||||
|
@ -501,7 +501,7 @@ Area* AreaTable(const RandomizerRegion areaKey) {
|
||||
//Retrieve all the shuffable entrances of a specific type
|
||||
std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary /*= true*/) {
|
||||
std::vector<Rando::Entrance*> entrancesToShuffle = {};
|
||||
for (RandomizerRegion area : Areas::GetAllAreas()) {
|
||||
for (RandomizerRegion area : Areas::GetAllAreas()) {
|
||||
for (auto& exit: AreaTable(area)->exits) {
|
||||
if ((exit.GetType() == type || type == Rando::EntranceType::All) && (exit.IsPrimary() || !onlyPrimary) && exit.GetType() != Rando::EntranceType::None) {
|
||||
entrancesToShuffle.push_back(&exit);
|
||||
@ -510,3 +510,16 @@ std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type,
|
||||
}
|
||||
return entrancesToShuffle;
|
||||
}
|
||||
|
||||
// Get the specific entrance by name
|
||||
Rando::Entrance* GetEntrance(const std::string name) {
|
||||
for (RandomizerRegion area : Areas::GetAllAreas()) {
|
||||
for (auto& exit : AreaTable(area)->exits) {
|
||||
if (exit.GetName() == name) {
|
||||
return &exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -251,6 +251,7 @@ namespace Areas {
|
||||
void AreaTable_Init();
|
||||
Area* AreaTable(const RandomizerRegion areaKey);
|
||||
std::vector<Rando::Entrance*> GetShuffleableEntrances(Rando::EntranceType type, bool onlyPrimary = true);
|
||||
Rando::Entrance* GetEntrance(const std::string name);
|
||||
|
||||
// Overworld
|
||||
void AreaTable_Init_LostWoods();
|
||||
|
@ -270,5 +270,6 @@ void AreaTable_Init_DekuTree() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_DEKU_TREE_BOSS_ENTRYWAY, { [] { return true; } }),
|
||||
Entrance(RR_KF_OUTSIDE_DEKU_TREE, { [] { return logic->DekuTreeClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -307,5 +307,6 @@ void AreaTable_Init_DodongosCavern() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_DODONGOS_CAVERN_BOSS_ENTRYWAY, { [] { return true; } }),
|
||||
Entrance(RR_DEATH_MOUNTAIN_TRAIL, { [] { return logic->DodongosCavernClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -418,5 +418,6 @@ void AreaTable_Init_FireTemple() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_FIRE_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||
Entrance(RR_DMC_CENTRAL_LOCAL, { [] { return logic->FireTempleClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -431,5 +431,6 @@ void AreaTable_Init_ForestTemple() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_FOREST_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||
Entrance(RR_SACRED_FOREST_MEADOW, { [] { return logic->ForestTempleClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -177,17 +177,17 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
//Locations
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_LOWER_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_SECOND_ROOM_UPPER_CHEST, {[]{return (logic->IsAdult && (logic->CanUse(RG_HOVER_BOOTS) || logic->CanUse(RG_HOOKSHOT))) || ChildCanAccess(RR_JABU_JABUS_BELLY_MQ_BOSS_AREA);}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_COMPASS_CHEST, {[]{return (logic->IsChild || logic->CanDive || logic->CanUse(RG_IRON_BOOTS) || randoCtx->GetTrickOption(RT_JABU_ALCOVE_JUMP_DIVE)) && (logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_HOOKSHOT) || logic->HasBombchus || (randoCtx->GetTrickOption(RT_JABU_MQ_RANG_JUMP) && logic->CanUse(RG_BOOMERANG)));}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_VINES_CHEST, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BASEMENT_NEAR_SWITCHES_CHEST, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_ROOM_SMALL_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_BOOMERANG_CHEST, {[]{return logic->CanUse(RG_KOKIRI_SWORD) || logic->CanUse(RG_MASTER_SWORD) || logic->CanUse(RG_BIGGORON_SWORD) || logic->CanUse(RG_MEGATON_HAMMER) || logic->CanUse(RG_FAIRY_SLINGSHOT) || logic->CanUse(RG_FAIRY_BOW) || logic->CanUse(RG_STICKS) || logic->Bombs;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_BOOMERANG_CHEST_ROOM, {[]{return logic->CanUse(RG_SONG_OF_TIME) || (randoCtx->GetTrickOption(RT_JABU_MQ_SOT_GS) && logic->IsChild && logic->CanUse(RG_BOOMERANG));}}),
|
||||
//Trick: logic->CanUse(RG_SONG_OF_TIME) || (LogicJabuMQSoTGS && logic->IsChild && logic->CanUse(RG_BOOMERANG))
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_BEGINNING, {[]{return true;}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return logic->HasExplosives && logic->IsChild && logic->CanUse(RG_BOOMERANG);}}),
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_DEPTHS, {[]{return logic->HasExplosives && logic->CanUse(RG_FAIRY_SLINGSHOT) && logic->CanUse(RG_BOOMERANG);}}),
|
||||
});
|
||||
|
||||
areaTable[RR_JABU_JABUS_BELLY_MQ_DEPTHS] = Area("Jabu Jabus Belly MQ Depths", "Jabu Jabus Belly", RA_JABU_JABUS_BELLY, NO_DAY_NIGHT_CYCLE, {}, {
|
||||
@ -207,8 +207,8 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
}, {
|
||||
//Locations
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_COW, {[]{return logic->CanUse(RG_EPONAS_SONG);}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return true;}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_NEAR_BOSS_CHEST, {[]{return logic->CanUse(RG_FAIRY_SLINGSHOT);}}),
|
||||
LocationAccess(RC_JABU_JABUS_BELLY_MQ_GS_NEAR_BOSS, {[]{return logic->CanUse(RG_BOOMERANG) || (randoCtx->GetTrickOption(RT_JABU_NEAR_BOSS_RANGED) && logic->CanUse(RG_HOOKSHOT));}}),
|
||||
}, {
|
||||
//Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_MQ_MAIN, {[]{return true;}}),
|
||||
@ -243,5 +243,6 @@ void AreaTable_Init_JabuJabusBelly() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_JABU_JABUS_BELLY_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||
Entrance(RR_ZORAS_FOUNTAIN, { [] { return logic->JabuJabusBellyClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -207,5 +207,6 @@ void AreaTable_Init_ShadowTemple() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_SHADOW_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||
Entrance(RR_GRAVEYARD_WARP_PAD_REGION, { [] { return logic->ShadowTempleClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -269,5 +269,6 @@ void AreaTable_Init_SpiritTemple() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_SPIRIT_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||
Entrance(RR_DESERT_COLOSSUS, { [] { return logic->SpiritTempleClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -329,5 +329,6 @@ void AreaTable_Init_WaterTemple() {
|
||||
{
|
||||
// Exits
|
||||
Entrance(RR_WATER_TEMPLE_BOSS_ENTRYWAY, { [] { return false; } }),
|
||||
Entrance(RR_LAKE_HYLIA, { [] { return logic->WaterTempleClear; } }),
|
||||
});
|
||||
}
|
||||
|
@ -316,35 +316,36 @@ static void WriteLocation(
|
||||
static void WriteShuffledEntrance(std::string sphereString, Entrance* entrance) {
|
||||
int16_t originalIndex = entrance->GetIndex();
|
||||
int16_t destinationIndex = -1;
|
||||
int16_t originalBlueWarp = entrance->GetBlueWarp();
|
||||
int16_t replacementBlueWarp = -1;
|
||||
int16_t replacementIndex = entrance->GetReplacement()->GetIndex();
|
||||
int16_t replacementDestinationIndex = -1;
|
||||
std::string name = entrance->GetName();
|
||||
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();
|
||||
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||
replacementBlueWarp = entrance->GetReplacement()->GetReverse()->GetBlueWarp();
|
||||
// When decouple is off we track the replacement's reverse destination, useful for recording visited entrances
|
||||
if (!entrance->IsDecoupled()) {
|
||||
replacementDestinationIndex = entrance->GetReplacement()->GetReverse()->GetIndex();
|
||||
}
|
||||
}
|
||||
|
||||
json entranceJson = json::object({
|
||||
{"type", entrance->GetType()},
|
||||
{"index", originalIndex},
|
||||
{"destination", destinationIndex},
|
||||
{"blueWarp", originalBlueWarp},
|
||||
{"override", replacementIndex},
|
||||
{"overrideDestination", replacementDestinationIndex},
|
||||
});
|
||||
|
||||
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()) {
|
||||
json reverseEntranceJson = json::object({
|
||||
{"type", entrance->GetReverse()->GetType()},
|
||||
{"index", replacementDestinationIndex},
|
||||
{"destination", replacementIndex},
|
||||
{"blueWarp", replacementBlueWarp},
|
||||
{"override", destinationIndex},
|
||||
{"overrideDestination", originalIndex},
|
||||
});
|
||||
|
@ -3643,6 +3643,7 @@ typedef enum {
|
||||
RSK_SHUFFLE_OVERWORLD_SPAWNS,
|
||||
RSK_MIXED_ENTRANCE_POOLS,
|
||||
RSK_MIX_DUNGEON_ENTRANCES,
|
||||
RSK_MIX_BOSS_ENTRANCES,
|
||||
RSK_MIX_OVERWORLD_ENTRANCES,
|
||||
RSK_MIX_INTERIOR_ENTRANCES,
|
||||
RSK_MIX_GROTTO_ENTRANCES,
|
||||
|
@ -40,17 +40,12 @@ s16 dynamicExitList[] = {
|
||||
// Owl Flights : 0x492064 and 0x492080
|
||||
|
||||
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
|
||||
static s16 dungeonBossSceneOverrides[SHUFFLEABLE_BOSS_COUNT] = {0};
|
||||
// Boss scenes (normalize boss scene range to 0 on lookup) mapped to save/death warp entrance
|
||||
static s16 bossSceneSaveDeathWarps[SHUFFLEABLE_BOSS_COUNT] = {0};
|
||||
static ActorEntry modifiedLinkActorEntry = {0};
|
||||
|
||||
EntranceInfo originalEntranceTable[ENTRANCE_TABLE_SIZE] = {0};
|
||||
|
||||
typedef struct {
|
||||
s16 blueWarp;
|
||||
s16 destination;
|
||||
} BlueWarpReplacement;
|
||||
|
||||
typedef struct {
|
||||
s16 entryway;
|
||||
s16 exit;
|
||||
@ -62,40 +57,25 @@ typedef struct {
|
||||
} DungeonEntranceInfo;
|
||||
|
||||
static DungeonEntranceInfo dungeons[] = {
|
||||
//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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
//entryway exit, boss, reverse, bluewarp, dungeon scene, boss scene
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 },
|
||||
{ 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 hasModifiedEntranceTable = 0;
|
||||
|
||||
void Entrance_SetEntranceDiscovered(u16 entranceIndex, u8 isReversedEntrance);
|
||||
|
||||
u8 Entrance_EntranceIsNull(EntranceOverride* entranceOverride) {
|
||||
return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->blueWarp == 0
|
||||
&& entranceOverride->override == 0 && entranceOverride->overrideDestination == 0;
|
||||
return entranceOverride->index == 0 && entranceOverride->destination == 0 && entranceOverride->override == 0 &&
|
||||
entranceOverride->overrideDestination == 0;
|
||||
}
|
||||
|
||||
static void Entrance_SeparateOGCFairyFountainExit(void) {
|
||||
@ -114,6 +94,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) {
|
||||
if (!hasCopiedEntranceTable) {
|
||||
memcpy(originalEntranceTable, gEntranceTable, sizeof(EntranceInfo) * ENTRANCE_TABLE_SIZE);
|
||||
@ -132,9 +134,6 @@ void Entrance_Init(void) {
|
||||
EntranceOverride* entranceOverrides = Randomizer_GetEntranceOverrides();
|
||||
s32 index;
|
||||
|
||||
size_t blueWarpRemapIdx = 0;
|
||||
BlueWarpReplacement bluewarps[SHUFFLEABLE_BOSS_COUNT] = {0};
|
||||
|
||||
Entrance_CopyOriginalEntranceTable();
|
||||
|
||||
// Skip Child Stealth if given by settings
|
||||
@ -151,6 +150,7 @@ void Entrance_Init(void) {
|
||||
|
||||
Entrance_SeparateOGCFairyFountainExit();
|
||||
Entrance_SeparateAdultSpawnAndPrelude();
|
||||
Entrance_ReplaceChildTempleWarps();
|
||||
|
||||
// Initialize the entrance override table with each index leading to itself. An
|
||||
// index referring to itself means that the entrance is not currently shuffled.
|
||||
@ -158,9 +158,9 @@ void Entrance_Init(void) {
|
||||
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++) {
|
||||
dungeonBossSceneOverrides[i] = i;
|
||||
bossSceneSaveDeathWarps[i] = dungeons[i].entryway;
|
||||
}
|
||||
|
||||
// Initialize the grotto exit and load lists
|
||||
@ -174,9 +174,30 @@ void Entrance_Init(void) {
|
||||
}
|
||||
|
||||
s16 originalIndex = entranceOverrides[i].index;
|
||||
s16 blueWarpIndex = entranceOverrides[i].blueWarp;
|
||||
s16 originalDestination = entranceOverrides[i].destination;
|
||||
s16 overrideIndex = 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
|
||||
if (originalIndex >= ENTRANCE_RANDO_GROTTO_EXIT_START) {
|
||||
Grotto_SetExitOverride(originalIndex, overrideIndex);
|
||||
@ -191,36 +212,6 @@ void Entrance_Init(void) {
|
||||
// Overwrite the indices which we want to shuffle, leaving the rest as they are
|
||||
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
|
||||
if (originalIndex == ENTR_ZORAS_RIVER_0) { //Hyrule Field -> ZR Front land entrance
|
||||
entranceOverrideTable[ENTR_ZORAS_RIVER_3] = overrideIndex;
|
||||
@ -229,14 +220,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
|
||||
// so that we don't get duplicated or overlapping music tracks
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES)) {
|
||||
@ -330,40 +313,39 @@ void Entrance_SetGameOverEntrance(void) {
|
||||
|
||||
s16 scene = gPlayState->sceneNum;
|
||||
|
||||
// When in a boss room and boss shuffle is on, get the connected dungeon's original boss room entrance
|
||||
// then run the normal game over overrides on it
|
||||
// When in a boss room and boss shuffle is on, use the boss scene to find the death warp entrance
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF &&
|
||||
scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) {
|
||||
// Normalize boss scene range to 0 on lookup
|
||||
scene = dungeonBossSceneOverrides[scene - SCENE_DEKU_TREE_BOSS];
|
||||
gSaveContext.entranceIndex = dungeons[scene].bossDoor;
|
||||
// Normalize boss scene range to 0 on lookup and handle for grotto entrances
|
||||
gSaveContext.entranceIndex = Grotto_OverrideSpecialEntrance(bossSceneSaveDeathWarps[scene - SCENE_DEKU_TREE_BOSS]);
|
||||
return;
|
||||
}
|
||||
|
||||
//Set the current entrance depending on which entrance the player last came through
|
||||
switch (gSaveContext.entranceIndex) {
|
||||
case ENTR_DEKU_TREE_BOSS_0 : //Deku Tree Boss Room
|
||||
gSaveContext.entranceIndex = newDekuTreeEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_DEKU_TREE_0;
|
||||
return;
|
||||
case ENTR_DODONGOS_CAVERN_BOSS_0 : //Dodongos Cavern Boss Room
|
||||
gSaveContext.entranceIndex = newDodongosCavernEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0;
|
||||
return;
|
||||
case ENTR_JABU_JABU_BOSS_0 : //Jabu Jabus Belly Boss Room
|
||||
gSaveContext.entranceIndex = newJabuJabusBellyEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_JABU_JABU_0;
|
||||
return;
|
||||
case ENTR_FOREST_TEMPLE_BOSS_0 : //Forest Temple Boss Room
|
||||
gSaveContext.entranceIndex = newForestTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0;
|
||||
return;
|
||||
case ENTR_FIRE_TEMPLE_BOSS_0 : //Fire Temple Boss Room
|
||||
gSaveContext.entranceIndex = newFireTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_FIRE_TEMPLE_0;
|
||||
return;
|
||||
case ENTR_WATER_TEMPLE_BOSS_0 : //Water Temple Boss Room
|
||||
gSaveContext.entranceIndex = newWaterTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0;
|
||||
return;
|
||||
case ENTR_SPIRIT_TEMPLE_BOSS_0 : //Spirit Temple Boss Room
|
||||
gSaveContext.entranceIndex = newSpiritTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_SPIRIT_TEMPLE_0;
|
||||
return;
|
||||
case ENTR_SHADOW_TEMPLE_BOSS_0 : //Shadow Temple Boss Room
|
||||
gSaveContext.entranceIndex = newShadowTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0;
|
||||
return;
|
||||
case ENTR_GANONDORF_BOSS_0 : //Ganondorf Boss Room
|
||||
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb
|
||||
@ -376,46 +358,46 @@ void Entrance_SetSavewarpEntrance(void) {
|
||||
|
||||
s16 scene = gSaveContext.savedSceneNum;
|
||||
|
||||
// When in a boss room and boss shuffle is on, use the boss scene override to remap to its
|
||||
// connected dungeon and use that for the final entrance
|
||||
// When in a boss room and boss shuffle is on, use the boss scene to find the savewarp entrance
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_BOSS_ENTRANCES) != RO_BOSS_ROOM_ENTRANCE_SHUFFLE_OFF &&
|
||||
scene >= SCENE_DEKU_TREE_BOSS && scene <= SCENE_SHADOW_TEMPLE_BOSS) {
|
||||
// Normalize boss scene range to 0 on lookup
|
||||
scene = dungeonBossSceneOverrides[scene - SCENE_DEKU_TREE_BOSS];
|
||||
// Normalize boss scene range to 0 on lookup and handle for grotto entrances
|
||||
gSaveContext.entranceIndex = Grotto_OverrideSpecialEntrance(bossSceneSaveDeathWarps[scene - SCENE_DEKU_TREE_BOSS]);
|
||||
return;
|
||||
}
|
||||
|
||||
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) {
|
||||
gSaveContext.entranceIndex = newDodongosCavernEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_DODONGOS_CAVERN_0;
|
||||
} 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
|
||||
gSaveContext.entranceIndex = newForestTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_FOREST_TEMPLE_0;
|
||||
} 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
|
||||
gSaveContext.entranceIndex = newWaterTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_WATER_TEMPLE_0;
|
||||
} 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
|
||||
gSaveContext.entranceIndex = newShadowTempleEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_SHADOW_TEMPLE_0;
|
||||
} 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
|
||||
gSaveContext.entranceIndex = newGerudoTrainingGroundsEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_GERUDO_TRAINING_GROUND_0;
|
||||
} else if (scene == SCENE_ICE_CAVERN) { // Ice cavern
|
||||
gSaveContext.entranceIndex = newIceCavernEntrance;
|
||||
gSaveContext.entranceIndex = ENTR_ICE_CAVERN_0;
|
||||
} 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) {
|
||||
gSaveContext.entranceIndex = ENTR_GANONS_TOWER_0; // Inside Ganon's Castle -> Ganon's Tower Climb
|
||||
} else if (scene == SCENE_THIEVES_HIDEOUT) { // Theives hideout
|
||||
gSaveContext.entranceIndex = ENTR_THIEVES_HIDEOUT_0; // Gerudo Fortress -> Thieve's Hideout spawn 0
|
||||
} 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) {
|
||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(LINK_HOUSE_SAVEWARP_ENTRANCE); // Child Overworld Spawn
|
||||
gSaveContext.entranceIndex = Entrance_OverrideNextIndex(ENTR_LINKS_HOUSE_0); // Child Overworld Spawn
|
||||
} 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)
|
||||
}
|
||||
@ -496,7 +478,7 @@ void Entrance_OverrideBlueWarp(void) {
|
||||
void Entrance_OverrideCutsceneEntrance(u16 cutsceneCmd) {
|
||||
switch (cutsceneCmd) {
|
||||
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->transitionType = TRANS_TYPE_FADE_BLACK;
|
||||
// In case Jabu's mouth leads to a grotto return
|
||||
|
@ -8,20 +8,6 @@
|
||||
|
||||
#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_EXIT_START 0x0800
|
||||
#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_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 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))
|
||||
|
||||
typedef struct {
|
||||
uint16_t type;
|
||||
int16_t index;
|
||||
int16_t destination;
|
||||
int16_t blueWarp;
|
||||
int16_t override;
|
||||
int16_t overrideDestination;
|
||||
} EntranceOverride;
|
||||
|
@ -105,6 +105,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_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_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
|
||||
{ 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"},
|
||||
@ -132,6 +133,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_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_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
|
||||
{ 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"},
|
||||
@ -180,6 +182,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_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_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
|
||||
{ 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"},
|
||||
@ -195,6 +198,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_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_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
|
||||
{ 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"},
|
||||
@ -209,6 +213,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_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_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
|
||||
{ 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"},
|
||||
@ -248,6 +253,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_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_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},
|
||||
|
||||
// Hyrule Field
|
||||
@ -299,6 +305,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_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_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
|
||||
{ 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"},
|
||||
@ -329,6 +336,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_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_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
|
||||
{ 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"},
|
||||
@ -800,6 +808,11 @@ void EntranceTrackerWindow::DrawElement() {
|
||||
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 showOriginal = (!destToggle ? CVarGetInteger("gEntranceTrackerShowTo", 0) : CVarGetInteger("gEntranceTrackerShowFrom", 0)) || isDiscovered;
|
||||
|
@ -210,9 +210,9 @@ void SaveManager::LoadRandomizerVersion2() {
|
||||
auto entranceCtx = randoContext->GetEntranceShuffler();
|
||||
SaveManager::Instance->LoadArray("entrances", ARRAY_COUNT(entranceCtx->entranceOverrides), [&](size_t i) {
|
||||
SaveManager::Instance->LoadStruct("", [&]() {
|
||||
SaveManager::Instance->LoadData("type", entranceCtx->entranceOverrides[i].type);
|
||||
SaveManager::Instance->LoadData("index", entranceCtx->entranceOverrides[i].index);
|
||||
SaveManager::Instance->LoadData("destination", entranceCtx->entranceOverrides[i].destination);
|
||||
SaveManager::Instance->LoadData("blueWarp", entranceCtx->entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->LoadData("override", entranceCtx->entranceOverrides[i].override);
|
||||
SaveManager::Instance->LoadData("overrideDestination", entranceCtx->entranceOverrides[i].overrideDestination);
|
||||
});
|
||||
@ -455,9 +455,9 @@ void SaveManager::SaveRandomizer(SaveContext* saveContext, int sectionID, bool f
|
||||
auto entranceCtx = randoContext->GetEntranceShuffler();
|
||||
SaveManager::Instance->SaveArray("entrances", ARRAY_COUNT(entranceCtx->entranceOverrides), [&](size_t i) {
|
||||
SaveManager::Instance->SaveStruct("", [&]() {
|
||||
SaveManager::Instance->SaveData("type", entranceCtx->entranceOverrides[i].type);
|
||||
SaveManager::Instance->SaveData("index", entranceCtx->entranceOverrides[i].index);
|
||||
SaveManager::Instance->SaveData("destination", entranceCtx->entranceOverrides[i].destination);
|
||||
SaveManager::Instance->SaveData("blueWarp", entranceCtx->entranceOverrides[i].blueWarp);
|
||||
SaveManager::Instance->SaveData("override", entranceCtx->entranceOverrides[i].override);
|
||||
SaveManager::Instance->SaveData("overrideDestination", entranceCtx->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)
|
||||
: 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);
|
||||
|
||||
return maxRoomSize;
|
||||
@ -583,12 +590,6 @@ u32 func_80096FE8(PlayState* play, RoomContext* roomCtx) {
|
||||
s32 func_8009728C(PlayState* play, RoomContext* roomCtx, s32 roomNum) {
|
||||
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);
|
||||
|
||||
if (roomCtx->status == 0) {
|
||||
|
@ -4539,7 +4539,9 @@ s32 Player_HandleExitsAndVoids(PlayState* play, Player* this, CollisionPoly* pol
|
||||
|
||||
Scene_SetTransitionForNextEntrance(play);
|
||||
} 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;
|
||||
Play_TriggerVoidOut(play);
|
||||
gSaveContext.respawnFlag = -2;
|
||||
|
Loading…
x
Reference in New Issue
Block a user